@ -992,6 +992,142 @@ legacy_get_prev_frame (struct frame_info *this_frame)
struct frame_info * prev ;
int fromleaf ;
/* Allocate the new frame but do not wire it in to the frame chain.
Some ( bad ) code in INIT_FRAME_EXTRA_INFO tries to look along
frame - > next to pull some fancy tricks ( of course such code is , by
definition , recursive ) . Try to prevent it .
There is no reason to worry about memory leaks , should the
remainder of the function fail . The allocated memory will be
quickly reclaimed when the frame cache is flushed , and the ` we ' ve
been here before ' check , in get_prev_frame will stop repeated
memory allocation calls . */
prev = FRAME_OBSTACK_ZALLOC ( struct frame_info ) ;
prev - > level = this_frame - > level + 1 ;
/* NOTE: cagney/2002-11-18: Should have been correctly setting the
frame ' s type here , before anything else , and not last , at the
bottom of this function . The various
DEPRECATED_INIT_EXTRA_FRAME_INFO , DEPRECATED_INIT_FRAME_PC ,
DEPRECATED_INIT_FRAME_PC_FIRST and
DEPRECATED_FRAME_INIT_SAVED_REGS methods are full of work - arounds
that handle the frame not being correctly set from the start .
Unfortunatly those same work - arounds rely on the type defaulting
to NORMAL_FRAME . Ulgh ! The new frame code does not have this
problem . */
prev - > type = NORMAL_FRAME ;
/* Handle sentinel frame unwind as a special case. */
if ( this_frame - > level < 0 )
{
/* Try to unwind the PC. If that doesn't work, assume we've reached
the oldest frame and simply return . Is there a better sentinal
value ? The unwound PC value is then used to initialize the new
previous frame ' s type .
Note that the pc - unwind is intentionally performed before the
frame chain . This is ok since , for old targets , both
frame_pc_unwind ( nee , FRAME_SAVED_PC ) and FRAME_CHAIN ( ) ) assume
THIS_FRAME ' s data structures have already been initialized ( using
DEPRECATED_INIT_EXTRA_FRAME_INFO ) and hence the call order
doesn ' t matter .
By unwinding the PC first , it becomes possible to , in the case of
a dummy frame , avoid also unwinding the frame ID . This is
because ( well ignoring the PPC ) a dummy frame can be located
using THIS_FRAME ' s frame ID . */
prev - > pc = frame_pc_unwind ( this_frame ) ;
if ( prev - > pc = = 0 )
{
/* The allocated PREV_FRAME will be reclaimed when the frame
obstack is next purged . */
if ( frame_debug )
fprintf_unfiltered ( gdb_stdlog ,
" Outermost frame - unwound PC zero \n " ) ;
return NULL ;
}
prev - > type = frame_type_from_pc ( prev - > pc ) ;
/* Set the unwind functions based on that identified PC. */
prev - > unwind = frame_unwind_find_by_pc ( current_gdbarch , prev - > pc ) ;
/* Find the prev's frame's ID. */
if ( prev - > type = = DUMMY_FRAME
& & gdbarch_unwind_dummy_id_p ( current_gdbarch ) )
{
/* When unwinding a normal frame, the stack structure is
determined by analyzing the frame ' s function ' s code ( be
it using brute force prologue analysis , or the dwarf2
CFI ) . In the case of a dummy frame , that simply isn ' t
possible . The The PC is either the program entry point ,
or some random address on the stack . Trying to use that
PC to apply standard frame ID unwind techniques is just
asking for trouble . */
/* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS,
previously saved the dummy frame ' s ID . Things only work
if the two return the same value . */
gdb_assert ( SAVE_DUMMY_FRAME_TOS_P ( ) ) ;
/* Use an architecture specific method to extract the prev's
dummy ID from the next frame . Note that this method uses
frame_register_unwind to obtain the register values
needed to determine the dummy frame ' s ID . */
prev - > id = gdbarch_unwind_dummy_id ( current_gdbarch , this_frame ) ;
}
else
{
/* We're unwinding a sentinel frame, the PC of which is
pointing at a stack dummy . Fake up the dummy frame ' s ID
using the same sequence as is found a traditional
unwinder . Once all architectures supply the
unwind_dummy_id method , this code can go away . */
prev - > id . base = read_fp ( ) ;
prev - > id . pc = read_pc ( ) ;
}
/* Check that the unwound ID is valid. */
if ( ! frame_id_p ( prev - > id ) )
{
if ( frame_debug )
fprintf_unfiltered ( gdb_stdlog ,
" Outermost legacy sentinel frame - unwound frame ID invalid \n " ) ;
return NULL ;
}
/* Check that the new frame isn't inner to (younger, below,
next ) the old frame . If that happens the frame unwind is
going backwards . */
/* FIXME: cagney/2003-02-25: Ignore the sentinel frame since
that doesn ' t have a valid frame ID . Should instead set the
sentinel frame ' s frame ID to a ` sentinel ' . Leave it until
after the switch to storing the frame ID , instead of the
frame base , in the frame object . */
/* FIXME: cagney/2002-12-18: Instead of this hack, should only
store the frame ID in PREV_FRAME . Unfortunatly , some
architectures ( HP / UX ) still reply on EXTRA_FRAME_INFO and ,
hence , still poke at the " struct frame_info " object directly . */
prev - > frame = prev - > id . base ;
/* Link it in. */
this_frame - > prev = prev ;
prev - > next = this_frame ;
/* FIXME: cagney/2002-01-19: This call will go away. Instead of
initializing extra info , all frames will use the frame_cache
( passed to the unwind functions ) to store additional frame
info . Unfortunatly legacy targets can ' t use
legacy_get_prev_frame ( ) to unwind the sentinel frame and ,
consequently , are forced to take this code path and rely on
the below call to DEPRECATED_INIT_EXTRA_FRAME_INFO to
initialize the inner - most frame . */
if ( DEPRECATED_INIT_EXTRA_FRAME_INFO_P ( ) )
{
DEPRECATED_INIT_EXTRA_FRAME_INFO ( 0 , prev ) ;
}
return prev ;
}
/* This code only works on normal frames. A sentinel frame, where
the level is - 1 , should never reach this code . */
gdb_assert ( this_frame - > level > = 0 ) ;
@ -1048,19 +1184,10 @@ legacy_get_prev_frame (struct frame_info *this_frame)
if ( address = = 0 )
return 0 ;
/* Create an initially zero previous frame. */
prev = frame_obstack_zalloc ( sizeof ( struct frame_info ) ) ;
/* Link it in. */
/* Link in the already allocated prev frame. */
this_frame - > prev = prev ;
prev - > next = this_frame ;
prev - > frame = address ;
prev - > level = this_frame - > level + 1 ;
/* FIXME: cagney/2002-11-18: Should be setting the frame's type
here , before anything else , and not last . Various INIT functions
are full of work - arounds for the frames type not being set
correctly from the word go . Ulgh ! */
prev - > type = NORMAL_FRAME ;
/* This change should not be needed, FIXME! We should determine
whether any targets * need * DEPRECATED_INIT_FRAME_PC to happen
@ -1305,11 +1432,8 @@ get_prev_frame (struct frame_info *this_frame)
}
/* If any of the old frame initialization methods are around, use
the legacy get_prev_frame method . Just don ' t try to unwind a
sentinel frame using that method - it doesn ' t work . All sentinal
frames use the new unwind code . */
if ( legacy_frame_p ( current_gdbarch )
& & this_frame - > level > = 0 )
the legacy get_prev_frame method . */
if ( legacy_frame_p ( current_gdbarch ) )
{
prev_frame = legacy_get_prev_frame ( this_frame ) ;
if ( frame_debug & & prev_frame = = NULL )
@ -1376,39 +1500,16 @@ get_prev_frame (struct frame_info *this_frame)
address on the stack . Trying to use that PC to apply
standard frame ID unwind techniques is just asking for
trouble . */
if ( gdbarch_unwind_dummy_id_p ( current_gdbarch ) )
{
/* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS,
previously saved the dummy frame ' s ID . Things only work
if the two return the same value . */
gdb_assert ( SAVE_DUMMY_FRAME_TOS_P ( ) ) ;
/* Use an architecture specific method to extract the prev's
dummy ID from the next frame . Note that this method uses
frame_register_unwind to obtain the register values
needed to determine the dummy frame ' s ID . */
prev_frame - > id = gdbarch_unwind_dummy_id ( current_gdbarch ,
this_frame ) ;
}
else if ( this_frame - > level < 0 )
{
/* We're unwinding a sentinel frame, the PC of which is
pointing at a stack dummy . Fake up the dummy frame ' s ID
using the same sequence as is found a traditional
unwinder . Once all architectures supply the
unwind_dummy_id method , this code can go away . */
prev_frame - > id . base = read_fp ( ) ;
prev_frame - > id . pc = read_pc ( ) ;
}
else
{
/* Outch! We're not on the innermost frame yet we're trying
to unwind to a dummy . The architecture must provide the
unwind_dummy_id ( ) method . Abandon the unwind process but
only after first warning the user . */
internal_warning ( __FILE__ , __LINE__ ,
" Missing unwind_dummy_id architecture method " ) ;
return NULL ;
}
gdb_assert ( gdbarch_unwind_dummy_id_p ( current_gdbarch ) ) ;
/* Assume hand_function_call(), via SAVE_DUMMY_FRAME_TOS,
previously saved the dummy frame ' s ID . Things only work if
the two return the same value . */
gdb_assert ( SAVE_DUMMY_FRAME_TOS_P ( ) ) ;
/* Use an architecture specific method to extract the prev's
dummy ID from the next frame . Note that this method uses
frame_register_unwind to obtain the register values needed to
determine the dummy frame ' s ID . */
prev_frame - > id = gdbarch_unwind_dummy_id ( current_gdbarch , this_frame ) ;
break ;
case NORMAL_FRAME :
case SIGTRAMP_FRAME :
@ -1455,20 +1556,6 @@ get_prev_frame (struct frame_info *this_frame)
this_frame - > prev = prev_frame ;
prev_frame - > next = this_frame ;
/* FIXME: cagney/2002-01-19: This call will go away. Instead of
initializing extra info , all frames will use the frame_cache
( passed to the unwind functions ) to store additional frame info .
Unfortunatly legacy targets can ' t use legacy_get_prev_frame ( ) to
unwind the sentinel frame and , consequently , are forced to take
this code path and rely on the below call to
DEPRECATED_INIT_EXTRA_FRAME_INFO to initialize the inner - most
frame . */
if ( DEPRECATED_INIT_EXTRA_FRAME_INFO_P ( ) )
{
gdb_assert ( prev_frame - > level = = 0 ) ;
DEPRECATED_INIT_EXTRA_FRAME_INFO ( 0 , prev_frame ) ;
}
return prev_frame ;
}
@ -1680,7 +1767,9 @@ legacy_frame_p (struct gdbarch *current_gdbarch)
return ( DEPRECATED_INIT_FRAME_PC_P ( )
| | DEPRECATED_INIT_FRAME_PC_FIRST_P ( )
| | DEPRECATED_INIT_EXTRA_FRAME_INFO_P ( )
| | FRAME_CHAIN_P ( ) ) ;
| | FRAME_CHAIN_P ( )
| | ! gdbarch_unwind_dummy_id_p ( current_gdbarch )
| | ! SAVE_DUMMY_FRAME_TOS_P ( ) ) ;
}
void