* frame.h, blockframe.c, stack.c, a29k-tdep.c,
config/gould/tmp-{pn,np1}.h, config/{sparc/tm-sparc.h,pyr/tm-pyr.h,vax/tm-vax.h}: Remove field next_frame from struct frame_info. It has no purpose beyond ->next->frame and is an artifact from GDB 2.8.
This commit is contained in:
parent
e154ecf4ab
commit
23a8e2915c
@ -1,3 +1,15 @@
|
||||
Wed Jul 7 14:30:00 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
|
||||
|
||||
* config/{rs6000/tm-rs6000.h,sparc/tm-sparc.h,pyr/tm-pyr.h},
|
||||
inferior.h (PC_IN_CALL_DUMMY) [ON_STACK]: Add comments about stack
|
||||
frame tops and bottoms.
|
||||
|
||||
* frame.h, blockframe.c, stack.c, a29k-tdep.c,
|
||||
config/gould/tmp-{pn,np1}.h,
|
||||
config/{sparc/tm-sparc.h,pyr/tm-pyr.h,vax/tm-vax.h}: Remove field
|
||||
next_frame from struct frame_info. It has no purpose beyond
|
||||
->next->frame and is an artifact from GDB 2.8.
|
||||
|
||||
Tue Jul 6 11:51:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
|
||||
|
||||
* Makefile.in: Remove gdb before creating a new one.
|
||||
|
@ -377,7 +377,7 @@ init_frame_info (innermost_frame, fci)
|
||||
if (innermost_frame)
|
||||
fci->frame = read_register (GR1_REGNUM);
|
||||
else
|
||||
fci->frame = fci->next_frame + fci->next->rsize;
|
||||
fci->frame = fci->next->frame + fci->next->rsize;
|
||||
|
||||
#if CALL_DUMMY_LOCATION == ON_STACK
|
||||
This wont work;
|
||||
|
272
gdb/blockframe.c
272
gdb/blockframe.c
@ -1,6 +1,6 @@
|
||||
/* Get info from stack frames;
|
||||
convert between frames, blocks, functions and pc values.
|
||||
Copyright (C) 1986, 1987, 1988, 1989 Free Software Foundation, Inc.
|
||||
Copyright 1986, 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
@ -18,111 +18,75 @@ 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. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defs.h"
|
||||
#include "param.h"
|
||||
#include "symtab.h"
|
||||
#include "bfd.h"
|
||||
#include "symfile.h"
|
||||
#include "objfiles.h"
|
||||
#include "frame.h"
|
||||
#include "gdbcore.h"
|
||||
#include "value.h" /* for read_register */
|
||||
#include "target.h" /* for target_has_stack */
|
||||
#include "inferior.h" /* for read_pc */
|
||||
|
||||
CORE_ADDR read_pc (); /* In infcmd.c */
|
||||
|
||||
/* Start and end of object file containing the entry point.
|
||||
STARTUP_FILE_END is the first address of the next file.
|
||||
This file is assumed to be a startup file
|
||||
and frames with pc's inside it
|
||||
are treated as nonexistent.
|
||||
|
||||
Setting these variables is necessary so that backtraces do not fly off
|
||||
the bottom of the stack. */
|
||||
CORE_ADDR startup_file_start;
|
||||
CORE_ADDR startup_file_end;
|
||||
|
||||
/* Is ADDR outside the startup file? Note that if your machine
|
||||
/* 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. */
|
||||
of stack.
|
||||
|
||||
A PC of zero is always considered to be the bottom of the stack. */
|
||||
|
||||
int
|
||||
outside_startup_file (addr)
|
||||
inside_entry_file (addr)
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
return !(addr >= startup_file_start && addr < startup_file_end);
|
||||
if (addr == 0)
|
||||
return 1;
|
||||
if (symfile_objfile == 0)
|
||||
return 0;
|
||||
return (addr >= symfile_objfile -> ei.entry_file_lowpc &&
|
||||
addr < symfile_objfile -> ei.entry_file_highpc);
|
||||
}
|
||||
|
||||
/* Support an alternate method to avoid running off the bottom of
|
||||
the stack (or top, depending upon your stack orientation).
|
||||
|
||||
There are two frames that are "special", the frame for the function
|
||||
containing the process entry point, since it has no predecessor frame,
|
||||
and the frame for the function containing the user code entry point
|
||||
(the main() function), since all the predecessor frames are for the
|
||||
process startup code. Since we have no guarantee that the linked
|
||||
in startup modules have any debugging information that gdb can use,
|
||||
we need to avoid following frame pointers back into frames that might
|
||||
have been built in the startup code, as we might get hopelessly
|
||||
confused. However, we almost always have debugging information
|
||||
available for main().
|
||||
|
||||
These variables are used to save the range of PC values which are valid
|
||||
within the main() function and within the function containing the process
|
||||
entry point. If we always consider the frame for main() as the outermost
|
||||
frame when debugging user code, and the frame for the process entry
|
||||
point function as the outermost frame when debugging startup code, then
|
||||
all we have to do is have FRAME_CHAIN_VALID return false whenever a
|
||||
frame's current PC is within the range specified by these variables.
|
||||
In essence, we set "blocks" in the frame chain beyond which we will
|
||||
not proceed when following the frame chain.
|
||||
|
||||
A nice side effect is that we can still debug startup code without
|
||||
running off the end of the frame chain, assuming that we have usable
|
||||
debugging information in the startup modules, and if we choose to not
|
||||
use the block at main, or can't find it for some reason, everything
|
||||
still works as before. And if we have no startup code debugging
|
||||
information but we do have usable information for main(), backtraces
|
||||
from user code don't go wandering off into the startup code.
|
||||
|
||||
To use this method, define your FRAME_CHAIN_VALID macro like:
|
||||
|
||||
#define FRAME_CHAIN_VALID(chain, thisframe) \
|
||||
(chain != 0 \
|
||||
&& !(inside_main_scope ((thisframe)->pc)) \
|
||||
&& !(inside_entry_scope ((thisframe)->pc)))
|
||||
|
||||
and add initializations of the four scope controlling variables inside
|
||||
the object file / debugging information processing modules. */
|
||||
|
||||
CORE_ADDR entry_scope_lowpc;
|
||||
CORE_ADDR entry_scope_highpc;
|
||||
CORE_ADDR main_scope_lowpc;
|
||||
CORE_ADDR main_scope_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 FRAME_CHAIN_VALID.
|
||||
|
||||
A PC of zero is always considered to be the bottom of the stack. */
|
||||
|
||||
int
|
||||
inside_main_scope (pc)
|
||||
inside_main_func (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
return (main_scope_lowpc <= pc && pc < main_scope_highpc);
|
||||
if (pc == 0)
|
||||
return 1;
|
||||
if (symfile_objfile == 0)
|
||||
return 0;
|
||||
return (symfile_objfile -> ei.main_func_lowpc <= pc &&
|
||||
symfile_objfile -> ei.main_func_highpc > pc);
|
||||
}
|
||||
|
||||
/* Test a specified PC value to see if it is in the range of addresses
|
||||
that correspond to the process entry point function. See comments above
|
||||
for why we might want to do this.
|
||||
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 FRAME_CHAIN_VALID.
|
||||
|
||||
A PC of zero is always considered to be the bottom of the stack. */
|
||||
|
||||
int
|
||||
inside_entry_scope (pc)
|
||||
inside_entry_func (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
return (entry_scope_lowpc <= pc && pc < entry_scope_highpc);
|
||||
if (pc == 0)
|
||||
return 1;
|
||||
if (symfile_objfile == 0)
|
||||
return 0;
|
||||
return (symfile_objfile -> ei.entry_func_lowpc <= pc &&
|
||||
symfile_objfile -> ei.entry_func_highpc > pc);
|
||||
}
|
||||
|
||||
/* Address of innermost stack frame (contents of FP register) */
|
||||
@ -169,8 +133,8 @@ create_new_frame (addr, pc)
|
||||
fci->next = (struct frame_info *) 0;
|
||||
fci->prev = (struct frame_info *) 0;
|
||||
fci->frame = addr;
|
||||
fci->next_frame = 0; /* Since arbitrary */
|
||||
fci->pc = pc;
|
||||
fci->signal_handler_caller = IN_SIGTRAMP (fci->pc, (char *)NULL);
|
||||
|
||||
#ifdef INIT_EXTRA_FRAME_INFO
|
||||
INIT_EXTRA_FRAME_INFO (0, fci);
|
||||
@ -223,8 +187,7 @@ reinit_frame_cache ()
|
||||
FRAME fr = current_frame;
|
||||
flush_cached_frames ();
|
||||
if (fr)
|
||||
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
|
||||
read_pc ()));
|
||||
set_current_frame ( create_new_frame (read_fp (), read_pc ()));
|
||||
}
|
||||
|
||||
/* Return a structure containing various interesting information
|
||||
@ -246,7 +209,7 @@ get_frame_info (frame)
|
||||
frame_info for the frame, and FRAMELESS should be set to nonzero
|
||||
if it represents a frameless function invocation. */
|
||||
|
||||
/* Return nonzero if the function for this frame has a prologue. Many
|
||||
/* Return nonzero if the function for this frame lacks a prologue. Many
|
||||
machines can define FRAMELESS_FUNCTION_INVOCATION to just call this
|
||||
function. */
|
||||
|
||||
@ -368,7 +331,47 @@ get_prev_frame_info (next_frame)
|
||||
prev->next = next_frame;
|
||||
prev->prev = (struct frame_info *) 0;
|
||||
prev->frame = address;
|
||||
prev->next_frame = prev->next ? prev->next->frame : 0;
|
||||
prev->signal_handler_caller = 0;
|
||||
|
||||
/* This change should not be needed, FIXME! We should
|
||||
determine whether any targets *need* INIT_FRAME_PC to happen
|
||||
after INIT_EXTRA_FRAME_INFO and come up with a simple way to
|
||||
express what goes on here.
|
||||
|
||||
INIT_EXTRA_FRAME_INFO is called from two places: create_new_frame
|
||||
(where the PC is already set up) and here (where it isn't).
|
||||
INIT_FRAME_PC is only called from here, always after
|
||||
INIT_EXTRA_FRAME_INFO.
|
||||
|
||||
The catch is the MIPS, where INIT_EXTRA_FRAME_INFO requires the PC
|
||||
value (which hasn't been set yet). Some other machines appear to
|
||||
require INIT_EXTRA_FRAME_INFO before they can do INIT_FRAME_PC. Phoo.
|
||||
|
||||
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:
|
||||
|
||||
SETUP_INNERMOST_FRAME()
|
||||
Default version is just create_new_frame (read_fp ()),
|
||||
read_pc ()). Machines with extra frame info would do that (or the
|
||||
local equivalent) and then set the extra fields.
|
||||
SETUP_ARBITRARY_FRAME(argc, argv)
|
||||
Only change here is that create_new_frame would no longer init extra
|
||||
frame info; SETUP_ARBITRARY_FRAME would have to do that.
|
||||
INIT_PREV_FRAME(fromleaf, prev)
|
||||
Replace INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC.
|
||||
std_frame_pc(fromleaf, prev)
|
||||
This is the default setting for INIT_PREV_FRAME. It just does what
|
||||
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. */
|
||||
|
||||
#ifdef INIT_FRAME_PC_FIRST
|
||||
INIT_FRAME_PC_FIRST (fromleaf, prev);
|
||||
#endif
|
||||
|
||||
#ifdef INIT_EXTRA_FRAME_INFO
|
||||
INIT_EXTRA_FRAME_INFO(fromleaf, prev);
|
||||
@ -379,6 +382,9 @@ get_prev_frame_info (next_frame)
|
||||
(see tm-sparc.h). We want the pc saved in the inferior frame. */
|
||||
INIT_FRAME_PC(fromleaf, prev);
|
||||
|
||||
if (IN_SIGTRAMP (prev->pc, (char *)NULL))
|
||||
prev->signal_handler_caller = 1;
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
@ -416,7 +422,7 @@ get_frame_block (frame)
|
||||
fi = get_frame_info (frame);
|
||||
|
||||
pc = fi->pc;
|
||||
if (fi->next_frame != 0)
|
||||
if (fi->next != 0)
|
||||
/* We are not in the innermost frame. 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
|
||||
@ -436,17 +442,26 @@ CORE_ADDR
|
||||
get_pc_function_start (pc)
|
||||
CORE_ADDR pc;
|
||||
{
|
||||
register struct block *bl = block_for_pc (pc);
|
||||
register struct block *bl;
|
||||
register struct symbol *symbol;
|
||||
if (bl == 0 || (symbol = block_function (bl)) == 0)
|
||||
register struct minimal_symbol *msymbol;
|
||||
CORE_ADDR fstart;
|
||||
|
||||
if ((bl = block_for_pc (pc)) != NULL &&
|
||||
(symbol = block_function (bl)) != NULL)
|
||||
{
|
||||
register int misc_index = find_pc_misc_function (pc);
|
||||
if (misc_index >= 0)
|
||||
return misc_function_vector[misc_index].address;
|
||||
return 0;
|
||||
bl = SYMBOL_BLOCK_VALUE (symbol);
|
||||
fstart = BLOCK_START (bl);
|
||||
}
|
||||
bl = SYMBOL_BLOCK_VALUE (symbol);
|
||||
return BLOCK_START (bl);
|
||||
else if ((msymbol = lookup_minimal_symbol_by_pc (pc)) != NULL)
|
||||
{
|
||||
fstart = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||
}
|
||||
else
|
||||
{
|
||||
fstart = 0;
|
||||
}
|
||||
return (fstart);
|
||||
}
|
||||
|
||||
/* Return the symbol for the function executing in frame FRAME. */
|
||||
@ -578,7 +593,7 @@ find_pc_partial_function (pc, name, address)
|
||||
{
|
||||
struct partial_symtab *pst;
|
||||
struct symbol *f;
|
||||
int miscfunc;
|
||||
struct minimal_symbol *msymbol;
|
||||
struct partial_symbol *psb;
|
||||
|
||||
if (pc >= cache_pc_function_low && pc < cache_pc_function_high)
|
||||
@ -621,19 +636,18 @@ find_pc_partial_function (pc, name, address)
|
||||
}
|
||||
|
||||
/* Get the information from a combination of the pst
|
||||
(static symbols), and the misc function vector (extern
|
||||
(static symbols), and the minimal symbol table (extern
|
||||
symbols). */
|
||||
miscfunc = find_pc_misc_function (pc);
|
||||
msymbol = lookup_minimal_symbol_by_pc (pc);
|
||||
psb = find_pc_psymbol (pst, pc);
|
||||
|
||||
if (!psb && miscfunc == -1)
|
||||
if (!psb && (msymbol == NULL))
|
||||
{
|
||||
goto return_error;
|
||||
}
|
||||
if (psb
|
||||
&& (miscfunc == -1
|
||||
|| (SYMBOL_VALUE_ADDRESS (psb)
|
||||
>= misc_function_vector[miscfunc].address)))
|
||||
&& (msymbol == NULL ||
|
||||
(SYMBOL_VALUE_ADDRESS (psb) >= SYMBOL_VALUE_ADDRESS (msymbol))))
|
||||
{
|
||||
/* This case isn't being cached currently. */
|
||||
if (address)
|
||||
@ -644,23 +658,25 @@ find_pc_partial_function (pc, name, address)
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Must be in the misc function stuff. */
|
||||
/* Must be in the minimal symbol table. */
|
||||
{
|
||||
miscfunc = find_pc_misc_function (pc);
|
||||
if (miscfunc == -1)
|
||||
msymbol = lookup_minimal_symbol_by_pc (pc);
|
||||
if (msymbol == NULL)
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
{
|
||||
if (misc_function_vector[miscfunc].type == mf_text)
|
||||
cache_pc_function_low = misc_function_vector[miscfunc].address;
|
||||
if (msymbol -> type == mst_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;
|
||||
}
|
||||
cache_pc_function_name = misc_function_vector[miscfunc].name;
|
||||
if (miscfunc < misc_function_count /* && FIXME mf_text again? */ )
|
||||
cache_pc_function_high = misc_function_vector[miscfunc+1].address;
|
||||
cache_pc_function_name = SYMBOL_NAME (msymbol);
|
||||
/* FIXME: Deal with bumping into end of minimal symbols for a given
|
||||
objfile, and what about testing for mst_text again? */
|
||||
if (SYMBOL_NAME (msymbol + 1) != NULL)
|
||||
cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + 1);
|
||||
else
|
||||
cache_pc_function_high = cache_pc_function_low + 1;
|
||||
if (address)
|
||||
@ -670,53 +686,11 @@ find_pc_partial_function (pc, name, address)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Find the misc function whose address is the largest
|
||||
while being less than PC. Return its index in misc_function_vector.
|
||||
Returns -1 if PC is not in suitable range. */
|
||||
|
||||
int
|
||||
find_pc_misc_function (pc)
|
||||
register CORE_ADDR pc;
|
||||
{
|
||||
register int lo = 0;
|
||||
register int hi = misc_function_count-1;
|
||||
register int new;
|
||||
|
||||
/* Note that the last thing in the vector is always _etext. */
|
||||
/* Actually, "end", now that non-functions
|
||||
go on the misc_function_vector. */
|
||||
|
||||
/* Above statement is not *always* true - fix for case where there are */
|
||||
/* no misc functions at all (ie no symbol table has been read). */
|
||||
if (hi < 0) return -1; /* no misc functions recorded */
|
||||
|
||||
/* trivial reject range test */
|
||||
if (pc < misc_function_vector[0].address ||
|
||||
pc > misc_function_vector[hi].address)
|
||||
return -1;
|
||||
|
||||
/* Note that the following search will not return hi if
|
||||
pc == misc_function_vector[hi].address. If "end" points to the
|
||||
first unused location, this is correct and the above test
|
||||
simply needs to be changed to
|
||||
"pc >= misc_function_vector[hi].address". */
|
||||
do {
|
||||
new = (lo + hi) >> 1;
|
||||
if (misc_function_vector[new].address == pc)
|
||||
return new; /* an exact match */
|
||||
else if (misc_function_vector[new].address > pc)
|
||||
hi = new;
|
||||
else
|
||||
lo = new;
|
||||
} while (hi-lo != 1);
|
||||
|
||||
/* if here, we had no exact match, so return the lower choice */
|
||||
return lo;
|
||||
}
|
||||
|
||||
/* Return the innermost stack frame executing inside of the specified block,
|
||||
or zero if there is no such frame. */
|
||||
|
||||
#if 0 /* Currently unused */
|
||||
|
||||
FRAME
|
||||
block_innermost_frame (block)
|
||||
struct block *block;
|
||||
@ -738,6 +712,8 @@ block_innermost_frame (block)
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
void
|
||||
_initialize_blockframe ()
|
||||
{
|
||||
|
@ -18,21 +18,10 @@ 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. */
|
||||
|
||||
extern int symtab_relocated;
|
||||
|
||||
/* Minimum possible text address in AIX */
|
||||
|
||||
#define TEXT_SEGMENT_BASE 0x10000000
|
||||
|
||||
|
||||
/* text addresses in a core file does not necessarily match to symbol table,
|
||||
if symbol table relocation wasn't done yet. */
|
||||
|
||||
#define CORE_NEEDS_RELOCATION(PC) \
|
||||
if (!symtab_relocated && !inferior_pid) \
|
||||
xcoff_relocate_core ();
|
||||
extern void xcoff_relocate_core PARAMS ((void));
|
||||
|
||||
/* Load segment of a given pc value. */
|
||||
|
||||
#define PC_LOAD_SEGMENT(PC) pc_load_segment_name(PC)
|
||||
@ -42,20 +31,16 @@ extern void xcoff_relocate_core PARAMS ((void));
|
||||
#define BELIEVE_PCC_PROMOTION 1
|
||||
|
||||
/* return true if a given `pc' value is in `call dummy' function. */
|
||||
|
||||
/* FIXME: This just checks for the end of the stack, which is broken
|
||||
for things like stepping through gcc nested function stubs. */
|
||||
#define PC_IN_CALL_DUMMY(STOP_PC, STOP_SP, STOP_FRAME_ADDR) \
|
||||
(STOP_SP < STOP_PC && STOP_PC < STACK_END_ADDR)
|
||||
|
||||
/* For each symtab, we keep track of which BFD it came from. */
|
||||
#define EXTRA_SYMTAB_INFO \
|
||||
unsigned nonreloc:1; /* TRUE if non relocatable */
|
||||
|
||||
#define INIT_EXTRA_SYMTAB_INFO(symtab) \
|
||||
symtab->nonreloc = 0; \
|
||||
|
||||
#if 0
|
||||
extern unsigned int text_start, data_start;
|
||||
extern int inferior_pid;
|
||||
extern char *corefile;
|
||||
#endif
|
||||
extern int inferior_pid;
|
||||
|
||||
/* setpgrp() messes up controling terminal. The other version of it
|
||||
requires libbsd.a. */
|
||||
@ -114,17 +99,12 @@ function_frame_info PARAMS ((CORE_ADDR, struct aix_framedata *));
|
||||
|
||||
/* When a child process is just starting, we sneak in and relocate
|
||||
the symbol table (and other stuff) after the dynamic linker has
|
||||
figured out where they go. But we want to do this relocation just
|
||||
once. */
|
||||
|
||||
extern int loadinfotextindex;
|
||||
figured out where they go. */
|
||||
|
||||
#define SOLIB_CREATE_INFERIOR_HOOK(PID) \
|
||||
do { \
|
||||
if (loadinfotextindex == 0) \
|
||||
xcoff_relocate_symtab (PID); \
|
||||
xcoff_relocate_symtab (PID); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Number of trap signals we need to skip over, once the inferior process
|
||||
starts running. */
|
||||
@ -155,15 +135,17 @@ extern int loadinfotextindex;
|
||||
|
||||
#define PROCESS_LINENUMBER_HOOK() aix_process_linenos ()
|
||||
|
||||
|
||||
/* When a target process or core-file has been attached, we sneak in
|
||||
and figure out where the shared libraries have got to. In case there
|
||||
is no inferior_process exists (e.g. bringing up a core file), we can't
|
||||
attemtp to relocate symbol table, since we don't have information about
|
||||
load segments. */
|
||||
and figure out where the shared libraries have got to. */
|
||||
|
||||
#define SOLIB_ADD(a, b, c) \
|
||||
if (inferior_pid) xcoff_relocate_symtab (inferior_pid)
|
||||
if (inferior_pid) \
|
||||
/* Attach to process. */ \
|
||||
xcoff_relocate_symtab (inferior_pid); \
|
||||
else \
|
||||
/* Core file. */ \
|
||||
xcoff_relocate_core ();
|
||||
extern void xcoff_relocate_core PARAMS ((void));
|
||||
|
||||
/* Immediately after a function call, return the saved pc.
|
||||
Can't go through the frames for this because on some machines
|
||||
@ -401,10 +383,11 @@ extern unsigned int rs6000_struct_return_address;
|
||||
/* In the case of the RS6000, the frame's nominal address
|
||||
is the address of a 4-byte word containing the calling frame's address. */
|
||||
|
||||
#define FRAME_CHAIN(thisframe) \
|
||||
(!inside_entry_file ((thisframe)->pc) ? \
|
||||
read_memory_integer ((thisframe)->frame, 4) :\
|
||||
0)
|
||||
#define FRAME_CHAIN(thisframe) rs6000_frame_chain (thisframe)
|
||||
#ifdef __STDC__
|
||||
struct frame_info;
|
||||
#endif
|
||||
CORE_ADDR rs6000_frame_chain PARAMS ((struct frame_info *));
|
||||
|
||||
/* Define other aspects of the stack frame. */
|
||||
|
||||
@ -426,19 +409,30 @@ extern unsigned int rs6000_struct_return_address;
|
||||
CORE_ADDR initial_sp; /* initial stack pointer. */ \
|
||||
struct frame_saved_regs *cache_fsr; /* saved registers */
|
||||
|
||||
#define INIT_FRAME_PC_FIRST(fromleaf, prev) \
|
||||
prev->pc = (fromleaf ? SAVED_PC_AFTER_CALL (prev->next) : \
|
||||
prev->next ? FRAME_SAVED_PC (prev->next) : read_pc ());
|
||||
#define INIT_FRAME_PC(fromleaf, prev) /* nothing */
|
||||
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
|
||||
fi->initial_sp = 0; \
|
||||
fi->cache_fsr = 0; \
|
||||
if (fi->next != (CORE_ADDR)0 \
|
||||
&& read_memory_integer (fi->frame, 4) == 0 \
|
||||
&& fi->pc < TEXT_SEGMENT_BASE) \
|
||||
/* We're in get_prev_frame_info */ \
|
||||
/* and this is a special signal frame. */ \
|
||||
/* (fi->pc will be something like 0x3f88 or 0x2790). */ \
|
||||
fi->signal_handler_caller = 1;
|
||||
|
||||
/* Frameless function invocation in IBM RS/6000 is sometimes
|
||||
half-done. It perfectly sets up a new frame, e.g. a new frame (in
|
||||
fact stack) pointer, etc, but it doesn't save the %pc. We call
|
||||
frameless_function_invocation to tell us how to get the %pc. */
|
||||
|
||||
#define INIT_EXTRA_FRAME_INFO(fromleaf, fi) \
|
||||
fi->initial_sp = 0; \
|
||||
fi->cache_fsr = 0;
|
||||
|
||||
#define FRAME_SAVED_PC(FRAME) \
|
||||
(frameless_function_invocation (FRAME, 1) \
|
||||
? SAVED_PC_AFTER_CALL (FRAME) \
|
||||
: read_memory_integer (read_memory_integer ((FRAME)->frame, 4)+8, 4))
|
||||
: read_memory_integer (rs6000_frame_chain (FRAME)+8, 4))
|
||||
|
||||
#define FRAME_ARGS_ADDRESS(FI) \
|
||||
(((struct frame_info*)(FI))->initial_sp ? \
|
||||
|
@ -310,13 +310,18 @@ sparc_extract_struct_value_address PARAMS ((char [REGISTER_BYTES]));
|
||||
If there is a frame below this one, and the frame pointers are
|
||||
identical, it's a leaf frame and the bottoms are the same also.
|
||||
|
||||
Otherwise the bottom of this frame is the top of the next frame. */
|
||||
Otherwise the bottom of this frame is the top of the next frame.
|
||||
|
||||
The bottom field is misnamed, since it might imply that memory from
|
||||
bottom to frame contains this frame. That need not be true if
|
||||
stack frames are allocated in different segments (e.g. some on a
|
||||
stack, some on a heap in the data segment). */
|
||||
|
||||
#define EXTRA_FRAME_INFO FRAME_ADDR bottom;
|
||||
#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) \
|
||||
(fci)->bottom = \
|
||||
((fci)->next ? \
|
||||
((fci)->frame == (fci)->next_frame ? \
|
||||
((fci)->frame == (fci)->next->frame ? \
|
||||
(fci)->next->bottom : (fci)->next->frame) : \
|
||||
read_register (SP_REGNUM));
|
||||
|
||||
|
@ -245,16 +245,16 @@ fix to bug-gdb@prep.ai.mit.edu. */
|
||||
So return 0 (indicating we don't know the address of
|
||||
the arglist) if we don't know what frame this frame calls. */
|
||||
#define FRAME_ARGS_ADDRESS_CORRECT(fi) \
|
||||
(((fi)->next_frame \
|
||||
? read_memory_integer ((fi)->next_frame + 8, 4) \
|
||||
(((fi)->next \
|
||||
? read_memory_integer ((fi)->next->frame + 8, 4) \
|
||||
: /* read_register (AP_REGNUM) */ 0))
|
||||
|
||||
/* In most of GDB, getting the args address is too important to
|
||||
just say "I don't know". This is sometimes wrong for functions
|
||||
that aren't on top of the stack, but c'est la vie. */
|
||||
#define FRAME_ARGS_ADDRESS(fi) \
|
||||
(((fi)->next_frame \
|
||||
? read_memory_integer ((fi)->next_frame + 8, 4) \
|
||||
(((fi)->next \
|
||||
? read_memory_integer ((fi)->next->frame + 8, 4) \
|
||||
: read_register (AP_REGNUM) /* 0 */))
|
||||
|
||||
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
|
||||
|
@ -21,9 +21,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#if !defined (INFERIOR_H)
|
||||
#define INFERIOR_H 1
|
||||
|
||||
/* For symtab_and_line */
|
||||
#include "symtab.h"
|
||||
|
||||
/* For bpstat. */
|
||||
#include "breakpoint.h"
|
||||
|
||||
@ -110,6 +107,18 @@ read_pc PARAMS ((void));
|
||||
extern void
|
||||
write_pc PARAMS ((CORE_ADDR));
|
||||
|
||||
extern CORE_ADDR
|
||||
read_sp PARAMS ((void));
|
||||
|
||||
extern void
|
||||
write_sp PARAMS ((CORE_ADDR));
|
||||
|
||||
extern CORE_ADDR
|
||||
read_fp PARAMS ((void));
|
||||
|
||||
extern void
|
||||
write_fp PARAMS ((CORE_ADDR));
|
||||
|
||||
extern void
|
||||
wait_for_inferior PARAMS ((void));
|
||||
|
||||
@ -188,6 +197,8 @@ fork_inferior PARAMS ((char *, char *, char **,
|
||||
extern void
|
||||
new_tty_prefork PARAMS ((char *));
|
||||
|
||||
extern int gdb_has_a_terminal PARAMS ((void));
|
||||
|
||||
/* From infrun.c */
|
||||
|
||||
extern void
|
||||
@ -300,6 +311,29 @@ extern int pc_changed;
|
||||
|
||||
extern int attach_flag;
|
||||
|
||||
/* Sigtramp is a routine that the kernel calls (which then calls the
|
||||
signal handler). On most machines it is a library routine that
|
||||
is linked into the executable.
|
||||
|
||||
This macro, given a program counter value and the name of the
|
||||
function in which that PC resides (which can be null if the
|
||||
name is not known), returns nonzero if the PC and name show
|
||||
that we are in sigtramp.
|
||||
|
||||
On most machines just see if the name is sigtramp (and if we have
|
||||
no name, assume we are not in sigtramp). */
|
||||
#if !defined (IN_SIGTRAMP)
|
||||
# if defined (SIGTRAMP_START)
|
||||
# define IN_SIGTRAMP(pc, name) \
|
||||
((pc) >= SIGTRAMP_START \
|
||||
&& (pc) < SIGTRAMP_END \
|
||||
)
|
||||
# else
|
||||
# define IN_SIGTRAMP(pc, name) \
|
||||
(name && STREQ ("_sigtramp", name))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Possible values for CALL_DUMMY_LOCATION. */
|
||||
#define ON_STACK 1
|
||||
#define BEFORE_TEXT_END 2
|
||||
@ -326,15 +360,23 @@ extern CORE_ADDR text_end;
|
||||
&& (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK)
|
||||
#else /* On stack. */
|
||||
|
||||
/* This assumes that frame_address is the value of SP_REGNUM before
|
||||
the dummy frame was pushed. The only known machine for which this
|
||||
isn't true is the 29k, which doesn't use ON_STACK. Machines for
|
||||
which it isn't true who want to put stack dummies on the stack
|
||||
could provide their own PC_IN_CALL_DUMMY, or perhaps this macro
|
||||
could be re-written to check for the end of the stack instead
|
||||
(using the target_ops->sections). Are there user programs, libraries,
|
||||
kernel routines, etc. which also execute on the stack? If so, the
|
||||
latter would be a bad idea. */
|
||||
/* 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.
|
||||
|
||||
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.
|
||||
|
||||
Something simpler, like checking for the stack segment, doesn't work,
|
||||
since various programs (threads implementations, gcc nested function
|
||||
stubs, etc) may either allocate stack frames in another segment, or
|
||||
allocate other kinds of code on the stack. */
|
||||
|
||||
#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
|
||||
((sp) INNER_THAN (pc) && (frame_address != 0) && (pc) INNER_THAN (frame_address))
|
||||
|
17
gdb/stack.c
17
gdb/stack.c
@ -162,7 +162,7 @@ print_frame_info (fi, level, source, args)
|
||||
enum language funlang = language_unknown;
|
||||
int numargs;
|
||||
|
||||
if (PC_IN_CALL_DUMMY (fi->pc, read_register (SP_REGNUM), fi->frame))
|
||||
if (PC_IN_CALL_DUMMY (fi->pc, read_sp (), fi->frame))
|
||||
{
|
||||
/* Do this regardless of SOURCE because we don't have any source
|
||||
to list for this frame. */
|
||||
@ -181,7 +181,7 @@ print_frame_info (fi, level, source, args)
|
||||
return;
|
||||
}
|
||||
|
||||
sal = find_pc_line (fi->pc, fi->next_frame);
|
||||
sal = find_pc_line (fi->pc, fi->next);
|
||||
func = find_pc_function (fi->pc);
|
||||
if (func)
|
||||
{
|
||||
@ -245,7 +245,7 @@ print_frame_info (fi, level, source, args)
|
||||
struct print_args_args args;
|
||||
args.fi = fi;
|
||||
args.func = func;
|
||||
catch_errors (print_args_stub, (char *)&args, "");
|
||||
catch_errors (print_args_stub, (char *)&args, "", RETURN_MASK_ERROR);
|
||||
}
|
||||
printf_filtered (")");
|
||||
if (sal.symtab && sal.symtab->filename)
|
||||
@ -417,7 +417,7 @@ frame_info (addr_exp, from_tty)
|
||||
error ("Invalid frame specified.");
|
||||
|
||||
fi = get_frame_info (frame);
|
||||
sal = find_pc_line (fi->pc, fi->next_frame);
|
||||
sal = find_pc_line (fi->pc, fi->next);
|
||||
func = get_frame_function (frame);
|
||||
s = find_pc_symtab(fi->pc);
|
||||
if (func)
|
||||
@ -475,12 +475,13 @@ frame_info (addr_exp, from_tty)
|
||||
if (calling_frame)
|
||||
printf_filtered (" called by frame at %s",
|
||||
local_hex_string(FRAME_FP (calling_frame)));
|
||||
if (fi->next_frame && calling_frame)
|
||||
if (fi->next && calling_frame)
|
||||
puts_filtered (",");
|
||||
wrap_here (" ");
|
||||
if (fi->next_frame)
|
||||
printf_filtered (" caller of frame at %s", local_hex_string(fi->next_frame));
|
||||
if (fi->next_frame || calling_frame)
|
||||
if (fi->next)
|
||||
printf_filtered (" caller of frame at %s",
|
||||
local_hex_string (fi->next->frame));
|
||||
if (fi->next || calling_frame)
|
||||
puts_filtered ("\n");
|
||||
if (s)
|
||||
printf_filtered(" source language %s.\n", language_str(s->language));
|
||||
|
Loading…
Reference in New Issue
Block a user