/* Get info from stack frames;
convert between frames, blocks, functions and pc values.
- Copyright 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1988, 1989, 1991, 1994 Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "symtab.h"
#include "value.h" /* for read_register */
#include "target.h" /* for target_has_stack */
#include "inferior.h" /* for read_pc */
+#include "annotate.h"
/* Is ADDR inside the startup file? Note that if your machine
has a way to detect the bottom of the stack, there is no need
inside_main_func (pc)
CORE_ADDR pc;
{
+struct symbol *mainsym;
if (pc == 0)
return 1;
if (symfile_objfile == 0)
return 0;
+
+ if (symfile_objfile -> ei.main_func_lowpc == 0 &&
+ symfile_objfile -> ei.main_func_highpc == 0)
+ {
+ mainsym = lookup_symbol ("main", NULL, VAR_NAMESPACE, NULL, NULL);
+ if (mainsym && SYMBOL_CLASS(mainsym) == LOC_BLOCK)
+ {
+ symfile_objfile->ei.main_func_lowpc = BLOCK_START (SYMBOL_BLOCK_VALUE (mainsym));
+ symfile_objfile->ei.main_func_highpc = BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
+ }
+
+ }
return (symfile_objfile -> ei.main_func_lowpc <= pc &&
symfile_objfile -> ei.main_func_highpc > pc);
}
symfile_objfile -> ei.entry_func_highpc > pc);
}
-/* Address of innermost stack frame (contents of FP register) */
+/* Info about the innermost stack frame (contents of FP register) */
-static FRAME current_frame;
+static struct frame_info *current_frame;
+
+/* Cache for frame addresses already read by gdb. Valid only while
+ inferior is stopped. Control variables for the frame cache should
+ be local to this module. */
-/*
- * Cache for frame addresses already read by gdb. Valid only while
- * inferior is stopped. Control variables for the frame cache should
- * be local to this module.
- */
struct obstack frame_cache_obstack;
/* Return the innermost (currently executing) stack frame. */
-FRAME
+struct frame_info *
get_current_frame ()
{
- /* We assume its address is kept in a general register;
- param.h says which register. */
-
+ if (current_frame == NULL)
+ {
+ if (target_has_stack)
+ current_frame = create_new_frame (read_fp (), read_pc ());
+ else
+ error ("No stack.");
+ }
return current_frame;
}
void
set_current_frame (frame)
- FRAME frame;
+ struct frame_info *frame;
{
current_frame = frame;
}
-FRAME
+/* Create an arbitrary (i.e. address specified by user) or innermost frame.
+ Always returns a non-NULL value. */
+
+struct frame_info *
create_new_frame (addr, pc)
- FRAME_ADDR addr;
+ CORE_ADDR addr;
CORE_ADDR pc;
{
- struct frame_info *fci; /* Same type as FRAME */
+ struct frame_info *fi;
char *name;
- fci = (struct frame_info *)
+ fi = (struct frame_info *)
obstack_alloc (&frame_cache_obstack,
sizeof (struct frame_info));
/* Arbitrary frame */
- fci->next = (struct frame_info *) 0;
- fci->prev = (struct frame_info *) 0;
- fci->frame = addr;
- fci->pc = pc;
+ fi->next = NULL;
+ fi->prev = NULL;
+ fi->frame = addr;
+ fi->pc = pc;
find_pc_partial_function (pc, &name, (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
- fci->signal_handler_caller = IN_SIGTRAMP (fci->pc, name);
+ fi->signal_handler_caller = IN_SIGTRAMP (fi->pc, name);
#ifdef INIT_EXTRA_FRAME_INFO
- INIT_EXTRA_FRAME_INFO (0, fci);
+ INIT_EXTRA_FRAME_INFO (0, fi);
#endif
- return fci;
+ return fi;
}
-/* Return the frame that called FRAME.
- If FRAME is the original frame (it has no caller), return 0. */
+/* Return the frame that called FI.
+ If FI is the original frame (it has no caller), return 0. */
-FRAME
+struct frame_info *
get_prev_frame (frame)
- FRAME frame;
+ struct frame_info *frame;
{
- /* We're allowed to know that FRAME and "struct frame_info *" are
- the same */
return get_prev_frame_info (frame);
}
-/* Return the frame that FRAME calls (0 if FRAME is the innermost
+/* Return the frame that FRAME calls (NULL if FRAME is the innermost
frame). */
-FRAME
+struct frame_info *
get_next_frame (frame)
- FRAME frame;
+ struct frame_info *frame;
{
- /* We're allowed to know that FRAME and "struct frame_info *" are
- the same */
return frame->next;
}
-/*
- * Flush the entire frame cache.
- */
+/* Flush the entire frame cache. */
+
void
flush_cached_frames ()
{
obstack_free (&frame_cache_obstack, 0);
obstack_init (&frame_cache_obstack);
- current_frame = (struct frame_info *) 0; /* Invalidate cache */
+ current_frame = NULL; /* Invalidate cache */
+ select_frame (NULL, -1);
+ annotate_frames_invalid ();
}
/* Flush the frame cache, and start a new one if necessary. */
+
void
reinit_frame_cache ()
{
flush_cached_frames ();
- if (target_has_stack)
+
+ /* FIXME: The inferior_pid test is wrong if there is a corefile. */
+ if (inferior_pid != 0)
{
- set_current_frame (create_new_frame (read_fp (), read_pc ()));
select_frame (get_current_frame (), 0);
}
- else
- {
- set_current_frame (0);
- select_frame ((FRAME) 0, -1);
- }
-}
-
-/* Return a structure containing various interesting information
- about a specified stack frame. */
-/* How do I justify including this function? Well, the FRAME
- identifier format has gone through several changes recently, and
- it's not completely inconceivable that it could happen again. If
- it does, have this routine around will help */
-
-struct frame_info *
-get_frame_info (frame)
- FRAME frame;
-{
- return frame;
}
/* If a machine allows frameless functions, it should define a macro
int
frameless_look_for_prologue (frame)
- FRAME frame;
+ struct frame_info *frame;
{
CORE_ADDR func_start, after_prologue;
- func_start = (get_pc_function_start (frame->pc) +
- FUNCTION_START_OFFSET);
+ func_start = (get_pc_function_start (frame->pc) + FUNCTION_START_OFFSET);
if (func_start)
{
after_prologue = func_start;
struct frame_info *
get_prev_frame_info (next_frame)
- FRAME next_frame;
+ struct frame_info *next_frame;
{
- FRAME_ADDR address = 0;
+ CORE_ADDR address = 0;
struct frame_info *prev;
int fromleaf = 0;
char *name;
{
FRAMELESS_FUNCTION_INVOCATION (next_frame, fromleaf);
if (fromleaf)
- address = next_frame->frame;
+ address = FRAME_FP (next_frame);
}
#endif
We shouldn't need INIT_FRAME_PC_FIRST to add more complication to
an already overcomplicated part of GDB. gnu@cygnus.com, 15Sep92.
- To answer the question, yes the sparc needs INIT_FRAME_PC after
- INIT_EXTRA_FRAME_INFO. Suggested scheme:
+ Assuming that some machines need INIT_FRAME_PC after
+ INIT_EXTRA_FRAME_INFO, one possible scheme:
SETUP_INNERMOST_FRAME()
Default version is just create_new_frame (read_fp ()),
the default INIT_FRAME_PC does. Some machines will call it from
INIT_PREV_FRAME (either at the beginning, the end, or in the middle).
Some machines won't use it.
- kingdon@cygnus.com, 13Apr93, 31Jan94. */
+ kingdon@cygnus.com, 13Apr93, 31Jan94, 14Dec94. */
#ifdef INIT_FRAME_PC_FIRST
INIT_FRAME_PC_FIRST (fromleaf, prev);
CORE_ADDR
get_frame_pc (frame)
- FRAME frame;
+ struct frame_info *frame;
{
- struct frame_info *fi;
- fi = get_frame_info (frame);
- return fi->pc;
+ return frame->pc;
}
#if defined (FRAME_FIND_SAVED_REGS)
/* Find the addresses in which registers are saved in FRAME. */
void
-get_frame_saved_regs (frame_info_addr, saved_regs_addr)
- struct frame_info *frame_info_addr;
+get_frame_saved_regs (frame, saved_regs_addr)
+ struct frame_info *frame;
struct frame_saved_regs *saved_regs_addr;
{
- FRAME_FIND_SAVED_REGS (frame_info_addr, *saved_regs_addr);
+ FRAME_FIND_SAVED_REGS (frame, *saved_regs_addr);
}
#endif
struct block *
get_frame_block (frame)
- FRAME frame;
+ struct frame_info *frame;
{
- struct frame_info *fi;
CORE_ADDR pc;
- fi = get_frame_info (frame);
-
- pc = fi->pc;
- if (fi->next != 0 && fi->next->signal_handler_caller == 0)
+ pc = frame->pc;
+ if (frame->next != 0 && frame->next->signal_handler_caller == 0)
/* We are not in the innermost frame and we were not interrupted
by a signal. We need to subtract one to get the correct block,
in case the call instruction was the last instruction of the block.
If there are any machines on which the saved pc does not point to
- after the call insn, we probably want to make fi->pc point after
+ after the call insn, we probably want to make frame->pc point after
the call insn anyway. */
--pc;
return block_for_pc (pc);
struct symbol *
get_frame_function (frame)
- FRAME frame;
+ struct frame_info *frame;
{
register struct block *bl = get_frame_block (frame);
if (bl == 0)
return 0;
}
- /* See if we're in a transfer table for Sun shared libs. */
+ /* See if we're in a transfer table for Sun shared libs.
+
+ Note the hack for Sun shared library transfer tables creates
+ problems for single stepping through the return path from a shared
+ library call if the return path includes trampoline code.
+
+ I don't really understand the reasoning behind the magic handling
+ for mst_trampoline symbols. */
+#ifdef INHIBIT_SUNSOLIB_TRANSFER_TABLE_HACK
+ cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
+#else
if (msymbol -> type == mst_text || msymbol -> type == mst_file_text)
cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
else
/* It is a transfer table for Sun shared libraries. */
cache_pc_function_low = pc - FUNCTION_START_OFFSET;
+#endif
cache_pc_function_name = SYMBOL_NAME (msymbol);
/* Return the innermost stack frame executing inside of BLOCK,
or NULL if there is no such frame. If BLOCK is NULL, just return NULL. */
-FRAME
+struct frame_info *
block_innermost_frame (block)
struct block *block;
{
- struct frame_info *fi;
- register FRAME frame;
+ struct frame_info *frame;
register CORE_ADDR start;
register CORE_ADDR end;
start = BLOCK_START (block);
end = BLOCK_END (block);
- frame = 0;
+ frame = NULL;
while (1)
{
frame = get_prev_frame (frame);
- if (frame == 0)
- return 0;
- fi = get_frame_info (frame);
- if (fi->pc >= start && fi->pc < end)
+ if (frame == NULL)
+ return NULL;
+ if (frame->pc >= start && frame->pc < end)
+ return frame;
+ }
+}
+
+/* Return the full FRAME which corresponds to the given CORE_ADDR
+ or NULL if no FRAME on the chain corresponds to CORE_ADDR. */
+
+struct frame_info *
+find_frame_addr_in_frame_chain (frame_addr)
+ CORE_ADDR frame_addr;
+{
+ struct frame_info *frame = NULL;
+
+ if (frame_addr == (CORE_ADDR)0)
+ return NULL;
+
+ while (1)
+ {
+ frame = get_prev_frame (frame);
+ if (frame == NULL)
+ return NULL;
+ if (FRAME_FP (frame) == frame_addr)
return frame;
}
}
CORE_ADDR
sigtramp_saved_pc (frame)
- FRAME frame;
+ struct frame_info *frame;
{
CORE_ADDR sigcontext_addr;
char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
/* Get sigcontext address, it is the third parameter on the stack. */
if (frame->next)
sigcontext_addr = read_memory_integer (FRAME_ARGS_ADDRESS (frame->next)
- + FRAME_ARGS_SKIP + sigcontext_offs,
+ + FRAME_ARGS_SKIP
+ + sigcontext_offs,
ptrbytes);
else
sigcontext_addr = read_memory_integer (read_register (SP_REGNUM)