mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-17 12:53:17 +08:00
* 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:
@ -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)
|
Tue Jul 6 11:51:18 1993 Jim Kingdon (kingdon@lioth.cygnus.com)
|
||||||
|
|
||||||
* Makefile.in: Remove gdb before creating a new one.
|
* Makefile.in: Remove gdb before creating a new one.
|
||||||
|
@ -377,7 +377,7 @@ init_frame_info (innermost_frame, fci)
|
|||||||
if (innermost_frame)
|
if (innermost_frame)
|
||||||
fci->frame = read_register (GR1_REGNUM);
|
fci->frame = read_register (GR1_REGNUM);
|
||||||
else
|
else
|
||||||
fci->frame = fci->next_frame + fci->next->rsize;
|
fci->frame = fci->next->frame + fci->next->rsize;
|
||||||
|
|
||||||
#if CALL_DUMMY_LOCATION == ON_STACK
|
#if CALL_DUMMY_LOCATION == ON_STACK
|
||||||
This wont work;
|
This wont work;
|
||||||
|
272
gdb/blockframe.c
272
gdb/blockframe.c
@ -1,6 +1,6 @@
|
|||||||
/* Get info from stack frames;
|
/* Get info from stack frames;
|
||||||
convert between frames, blocks, functions and pc values.
|
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.
|
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
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "param.h"
|
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
#include "bfd.h"
|
||||||
|
#include "symfile.h"
|
||||||
|
#include "objfiles.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
#include "gdbcore.h"
|
#include "gdbcore.h"
|
||||||
#include "value.h" /* for read_register */
|
#include "value.h" /* for read_register */
|
||||||
#include "target.h" /* for target_has_stack */
|
#include "target.h" /* for target_has_stack */
|
||||||
|
#include "inferior.h" /* for read_pc */
|
||||||
|
|
||||||
CORE_ADDR read_pc (); /* In infcmd.c */
|
/* Is ADDR inside the startup file? Note that if your machine
|
||||||
|
|
||||||
/* 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
|
|
||||||
has a way to detect the bottom of the stack, there is no need
|
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
|
to call this function from FRAME_CHAIN_VALID; the reason for
|
||||||
doing so is that some machines have no way of detecting bottom
|
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
|
int
|
||||||
outside_startup_file (addr)
|
inside_entry_file (addr)
|
||||||
CORE_ADDR 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
|
/* 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
|
that correspond to the main() function. See comments above for why
|
||||||
we might want to do this.
|
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
|
int
|
||||||
inside_main_scope (pc)
|
inside_main_func (pc)
|
||||||
CORE_ADDR 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
|
/* 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
|
that correspond to the process entry point function. See comments
|
||||||
for why we might want to do this.
|
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
|
int
|
||||||
inside_entry_scope (pc)
|
inside_entry_func (pc)
|
||||||
CORE_ADDR 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) */
|
/* 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->next = (struct frame_info *) 0;
|
||||||
fci->prev = (struct frame_info *) 0;
|
fci->prev = (struct frame_info *) 0;
|
||||||
fci->frame = addr;
|
fci->frame = addr;
|
||||||
fci->next_frame = 0; /* Since arbitrary */
|
|
||||||
fci->pc = pc;
|
fci->pc = pc;
|
||||||
|
fci->signal_handler_caller = IN_SIGTRAMP (fci->pc, (char *)NULL);
|
||||||
|
|
||||||
#ifdef INIT_EXTRA_FRAME_INFO
|
#ifdef INIT_EXTRA_FRAME_INFO
|
||||||
INIT_EXTRA_FRAME_INFO (0, fci);
|
INIT_EXTRA_FRAME_INFO (0, fci);
|
||||||
@ -223,8 +187,7 @@ reinit_frame_cache ()
|
|||||||
FRAME fr = current_frame;
|
FRAME fr = current_frame;
|
||||||
flush_cached_frames ();
|
flush_cached_frames ();
|
||||||
if (fr)
|
if (fr)
|
||||||
set_current_frame ( create_new_frame (read_register (FP_REGNUM),
|
set_current_frame ( create_new_frame (read_fp (), read_pc ()));
|
||||||
read_pc ()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a structure containing various interesting information
|
/* 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
|
frame_info for the frame, and FRAMELESS should be set to nonzero
|
||||||
if it represents a frameless function invocation. */
|
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
|
machines can define FRAMELESS_FUNCTION_INVOCATION to just call this
|
||||||
function. */
|
function. */
|
||||||
|
|
||||||
@ -368,7 +331,47 @@ get_prev_frame_info (next_frame)
|
|||||||
prev->next = next_frame;
|
prev->next = next_frame;
|
||||||
prev->prev = (struct frame_info *) 0;
|
prev->prev = (struct frame_info *) 0;
|
||||||
prev->frame = address;
|
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
|
#ifdef INIT_EXTRA_FRAME_INFO
|
||||||
INIT_EXTRA_FRAME_INFO(fromleaf, prev);
|
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. */
|
(see tm-sparc.h). We want the pc saved in the inferior frame. */
|
||||||
INIT_FRAME_PC(fromleaf, prev);
|
INIT_FRAME_PC(fromleaf, prev);
|
||||||
|
|
||||||
|
if (IN_SIGTRAMP (prev->pc, (char *)NULL))
|
||||||
|
prev->signal_handler_caller = 1;
|
||||||
|
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,7 +422,7 @@ get_frame_block (frame)
|
|||||||
fi = get_frame_info (frame);
|
fi = get_frame_info (frame);
|
||||||
|
|
||||||
pc = fi->pc;
|
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
|
/* We are not in the innermost frame. We need to subtract one to
|
||||||
get the correct block, in case the call instruction was the
|
get the correct block, in case the call instruction was the
|
||||||
last instruction of the block. If there are any machines on
|
last instruction of the block. If there are any machines on
|
||||||
@ -436,17 +442,26 @@ CORE_ADDR
|
|||||||
get_pc_function_start (pc)
|
get_pc_function_start (pc)
|
||||||
CORE_ADDR pc;
|
CORE_ADDR pc;
|
||||||
{
|
{
|
||||||
register struct block *bl = block_for_pc (pc);
|
register struct block *bl;
|
||||||
register struct symbol *symbol;
|
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);
|
bl = SYMBOL_BLOCK_VALUE (symbol);
|
||||||
if (misc_index >= 0)
|
fstart = BLOCK_START (bl);
|
||||||
return misc_function_vector[misc_index].address;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
bl = SYMBOL_BLOCK_VALUE (symbol);
|
else if ((msymbol = lookup_minimal_symbol_by_pc (pc)) != NULL)
|
||||||
return BLOCK_START (bl);
|
{
|
||||||
|
fstart = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fstart = 0;
|
||||||
|
}
|
||||||
|
return (fstart);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the symbol for the function executing in frame FRAME. */
|
/* 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 partial_symtab *pst;
|
||||||
struct symbol *f;
|
struct symbol *f;
|
||||||
int miscfunc;
|
struct minimal_symbol *msymbol;
|
||||||
struct partial_symbol *psb;
|
struct partial_symbol *psb;
|
||||||
|
|
||||||
if (pc >= cache_pc_function_low && pc < cache_pc_function_high)
|
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
|
/* 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). */
|
symbols). */
|
||||||
miscfunc = find_pc_misc_function (pc);
|
msymbol = lookup_minimal_symbol_by_pc (pc);
|
||||||
psb = find_pc_psymbol (pst, pc);
|
psb = find_pc_psymbol (pst, pc);
|
||||||
|
|
||||||
if (!psb && miscfunc == -1)
|
if (!psb && (msymbol == NULL))
|
||||||
{
|
{
|
||||||
goto return_error;
|
goto return_error;
|
||||||
}
|
}
|
||||||
if (psb
|
if (psb
|
||||||
&& (miscfunc == -1
|
&& (msymbol == NULL ||
|
||||||
|| (SYMBOL_VALUE_ADDRESS (psb)
|
(SYMBOL_VALUE_ADDRESS (psb) >= SYMBOL_VALUE_ADDRESS (msymbol))))
|
||||||
>= misc_function_vector[miscfunc].address)))
|
|
||||||
{
|
{
|
||||||
/* This case isn't being cached currently. */
|
/* This case isn't being cached currently. */
|
||||||
if (address)
|
if (address)
|
||||||
@ -644,23 +658,25 @@ find_pc_partial_function (pc, name, address)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Must be in the misc function stuff. */
|
/* Must be in the minimal symbol table. */
|
||||||
{
|
{
|
||||||
miscfunc = find_pc_misc_function (pc);
|
msymbol = lookup_minimal_symbol_by_pc (pc);
|
||||||
if (miscfunc == -1)
|
if (msymbol == NULL)
|
||||||
goto return_error;
|
goto return_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
if (misc_function_vector[miscfunc].type == mf_text)
|
if (msymbol -> type == mst_text)
|
||||||
cache_pc_function_low = misc_function_vector[miscfunc].address;
|
cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
|
||||||
else
|
else
|
||||||
/* It is a transfer table for Sun shared libraries. */
|
/* It is a transfer table for Sun shared libraries. */
|
||||||
cache_pc_function_low = pc - FUNCTION_START_OFFSET;
|
cache_pc_function_low = pc - FUNCTION_START_OFFSET;
|
||||||
}
|
}
|
||||||
cache_pc_function_name = misc_function_vector[miscfunc].name;
|
cache_pc_function_name = SYMBOL_NAME (msymbol);
|
||||||
if (miscfunc < misc_function_count /* && FIXME mf_text again? */ )
|
/* FIXME: Deal with bumping into end of minimal symbols for a given
|
||||||
cache_pc_function_high = misc_function_vector[miscfunc+1].address;
|
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
|
else
|
||||||
cache_pc_function_high = cache_pc_function_low + 1;
|
cache_pc_function_high = cache_pc_function_low + 1;
|
||||||
if (address)
|
if (address)
|
||||||
@ -670,53 +686,11 @@ find_pc_partial_function (pc, name, address)
|
|||||||
return 1;
|
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,
|
/* Return the innermost stack frame executing inside of the specified block,
|
||||||
or zero if there is no such frame. */
|
or zero if there is no such frame. */
|
||||||
|
|
||||||
|
#if 0 /* Currently unused */
|
||||||
|
|
||||||
FRAME
|
FRAME
|
||||||
block_innermost_frame (block)
|
block_innermost_frame (block)
|
||||||
struct block *block;
|
struct block *block;
|
||||||
@ -738,6 +712,8 @@ block_innermost_frame (block)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
void
|
void
|
||||||
_initialize_blockframe ()
|
_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
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
extern int symtab_relocated;
|
|
||||||
|
|
||||||
/* Minimum possible text address in AIX */
|
/* Minimum possible text address in AIX */
|
||||||
|
|
||||||
#define TEXT_SEGMENT_BASE 0x10000000
|
#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. */
|
/* Load segment of a given pc value. */
|
||||||
|
|
||||||
#define PC_LOAD_SEGMENT(PC) pc_load_segment_name(PC)
|
#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
|
#define BELIEVE_PCC_PROMOTION 1
|
||||||
|
|
||||||
/* return true if a given `pc' value is in `call dummy' function. */
|
/* 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) \
|
#define PC_IN_CALL_DUMMY(STOP_PC, STOP_SP, STOP_FRAME_ADDR) \
|
||||||
(STOP_SP < STOP_PC && STOP_PC < STACK_END_ADDR)
|
(STOP_SP < STOP_PC && STOP_PC < STACK_END_ADDR)
|
||||||
|
|
||||||
/* For each symtab, we keep track of which BFD it came from. */
|
#if 0
|
||||||
#define EXTRA_SYMTAB_INFO \
|
|
||||||
unsigned nonreloc:1; /* TRUE if non relocatable */
|
|
||||||
|
|
||||||
#define INIT_EXTRA_SYMTAB_INFO(symtab) \
|
|
||||||
symtab->nonreloc = 0; \
|
|
||||||
|
|
||||||
extern unsigned int text_start, data_start;
|
extern unsigned int text_start, data_start;
|
||||||
extern int inferior_pid;
|
|
||||||
extern char *corefile;
|
extern char *corefile;
|
||||||
|
#endif
|
||||||
|
extern int inferior_pid;
|
||||||
|
|
||||||
/* setpgrp() messes up controling terminal. The other version of it
|
/* setpgrp() messes up controling terminal. The other version of it
|
||||||
requires libbsd.a. */
|
requires libbsd.a. */
|
||||||
@ -114,18 +99,13 @@ function_frame_info PARAMS ((CORE_ADDR, struct aix_framedata *));
|
|||||||
|
|
||||||
/* When a child process is just starting, we sneak in and relocate
|
/* When a child process is just starting, we sneak in and relocate
|
||||||
the symbol table (and other stuff) after the dynamic linker has
|
the symbol table (and other stuff) after the dynamic linker has
|
||||||
figured out where they go. But we want to do this relocation just
|
figured out where they go. */
|
||||||
once. */
|
|
||||||
|
|
||||||
extern int loadinfotextindex;
|
|
||||||
|
|
||||||
#define SOLIB_CREATE_INFERIOR_HOOK(PID) \
|
#define SOLIB_CREATE_INFERIOR_HOOK(PID) \
|
||||||
do { \
|
do { \
|
||||||
if (loadinfotextindex == 0) \
|
xcoff_relocate_symtab (PID); \
|
||||||
xcoff_relocate_symtab (PID); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
/* Number of trap signals we need to skip over, once the inferior process
|
/* Number of trap signals we need to skip over, once the inferior process
|
||||||
starts running. */
|
starts running. */
|
||||||
|
|
||||||
@ -155,15 +135,17 @@ extern int loadinfotextindex;
|
|||||||
|
|
||||||
#define PROCESS_LINENUMBER_HOOK() aix_process_linenos ()
|
#define PROCESS_LINENUMBER_HOOK() aix_process_linenos ()
|
||||||
|
|
||||||
|
|
||||||
/* When a target process or core-file has been attached, we sneak in
|
/* 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
|
and figure out where the shared libraries have got to. */
|
||||||
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. */
|
|
||||||
|
|
||||||
#define SOLIB_ADD(a, b, c) \
|
#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.
|
/* Immediately after a function call, return the saved pc.
|
||||||
Can't go through the frames for this because on some machines
|
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
|
/* 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. */
|
is the address of a 4-byte word containing the calling frame's address. */
|
||||||
|
|
||||||
#define FRAME_CHAIN(thisframe) \
|
#define FRAME_CHAIN(thisframe) rs6000_frame_chain (thisframe)
|
||||||
(!inside_entry_file ((thisframe)->pc) ? \
|
#ifdef __STDC__
|
||||||
read_memory_integer ((thisframe)->frame, 4) :\
|
struct frame_info;
|
||||||
0)
|
#endif
|
||||||
|
CORE_ADDR rs6000_frame_chain PARAMS ((struct frame_info *));
|
||||||
|
|
||||||
/* Define other aspects of the stack frame. */
|
/* 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. */ \
|
CORE_ADDR initial_sp; /* initial stack pointer. */ \
|
||||||
struct frame_saved_regs *cache_fsr; /* saved registers */
|
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
|
/* Frameless function invocation in IBM RS/6000 is sometimes
|
||||||
half-done. It perfectly sets up a new frame, e.g. a new frame (in
|
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
|
fact stack) pointer, etc, but it doesn't save the %pc. We call
|
||||||
frameless_function_invocation to tell us how to get the %pc. */
|
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) \
|
#define FRAME_SAVED_PC(FRAME) \
|
||||||
(frameless_function_invocation (FRAME, 1) \
|
(frameless_function_invocation (FRAME, 1) \
|
||||||
? SAVED_PC_AFTER_CALL (FRAME) \
|
? 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) \
|
#define FRAME_ARGS_ADDRESS(FI) \
|
||||||
(((struct frame_info*)(FI))->initial_sp ? \
|
(((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
|
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.
|
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 EXTRA_FRAME_INFO FRAME_ADDR bottom;
|
||||||
#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) \
|
#define INIT_EXTRA_FRAME_INFO(fromleaf, fci) \
|
||||||
(fci)->bottom = \
|
(fci)->bottom = \
|
||||||
((fci)->next ? \
|
((fci)->next ? \
|
||||||
((fci)->frame == (fci)->next_frame ? \
|
((fci)->frame == (fci)->next->frame ? \
|
||||||
(fci)->next->bottom : (fci)->next->frame) : \
|
(fci)->next->bottom : (fci)->next->frame) : \
|
||||||
read_register (SP_REGNUM));
|
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
|
So return 0 (indicating we don't know the address of
|
||||||
the arglist) if we don't know what frame this frame calls. */
|
the arglist) if we don't know what frame this frame calls. */
|
||||||
#define FRAME_ARGS_ADDRESS_CORRECT(fi) \
|
#define FRAME_ARGS_ADDRESS_CORRECT(fi) \
|
||||||
(((fi)->next_frame \
|
(((fi)->next \
|
||||||
? read_memory_integer ((fi)->next_frame + 8, 4) \
|
? read_memory_integer ((fi)->next->frame + 8, 4) \
|
||||||
: /* read_register (AP_REGNUM) */ 0))
|
: /* read_register (AP_REGNUM) */ 0))
|
||||||
|
|
||||||
/* In most of GDB, getting the args address is too important to
|
/* In most of GDB, getting the args address is too important to
|
||||||
just say "I don't know". This is sometimes wrong for functions
|
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. */
|
that aren't on top of the stack, but c'est la vie. */
|
||||||
#define FRAME_ARGS_ADDRESS(fi) \
|
#define FRAME_ARGS_ADDRESS(fi) \
|
||||||
(((fi)->next_frame \
|
(((fi)->next \
|
||||||
? read_memory_integer ((fi)->next_frame + 8, 4) \
|
? read_memory_integer ((fi)->next->frame + 8, 4) \
|
||||||
: read_register (AP_REGNUM) /* 0 */))
|
: read_register (AP_REGNUM) /* 0 */))
|
||||||
|
|
||||||
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
|
#define FRAME_LOCALS_ADDRESS(fi) ((fi)->frame)
|
||||||
|
@ -21,9 +21,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||||||
#if !defined (INFERIOR_H)
|
#if !defined (INFERIOR_H)
|
||||||
#define INFERIOR_H 1
|
#define INFERIOR_H 1
|
||||||
|
|
||||||
/* For symtab_and_line */
|
|
||||||
#include "symtab.h"
|
|
||||||
|
|
||||||
/* For bpstat. */
|
/* For bpstat. */
|
||||||
#include "breakpoint.h"
|
#include "breakpoint.h"
|
||||||
|
|
||||||
@ -110,6 +107,18 @@ read_pc PARAMS ((void));
|
|||||||
extern void
|
extern void
|
||||||
write_pc PARAMS ((CORE_ADDR));
|
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
|
extern void
|
||||||
wait_for_inferior PARAMS ((void));
|
wait_for_inferior PARAMS ((void));
|
||||||
|
|
||||||
@ -188,6 +197,8 @@ fork_inferior PARAMS ((char *, char *, char **,
|
|||||||
extern void
|
extern void
|
||||||
new_tty_prefork PARAMS ((char *));
|
new_tty_prefork PARAMS ((char *));
|
||||||
|
|
||||||
|
extern int gdb_has_a_terminal PARAMS ((void));
|
||||||
|
|
||||||
/* From infrun.c */
|
/* From infrun.c */
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
@ -300,6 +311,29 @@ extern int pc_changed;
|
|||||||
|
|
||||||
extern int attach_flag;
|
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. */
|
/* Possible values for CALL_DUMMY_LOCATION. */
|
||||||
#define ON_STACK 1
|
#define ON_STACK 1
|
||||||
#define BEFORE_TEXT_END 2
|
#define BEFORE_TEXT_END 2
|
||||||
@ -326,15 +360,23 @@ extern CORE_ADDR text_end;
|
|||||||
&& (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK)
|
&& (pc) <= text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK)
|
||||||
#else /* On stack. */
|
#else /* On stack. */
|
||||||
|
|
||||||
/* This assumes that frame_address is the value of SP_REGNUM before
|
/* Is the PC in a call dummy? SP and FRAME_ADDRESS are the bottom and
|
||||||
the dummy frame was pushed. The only known machine for which this
|
top of the stack frame which we are checking, where "bottom" and
|
||||||
isn't true is the 29k, which doesn't use ON_STACK. Machines for
|
"top" refer to some section of memory which contains the code for
|
||||||
which it isn't true who want to put stack dummies on the stack
|
the call dummy. Calls to this macro assume that the contents of
|
||||||
could provide their own PC_IN_CALL_DUMMY, or perhaps this macro
|
SP_REGNUM and FP_REGNUM (or the saved values thereof), respectively,
|
||||||
could be re-written to check for the end of the stack instead
|
are the things to pass.
|
||||||
(using the target_ops->sections). Are there user programs, libraries,
|
|
||||||
kernel routines, etc. which also execute on the stack? If so, the
|
This won't work on the 29k, where SP_REGNUM and FP_REGNUM don't
|
||||||
latter would be a bad idea. */
|
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) \
|
#define PC_IN_CALL_DUMMY(pc, sp, frame_address) \
|
||||||
((sp) INNER_THAN (pc) && (frame_address != 0) && (pc) INNER_THAN (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;
|
enum language funlang = language_unknown;
|
||||||
int numargs;
|
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
|
/* Do this regardless of SOURCE because we don't have any source
|
||||||
to list for this frame. */
|
to list for this frame. */
|
||||||
@ -181,7 +181,7 @@ print_frame_info (fi, level, source, args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sal = find_pc_line (fi->pc, fi->next_frame);
|
sal = find_pc_line (fi->pc, fi->next);
|
||||||
func = find_pc_function (fi->pc);
|
func = find_pc_function (fi->pc);
|
||||||
if (func)
|
if (func)
|
||||||
{
|
{
|
||||||
@ -245,7 +245,7 @@ print_frame_info (fi, level, source, args)
|
|||||||
struct print_args_args args;
|
struct print_args_args args;
|
||||||
args.fi = fi;
|
args.fi = fi;
|
||||||
args.func = func;
|
args.func = func;
|
||||||
catch_errors (print_args_stub, (char *)&args, "");
|
catch_errors (print_args_stub, (char *)&args, "", RETURN_MASK_ERROR);
|
||||||
}
|
}
|
||||||
printf_filtered (")");
|
printf_filtered (")");
|
||||||
if (sal.symtab && sal.symtab->filename)
|
if (sal.symtab && sal.symtab->filename)
|
||||||
@ -417,7 +417,7 @@ frame_info (addr_exp, from_tty)
|
|||||||
error ("Invalid frame specified.");
|
error ("Invalid frame specified.");
|
||||||
|
|
||||||
fi = get_frame_info (frame);
|
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);
|
func = get_frame_function (frame);
|
||||||
s = find_pc_symtab(fi->pc);
|
s = find_pc_symtab(fi->pc);
|
||||||
if (func)
|
if (func)
|
||||||
@ -475,12 +475,13 @@ frame_info (addr_exp, from_tty)
|
|||||||
if (calling_frame)
|
if (calling_frame)
|
||||||
printf_filtered (" called by frame at %s",
|
printf_filtered (" called by frame at %s",
|
||||||
local_hex_string(FRAME_FP (calling_frame)));
|
local_hex_string(FRAME_FP (calling_frame)));
|
||||||
if (fi->next_frame && calling_frame)
|
if (fi->next && calling_frame)
|
||||||
puts_filtered (",");
|
puts_filtered (",");
|
||||||
wrap_here (" ");
|
wrap_here (" ");
|
||||||
if (fi->next_frame)
|
if (fi->next)
|
||||||
printf_filtered (" caller of frame at %s", local_hex_string(fi->next_frame));
|
printf_filtered (" caller of frame at %s",
|
||||||
if (fi->next_frame || calling_frame)
|
local_hex_string (fi->next->frame));
|
||||||
|
if (fi->next || calling_frame)
|
||||||
puts_filtered ("\n");
|
puts_filtered ("\n");
|
||||||
if (s)
|
if (s)
|
||||||
printf_filtered(" source language %s.\n", language_str(s->language));
|
printf_filtered(" source language %s.\n", language_str(s->language));
|
||||||
|
Reference in New Issue
Block a user