diff options
Diffstat (limited to 'gdb/frame.c')
-rw-r--r-- | gdb/frame.c | 122 |
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 ()); } |