functions and pc values.
Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
- 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 Free Software
+ 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software
Foundation, Inc.
This file is part of GDB.
#include "regcache.h"
#include "gdb_assert.h"
#include "dummy-frame.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "block.h"
/* Prototypes for exported functions. */
void _initialize_blockframe (void);
-/* A default FRAME_CHAIN_VALID, in the form that is suitable for most
- targets. If FRAME_CHAIN_VALID returns zero it means that the given
- frame is the outermost one and has no caller. */
-
-int
-file_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
-{
- return ((chain) != 0
- && !inside_entry_file (frame_pc_unwind (thisframe)));
-}
-
-/* Use the alternate method of avoiding running up off the end of the
- frame chain or following frames back into the startup code. See
- the comments in objfiles.h. */
-
-int
-func_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
-{
- return ((chain) != 0
- && !inside_main_func ((thisframe)->pc)
- && !inside_entry_func ((thisframe)->pc));
-}
-
-/* A very simple method of determining a valid frame */
-
-int
-nonnull_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe)
-{
- return ((chain) != 0);
-}
-
-/* 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
- to call this function from FRAME_CHAIN_VALID; the reason for
- doing so is that some machines have no way of detecting bottom
- of stack.
+/* 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 to call
+ this function from DEPRECATED_FRAME_CHAIN_VALID; the reason for
+ doing so is that some machines have no way of detecting bottom of
+ stack.
A PC of zero is always considered to be the bottom of the stack. */
int
-inside_entry_file (CORE_ADDR addr)
+deprecated_inside_entry_file (CORE_ADDR addr)
{
if (addr == 0)
return 1;
if (symfile_objfile == 0)
return 0;
- if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT)
+ if (CALL_DUMMY_LOCATION == AT_ENTRY_POINT
+ || CALL_DUMMY_LOCATION == AT_SYMBOL)
{
/* Do not stop backtracing if the pc is in the call dummy
at the entry point. */
/* FIXME: Won't always work with zeros for the last two arguments */
- if (PC_IN_CALL_DUMMY (addr, 0, 0))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (addr, 0, 0))
return 0;
}
- return (addr >= symfile_objfile->ei.entry_file_lowpc &&
- addr < symfile_objfile->ei.entry_file_highpc);
+ return (addr >= symfile_objfile->ei.deprecated_entry_file_lowpc &&
+ addr < symfile_objfile->ei.deprecated_entry_file_highpc);
}
/* Test a specified PC value to see if it is in the range of addresses
that correspond to the main() function. See comments above for why
we might want to do this.
- Typically called from FRAME_CHAIN_VALID.
+ Typically called from DEPRECATED_FRAME_CHAIN_VALID.
A PC of zero is always considered to be the bottom of the stack. */
if (symfile_objfile == 0)
return 0;
- /* If the addr range is not set up at symbol reading time, set it up now.
- This is for FRAME_CHAIN_VALID_ALTERNATE. I do this for coff, because
- it is unable to set it up and symbol reading time. */
+ /* If the addr range is not set up at symbol reading time, set it up
+ now. This is for DEPRECATED_FRAME_CHAIN_VALID_ALTERNATE. I do
+ this for coff, because it is unable to set it up and symbol
+ reading time. */
if (symfile_objfile->ei.main_func_lowpc == INVALID_ENTRY_LOWPC &&
symfile_objfile->ei.main_func_highpc == INVALID_ENTRY_HIGHPC)
{
struct symbol *mainsym;
- mainsym = lookup_symbol (main_name (), NULL, VAR_NAMESPACE, NULL, NULL);
+ mainsym = lookup_symbol (main_name (), NULL, VAR_DOMAIN, NULL, NULL);
if (mainsym && SYMBOL_CLASS (mainsym) == LOC_BLOCK)
{
symfile_objfile->ei.main_func_lowpc =
BLOCK_END (SYMBOL_BLOCK_VALUE (mainsym));
}
}
+
+ /* Not in the normal symbol tables, see if "main" is in the partial
+ symbol table. If it's not, then give up. */
+ {
+ struct minimal_symbol *msymbol
+ = lookup_minimal_symbol (main_name (), NULL, symfile_objfile);
+ if (msymbol != NULL && MSYMBOL_TYPE (msymbol) == mst_text)
+ {
+ struct obj_section *osect
+ = find_pc_sect_section (SYMBOL_VALUE_ADDRESS (msymbol),
+ msymbol->ginfo.bfd_section);
+ if (osect != NULL)
+ {
+ int i;
+ /* Step over other symbols at this same address, and
+ symbols in other sections, to find the next symbol in
+ this section with a different address. */
+ for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++)
+ {
+ if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol)
+ && SYMBOL_BFD_SECTION (msymbol + i) == SYMBOL_BFD_SECTION (msymbol))
+ break;
+ }
+
+ symfile_objfile->ei.main_func_lowpc = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ /* Use the lesser of the next minimal symbol in the same
+ section, or the end of the section, as the end of the
+ function. */
+ if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL
+ && SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
+ symfile_objfile->ei.main_func_highpc = SYMBOL_VALUE_ADDRESS (msymbol + i);
+ else
+ /* We got the start address from the last msymbol in the
+ objfile. So the end address is the end of the
+ section. */
+ symfile_objfile->ei.main_func_highpc = osect->endaddr;
+ }
+ }
+ }
+
return (symfile_objfile->ei.main_func_lowpc <= pc &&
symfile_objfile->ei.main_func_highpc > pc);
}
that correspond to the process entry point function. See comments
in objfiles.h for why we might want to do this.
- Typically called from FRAME_CHAIN_VALID.
+ Typically called from DEPRECATED_FRAME_CHAIN_VALID.
A PC of zero is always considered to be the bottom of the stack. */
/* Do not stop backtracing if the pc is in the call dummy
at the entry point. */
/* FIXME: Won't always work with zeros for the last two arguments */
- if (PC_IN_CALL_DUMMY (pc, 0, 0))
+ if (DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0))
return 0;
}
return (symfile_objfile->ei.entry_func_lowpc <= pc &&
int
frameless_look_for_prologue (struct frame_info *frame)
{
- CORE_ADDR func_start, after_prologue;
+ CORE_ADDR func_start;
- func_start = get_pc_function_start (frame->pc);
+ func_start = get_frame_func (frame);
if (func_start)
{
func_start += FUNCTION_START_OFFSET;
prologue, not how long it is. */
return PROLOGUE_FRAMELESS_P (func_start);
}
- else if (frame->pc == 0)
+ else if (get_frame_pc (frame) == 0)
/* A frame with a zero PC is usually created by dereferencing a
NULL function pointer, normally causing an immediate core dump
of the inferior. Mark function as frameless, as the inferior
return 0;
}
-/* return the address of the PC for the given FRAME, ie the current PC value
- if FRAME is the innermost frame, or the address adjusted to point to the
- call instruction if not. */
-
-CORE_ADDR
-frame_address_in_block (struct frame_info *frame)
-{
- CORE_ADDR pc = frame->pc;
-
- /* If we are not in the innermost frame, and we are not interrupted
- by a signal, frame->pc points to the instruction following the
- call. As a consequence, we need to get the address of the previous
- instruction. Unfortunately, this is not straightforward to do, so
- we just use the address minus one, which is a good enough
- approximation. */
- if (frame->next != 0 && frame->next->signal_handler_caller == 0)
- --pc;
-
- return pc;
-}
-
/* Return the innermost lexical block in execution
in a specified stack frame. The frame address is assumed valid.
struct block *
get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block)
{
- const CORE_ADDR pc = frame_address_in_block (frame);
-
- if (addr_in_block)
- *addr_in_block = pc;
-
- return block_for_pc (pc);
-}
-
-struct block *
-get_current_block (CORE_ADDR *addr_in_block)
-{
- CORE_ADDR pc = read_pc ();
+ const CORE_ADDR pc = get_frame_address_in_block (frame);
if (addr_in_block)
*addr_in_block = pc;
CORE_ADDR
get_pc_function_start (CORE_ADDR pc)
{
- register struct block *bl;
- register struct symbol *symbol;
- register struct minimal_symbol *msymbol;
- CORE_ADDR fstart;
+ struct block *bl;
+ struct minimal_symbol *msymbol;
- if ((bl = block_for_pc (pc)) != NULL &&
- (symbol = block_function (bl)) != NULL)
- {
- bl = SYMBOL_BLOCK_VALUE (symbol);
- fstart = BLOCK_START (bl);
- }
- else if ((msymbol = lookup_minimal_symbol_by_pc (pc)) != NULL)
+ bl = block_for_pc (pc);
+ if (bl)
{
- fstart = SYMBOL_VALUE_ADDRESS (msymbol);
- if (!find_pc_section (fstart))
- return 0;
+ struct symbol *symbol = block_function (bl);
+
+ if (symbol)
+ {
+ bl = SYMBOL_BLOCK_VALUE (symbol);
+ return BLOCK_START (bl);
+ }
}
- else
+
+ msymbol = lookup_minimal_symbol_by_pc (pc);
+ if (msymbol)
{
- fstart = 0;
+ CORE_ADDR fstart = SYMBOL_VALUE_ADDRESS (msymbol);
+
+ if (find_pc_section (fstart))
+ return fstart;
}
- return (fstart);
+
+ return 0;
}
/* Return the symbol for the function executing in frame FRAME. */
struct symbol *
get_frame_function (struct frame_info *frame)
{
- register struct block *bl = get_frame_block (frame, 0);
+ struct block *bl = get_frame_block (frame, 0);
if (bl == 0)
return 0;
return block_function (bl);
}
\f
-/* Return the blockvector immediately containing the innermost lexical block
- containing the specified pc value and section, or 0 if there is none.
- PINDEX is a pointer to the index value of the block. If PINDEX
- is NULL, we don't pass this information back to the caller. */
-
-struct blockvector *
-blockvector_for_pc_sect (register CORE_ADDR pc, struct sec *section,
- int *pindex, struct symtab *symtab)
-{
- register struct block *b;
- register int bot, top, half;
- struct blockvector *bl;
-
- if (symtab == 0) /* if no symtab specified by caller */
- {
- /* First search all symtabs for one whose file contains our pc */
- if ((symtab = find_pc_sect_symtab (pc, section)) == 0)
- return 0;
- }
-
- bl = BLOCKVECTOR (symtab);
- b = BLOCKVECTOR_BLOCK (bl, 0);
-
- /* Then search that symtab for the smallest block that wins. */
- /* Use binary search to find the last block that starts before PC. */
-
- bot = 0;
- top = BLOCKVECTOR_NBLOCKS (bl);
-
- while (top - bot > 1)
- {
- half = (top - bot + 1) >> 1;
- b = BLOCKVECTOR_BLOCK (bl, bot + half);
- if (BLOCK_START (b) <= pc)
- bot += half;
- else
- top = bot + half;
- }
-
- /* Now search backward for a block that ends after PC. */
-
- while (bot >= 0)
- {
- b = BLOCKVECTOR_BLOCK (bl, bot);
- if (BLOCK_END (b) > pc)
- {
- if (pindex)
- *pindex = bot;
- return bl;
- }
- bot--;
- }
- return 0;
-}
-
-/* Return the blockvector immediately containing the innermost lexical block
- containing the specified pc value, or 0 if there is none.
- Backward compatibility, no section. */
-
-struct blockvector *
-blockvector_for_pc (register CORE_ADDR pc, int *pindex)
-{
- return blockvector_for_pc_sect (pc, find_pc_mapped_section (pc),
- pindex, NULL);
-}
-
-/* Return the innermost lexical block containing the specified pc value
- in the specified section, or 0 if there is none. */
-
-struct block *
-block_for_pc_sect (register CORE_ADDR pc, struct sec *section)
-{
- register struct blockvector *bl;
- int index;
-
- bl = blockvector_for_pc_sect (pc, section, &index, NULL);
- if (bl)
- return BLOCKVECTOR_BLOCK (bl, index);
- return 0;
-}
-
-/* Return the innermost lexical block containing the specified pc value,
- or 0 if there is none. Backward compatibility, no section. */
-
-struct block *
-block_for_pc (register CORE_ADDR pc)
-{
- return block_for_pc_sect (pc, find_pc_mapped_section (pc));
-}
-
/* Return the function containing pc value PC in section SECTION.
Returns 0 if function is not known. */
struct symbol *
find_pc_sect_function (CORE_ADDR pc, struct sec *section)
{
- register struct block *b = block_for_pc_sect (pc, section);
+ struct block *b = block_for_pc_sect (pc, section);
if (b == 0)
return 0;
return block_function (b);
{
cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
- cache_pc_function_name = SYMBOL_NAME (f);
+ cache_pc_function_name = DEPRECATED_SYMBOL_NAME (f);
cache_pc_function_section = section;
goto return_cached_value;
}
if (address)
*address = SYMBOL_VALUE_ADDRESS (psb);
if (name)
- *name = SYMBOL_NAME (psb);
+ *name = DEPRECATED_SYMBOL_NAME (psb);
/* endaddr non-NULL can't happen here. */
return 1;
}
}
cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
- cache_pc_function_name = SYMBOL_NAME (msymbol);
+ cache_pc_function_name = DEPRECATED_SYMBOL_NAME (msymbol);
cache_pc_function_section = section;
/* Use the lesser of the next minimal symbol in the same section, or
other sections, to find the next symbol in this section with
a different address. */
- for (i = 1; SYMBOL_NAME (msymbol + i) != NULL; i++)
+ for (i = 1; DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL; i++)
{
if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol)
&& SYMBOL_BFD_SECTION (msymbol + i) == SYMBOL_BFD_SECTION (msymbol))
break;
}
- if (SYMBOL_NAME (msymbol + i) != NULL
+ if (DEPRECATED_SYMBOL_NAME (msymbol + i) != NULL
&& SYMBOL_VALUE_ADDRESS (msymbol + i) < osect->endaddr)
cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i);
else
block_innermost_frame (struct block *block)
{
struct frame_info *frame;
- register CORE_ADDR start;
- register CORE_ADDR end;
+ CORE_ADDR start;
+ CORE_ADDR end;
CORE_ADDR calling_pc;
if (block == NULL)
frame = get_prev_frame (frame);
if (frame == NULL)
return NULL;
- calling_pc = frame_address_in_block (frame);
+ calling_pc = get_frame_address_in_block (frame);
if (calling_pc >= start && calling_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 (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;
- }
-}
-
-#ifdef SIGCONTEXT_PC_OFFSET
-/* Get saved user PC for sigtramp from sigcontext for BSD style sigtramp. */
-
-CORE_ADDR
-sigtramp_saved_pc (struct frame_info *frame)
-{
- CORE_ADDR sigcontext_addr;
- char *buf;
- int ptrbytes = TYPE_LENGTH (builtin_type_void_func_ptr);
- int sigcontext_offs = (2 * TARGET_INT_BIT) / TARGET_CHAR_BIT;
-
- buf = alloca (ptrbytes);
- /* Get sigcontext address, it is the third parameter on the stack. */
- if (frame->next)
- sigcontext_addr = read_memory_typed_address
- (FRAME_ARGS_ADDRESS (frame->next) + FRAME_ARGS_SKIP + sigcontext_offs,
- builtin_type_void_data_ptr);
- else
- sigcontext_addr = read_memory_typed_address
- (read_register (SP_REGNUM) + sigcontext_offs, builtin_type_void_data_ptr);
-
- /* Don't cause a memory_error when accessing sigcontext in case the stack
- layout has changed or the stack is corrupt. */
- target_read_memory (sigcontext_addr + SIGCONTEXT_PC_OFFSET, buf, ptrbytes);
- return extract_typed_address (buf, builtin_type_void_func_ptr);
-}
-#endif /* SIGCONTEXT_PC_OFFSET */
-
-
/* Are we in a call dummy? The code below which allows DECR_PC_AFTER_BREAK
below is for infrun.c, which may give the macro a pc without that
subtracted out. */
-extern CORE_ADDR text_end;
-
-int
-pc_in_call_dummy_before_text_end (CORE_ADDR pc, CORE_ADDR sp,
- CORE_ADDR frame_address)
-{
- return ((pc) >= text_end - CALL_DUMMY_LENGTH
- && (pc) <= text_end + DECR_PC_AFTER_BREAK);
-}
-
-int
-pc_in_call_dummy_after_text_end (CORE_ADDR pc, CORE_ADDR sp,
- CORE_ADDR frame_address)
-{
- return ((pc) >= text_end
- && (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK);
-}
-
/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and
top of the stack frame which we are checking, where "bottom" and
"top" refer to some section of memory which contains the code for
the call dummy. Calls to this macro assume that the contents of
- SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively,
- are the things to pass.
+ SP_REGNUM and DEPRECATED_FP_REGNUM (or the saved values thereof),
+ respectively, are the things to pass.
- This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't
- have that meaning, but the 29k doesn't use ON_STACK. This could be
- fixed by generalizing this scheme, perhaps by passing in a frame
- and adding a few fields, at least on machines which need them for
- PC_IN_CALL_DUMMY.
+ This won't work on the 29k, where SP_REGNUM and
+ DEPRECATED_FP_REGNUM don't have that meaning, but the 29k doesn't
+ use ON_STACK. This could be fixed by generalizing this scheme,
+ perhaps by passing in a frame and adding a few fields, at least on
+ machines which need them for DEPRECATED_PC_IN_CALL_DUMMY.
Something simpler, like checking for the stack segment, doesn't work,
since various programs (threads implementations, gcc nested function
allocate other kinds of code on the stack. */
int
-pc_in_call_dummy_on_stack (CORE_ADDR pc, CORE_ADDR sp, CORE_ADDR frame_address)
+deprecated_pc_in_call_dummy_on_stack (CORE_ADDR pc, CORE_ADDR sp,
+ CORE_ADDR frame_address)
{
return (INNER_THAN ((sp), (pc))
&& (frame_address != 0)
}
int
-pc_in_call_dummy_at_entry_point (CORE_ADDR pc, CORE_ADDR sp,
- CORE_ADDR frame_address)
+deprecated_pc_in_call_dummy_at_entry_point (CORE_ADDR pc, CORE_ADDR sp,
+ CORE_ADDR frame_address)
{
- return ((pc) >= CALL_DUMMY_ADDRESS ()
- && (pc) <= (CALL_DUMMY_ADDRESS () + DECR_PC_AFTER_BREAK));
+ CORE_ADDR addr = entry_point_address ();
+ if (DEPRECATED_CALL_DUMMY_ADDRESS_P ())
+ addr = DEPRECATED_CALL_DUMMY_ADDRESS ();
+ return ((pc) >= addr && (pc) <= (addr + DECR_PC_AFTER_BREAK));
}
-
-/* Function: frame_chain_valid
- Returns true for a user frame or a call_function_by_hand dummy frame,
- and false for the CRT0 start-up frame. Purpose is to terminate backtrace */
+/* Returns true for a user frame or a call_function_by_hand dummy
+ frame, and false for the CRT0 start-up frame. Purpose is to
+ terminate backtrace. */
int
-generic_file_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
+legacy_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
{
- if (PC_IN_CALL_DUMMY (frame_pc_unwind (fi), fp, fp))
- return 1; /* don't prune CALL_DUMMY frames */
- else /* fall back to default algorithm (see frame.h) */
- return (fp != 0
- && (INNER_THAN (fi->frame, fp) || fi->frame == fp)
- && !inside_entry_file (frame_pc_unwind (fi)));
-}
+ /* Don't prune CALL_DUMMY frames. */
+ if (DEPRECATED_USE_GENERIC_DUMMY_FRAMES
+ && DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fi), 0, 0))
+ return 1;
-int
-generic_func_frame_chain_valid (CORE_ADDR fp, struct frame_info *fi)
-{
- if (USE_GENERIC_DUMMY_FRAMES
- && PC_IN_CALL_DUMMY ((fi)->pc, 0, 0))
- return 1; /* don't prune CALL_DUMMY frames */
- else /* fall back to default algorithm (see frame.h) */
- return (fp != 0
- && (INNER_THAN (fi->frame, fp) || fi->frame == fp)
- && !inside_main_func ((fi)->pc)
- && !inside_entry_func ((fi)->pc));
-}
+ /* If the new frame pointer is zero, then it isn't valid. */
+ if (fp == 0)
+ return 0;
+
+ /* If the new frame would be inside (younger than) the previous frame,
+ then it isn't valid. */
+ if (INNER_THAN (fp, get_frame_base (fi)))
+ return 0;
+
+ /* If the architecture has a custom DEPRECATED_FRAME_CHAIN_VALID,
+ call it now. */
+ if (DEPRECATED_FRAME_CHAIN_VALID_P ())
+ return DEPRECATED_FRAME_CHAIN_VALID (fp, fi);
+
+ /* If we're already inside the entry function for the main objfile, then it
+ isn't valid. */
+ if (inside_entry_func (get_frame_pc (fi)))
+ return 0;
+ /* If we're inside the entry file, it isn't valid. */
+ /* NOTE/drow 2002-12-25: should there be a way to disable this check? It
+ assumes a single small entry file, and the way some debug readers (e.g.
+ dbxread) figure out which object is the entry file is somewhat hokey. */
+ if (deprecated_inside_entry_file (frame_pc_unwind (fi)))
+ return 0;
+
+ return 1;
+}