summaryrefslogtreecommitdiff
path: root/gdb/frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/frame.c')
-rw-r--r--gdb/frame.c122
1 files changed, 69 insertions, 53 deletions
diff --git a/gdb/frame.c b/gdb/frame.c
index 900b51518c5..8609ce194fb 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -791,8 +791,8 @@ legacy_saved_regs_this_id (struct frame_info *next_frame,
this to after the ffi test; I'd rather have backtraces from
start go curfluy than have an abort called from main not show
main. */
- gdb_assert (FRAME_CHAIN_P ());
- base = FRAME_CHAIN (next_frame);
+ gdb_assert (DEPRECATED_FRAME_CHAIN_P ());
+ base = DEPRECATED_FRAME_CHAIN (next_frame);
if (!frame_chain_valid (base, next_frame))
return;
@@ -1048,8 +1048,9 @@ legacy_get_prev_frame (struct frame_info *this_frame)
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
+ frame_pc_unwind (nee, DEPRECATED_FRAME_SAVED_PC) and
+ DEPRECATED_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.
@@ -1196,8 +1197,8 @@ legacy_get_prev_frame (struct frame_info *this_frame)
this to after the ffi test; I'd rather have backtraces from
start go curfluy than have an abort called from main not show
main. */
- gdb_assert (FRAME_CHAIN_P ());
- address = FRAME_CHAIN (this_frame);
+ gdb_assert (DEPRECATED_FRAME_CHAIN_P ());
+ address = DEPRECATED_FRAME_CHAIN (this_frame);
if (!frame_chain_valid (address, this_frame))
return 0;
@@ -1244,10 +1245,11 @@ legacy_get_prev_frame (struct frame_info *this_frame)
DEPRECATED_INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC.
This should also return a flag saying whether to keep the new
frame, or whether to discard it, because on some machines (e.g.
- mips) it is really awkward to have FRAME_CHAIN_VALID called
- BEFORE DEPRECATED_INIT_EXTRA_FRAME_INFO (there is no good way to
- get information deduced in FRAME_CHAIN_VALID into the extra
- fields of the new frame). std_frame_pc(fromleaf, prev)
+ mips) it is really awkward to have DEPRECATED_FRAME_CHAIN_VALID
+ called BEFORE DEPRECATED_INIT_EXTRA_FRAME_INFO (there is no good
+ way to get information deduced in DEPRECATED_FRAME_CHAIN_VALID
+ into the extra fields of the new frame). std_frame_pc(fromleaf,
+ prev)
This is the default setting for INIT_PREV_FRAME. It just does
what the default DEPRECATED_INIT_FRAME_PC does. Some machines
@@ -1273,13 +1275,14 @@ legacy_get_prev_frame (struct frame_info *this_frame)
means that the convolution below - needing to carefully order a
frame's initialization - isn't needed.
- The irony here though, is that FRAME_CHAIN(), at least for a more
- up-to-date architecture, always calls FRAME_SAVED_PC(), and
- FRAME_SAVED_PC() computes the PC but without first needing the
- frame! Instead of the convolution below, we could have simply
- called FRAME_SAVED_PC() and been done with it! Note that
- FRAME_SAVED_PC() is being superseed by frame_pc_unwind() and that
- function does have somewhere to cache that PC value. */
+ The irony here though, is that DEPRECATED_FRAME_CHAIN(), at least
+ for a more up-to-date architecture, always calls
+ FRAME_SAVED_PC(), and FRAME_SAVED_PC() computes the PC but
+ without first needing the frame! Instead of the convolution
+ below, we could have simply called FRAME_SAVED_PC() and been done
+ with it! Note that FRAME_SAVED_PC() is being superseed by
+ frame_pc_unwind() and that function does have somewhere to cache
+ that PC value. */
if (DEPRECATED_INIT_FRAME_PC_FIRST_P ())
prev->pc = (DEPRECATED_INIT_FRAME_PC_FIRST (fromleaf, prev));
@@ -1295,8 +1298,9 @@ legacy_get_prev_frame (struct frame_info *this_frame)
/* If ->frame and ->pc are unchanged, we are in the process of
getting ourselves into an infinite backtrace. Some architectures
- check this in FRAME_CHAIN or thereabouts, but it seems like there
- is no reason this can't be an architecture-independent check. */
+ check this in DEPRECATED_FRAME_CHAIN or thereabouts, but it seems
+ like there is no reason this can't be an architecture-independent
+ check. */
if (prev->frame == this_frame->frame
&& prev->pc == this_frame->pc)
{
@@ -1463,6 +1467,38 @@ get_prev_frame (struct frame_info *this_frame)
return prev_frame;
}
+ /* Check that this frame's ID was valid. If it wasn't, don't try to
+ unwind to the prev frame. Be careful to not apply this test to
+ the sentinel frame. */
+ if (this_frame->level >= 0 && !frame_id_p (get_frame_id (this_frame)))
+ {
+ if (frame_debug)
+ fprintf_filtered (gdb_stdlog,
+ "Outermost frame - this ID is NULL\n");
+ return NULL;
+ }
+
+ /* Check that this frame's ID isn't inner to (younger, below, next)
+ the next frame. This happens when frame unwind goes backwards.
+ Since the sentinel frame isn't valid, don't apply this if this
+ frame is entier the inner-most or sentinel frame. */
+ if (this_frame->level > 0
+ && frame_id_inner (get_frame_id (this_frame),
+ get_frame_id (this_frame->next)))
+ error ("This frame inner-to next frame (corrupt stack?)");
+
+ /* Check that this and the next frame are different. If they are
+ not, there is most likely a stack cycle. As with the inner-than
+ test, avoid the inner-most and sentinel frames. */
+ /* FIXME: cagney/2003-03-17: Can't yet enable this this check. The
+ frame_id_eq() method doesn't yet use function addresses when
+ comparing frame IDs. */
+ if (0
+ && this_frame->level > 0
+ && frame_id_eq (get_frame_id (this_frame),
+ get_frame_id (this_frame->next)))
+ error ("This frame identical to next frame (corrupt stack?)");
+
/* 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
@@ -1483,8 +1519,9 @@ get_prev_frame (struct frame_info *this_frame)
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
+ frame_pc_unwind (nee, FRAME_SAVED_PC) and
+ DEPRECATED_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.
@@ -1528,38 +1565,17 @@ get_prev_frame (struct frame_info *this_frame)
&prev_frame->prologue_cache,
&prev_frame->id);
- /* Check that the unwound ID is valid. */
- if (!frame_id_p (prev_frame->id))
- {
- if (frame_debug)
- fprintf_unfiltered (gdb_stdlog,
- "Outermost 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 true `sentinel'. Leave it until after the
- switch to storing the frame ID, instead of the frame base, in the
- frame object. */
- if (this_frame->level >= 0
- && frame_id_inner (prev_frame->id, get_frame_id (this_frame)))
- error ("Unwound frame inner-to selected frame (corrupt stack?)");
-
- /* FIXME: cagney/2003-03-14: Should check that this and next frame's
- IDs are different (i.e., !frame_id_eq()). Can't yet do that as
- the EQ function doesn't yet compare PC values. */
-
- /* FIXME: cagney/2003-03-14: Should delay the evaluation of the
- frame ID until when it is needed. That way the inner most frame
- can be created without needing to do prologue analysis. */
+ /* The unwound frame ID is validate at the start of this function,
+ as part of the logic to decide if that frame should be further
+ unwound, and not here while the prev frame is being created.
+ Doing this makes it possible for the user to examine a frame that
+ has an invalid frame ID.
- /* Note that, due to frameless functions, the stronger test of the
- new frame being outer to the old frame can't be used - frameless
- functions differ by only their PC value. */
+ The very old VAX frame_args_address_correct() method noted: [...]
+ For the sake of argument, suppose that the stack is somewhat
+ trashed (which is one reason that "info frame" exists). So,
+ return 0 (indicating we don't know the address of the arglist) if
+ we don't know what frame this frame calls. */
/* FIXME: cagney/2002-12-18: Instead of this hack, should only store
the frame ID in PREV_FRAME. Unfortunatly, some architectures
@@ -1782,7 +1798,7 @@ 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 ()
+ || DEPRECATED_FRAME_CHAIN_P ()
|| !gdbarch_unwind_dummy_id_p (current_gdbarch)
|| !SAVE_DUMMY_FRAME_TOS_P ());
}