diff options
author | Andrew Cagney <cagney@redhat.com> | 2003-03-17 14:23:50 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 2003-03-17 14:23:50 +0000 |
commit | 1557b85d755f3373e232f6c3acb643b1e2992eec (patch) | |
tree | 8d9eed64edb31e13673dcd85f70217211d83aa49 /gdb/frame.c | |
parent | 6edb7b34e7416add0d4142498db767ddc9ea19c7 (diff) | |
download | gdb-1557b85d755f3373e232f6c3acb643b1e2992eec.tar.gz |
2003-03-17 Andrew Cagney <cagney@redhat.com>cagney_lazyid-20030317-branchpoint
Fix frame off-by-one bug.
* frame-unwind.h (frame_this_id_ftype): Replace
frame_unwind_id_ftype.
(frame_prev_register_ftype): Replace frame_unwind_reg_ftype.
(struct frame_unwind): Replace "id" with "this_id". Replace "reg"
with "prev_register".
* frame-unwind.c (frame_unwind_find_by_pc): Return
legacy_saved_regs_unwind instead of trad_frame_unwind. Update
comment.
* dummy-frame.c (cached_find_dummy_frame): Delete function.
(dummy_frame_this_id): Replace dummy_frame_id_unwind.
(dummy_frame_prev_register): Replace dummy_frame_register_unwind.
(dummy_frame_unwind): Update.
* sentinel-frame.c (sentinel_frame_prev_register): Replace
sentinel_frame_register_unwind.
(sentinel_frame_this_id): Replace sentinel_frame_id_unwind.
(sentinel_frame_unwinder): Update.
* frame.h (legacy_saved_regs_unwind): Replace trad_frame_unwind.
(struct frame_info): Rename "unwind_cache" to "prologue_cache".
* frame.c (create_sentinel_frame): Update. Initialize
"prologue_cache" instead of "unwind_cache".
(frame_register_unwind): Call this frame's prev_register with the
next frame and this frame's prologue cache.
(get_prev_frame): Simplify. Always call prev frame's this_id with
this frame and prev frame's prologue cache. Document that this
call is shifted one to the left when compared to the
frame_register_unwind call.
(legacy_saved_regs_prev_register): Replace
frame_saved_regs_register_unwind.
(legacy_saved_regs_this_id): Replace frame_saved_regs_id_unwind.
(legacy_saved_regs_unwinder): Replace trad_frame_unwinder.
(legacy_saved_regs_unwind): Replace trad_frame_unwind.
* d10v-tdep.c (d10v_frame_this_id): Replace d10v_frame_id_unwind.
(d10v_frame_unwind): Update.
(d10v_frame_prev_register): Replace d10v_frame_register_unwind.
(d10v_frame_unwind_cache): Replace this "fi" with "next_frame".
(saved_regs_unwinder): Replace this "frame" with "next_frame", and
"saved_regs" with "this_saved_regs".
Diffstat (limited to 'gdb/frame.c')
-rw-r--r-- | gdb/frame.c | 176 |
1 files changed, 92 insertions, 84 deletions
diff --git a/gdb/frame.c b/gdb/frame.c index 178dfdfe5d9..900b51518c5 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -254,9 +254,12 @@ frame_register_unwind (struct frame_info *frame, int regnum, detected the problem before calling here. */ gdb_assert (frame != NULL); - /* Ask this frame to unwind its register. */ - frame->unwind->reg (frame, &frame->unwind_cache, regnum, - optimizedp, lvalp, addrp, realnump, bufferp); + /* Ask this frame to unwind its register. See comment in + "frame-unwind.h" for why NEXT frame and this unwind cace are + passed in. */ + frame->unwind->prev_register (frame->next, &frame->prologue_cache, regnum, + optimizedp, lvalp, addrp, realnump, bufferp); + } void @@ -490,7 +493,7 @@ create_sentinel_frame (struct regcache *regcache) /* Explicitly initialize the sentinel frame's cache. Provide it with the underlying regcache. In the future additional information, such as the frame's thread will be added. */ - frame->unwind_cache = sentinel_frame_cache (regcache); + frame->prologue_cache = sentinel_frame_cache (regcache); /* For the moment there is only one sentinel frame implementation. */ frame->unwind = sentinel_frame_unwind; /* Link this frame back to itself. The frame is self referential @@ -647,19 +650,20 @@ select_frame (struct frame_info *fi) most frame. */ static void -frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, - int regnum, int *optimizedp, - enum lval_type *lvalp, CORE_ADDR *addrp, - int *realnump, void *bufferp) +legacy_saved_regs_prev_register (struct frame_info *next_frame, + void **this_prologue_cache, + int regnum, int *optimizedp, + enum lval_type *lvalp, CORE_ADDR *addrp, + int *realnump, void *bufferp) { - /* There is always a frame at this point. And THIS is the frame - we're interested in. */ + /* HACK: New code is passed the next frame and this cache. + Unfortunatly, old code expects this frame. Since this is a + backward compatibility hack, cheat by walking one level along the + prologue chain to the frame the old code expects. + + Do not try this at home. Professional driver, closed course. */ + struct frame_info *frame = next_frame->prev; gdb_assert (frame != NULL); - /* If we're using generic dummy frames, we'd better not be in a call - dummy. (generic_call_dummy_register_unwind ought to have been called - instead.) */ - gdb_assert (!(DEPRECATED_USE_GENERIC_DUMMY_FRAMES - && (get_frame_type (frame) == DUMMY_FRAME))); /* Only (older) architectures that implement the DEPRECATED_FRAME_INIT_SAVED_REGS method should be using this @@ -697,13 +701,13 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, #if 1 /* Save each register value, as it is read in, in a frame based cache. */ - void **regs = (*cache); + void **regs = (*this_prologue_cache); if (regs == NULL) { int sizeof_cache = ((NUM_REGS + NUM_PSEUDO_REGS) * sizeof (void *)); regs = frame_obstack_zalloc (sizeof_cache); - (*cache) = regs; + (*this_prologue_cache) = regs; } if (regs[regnum] == NULL) { @@ -723,22 +727,33 @@ frame_saved_regs_register_unwind (struct frame_info *frame, void **cache, return; } - /* No luck, assume this and the next frame have the same register - value. Pass the request down the frame chain to the next frame. - Hopefully that will find the register's location, either in a - register or in memory. */ - frame_register (frame, regnum, optimizedp, lvalp, addrp, realnump, - bufferp); + /* No luck. Assume this and the next frame have the same register + value. Pass the unwind request down the frame chain to the next + frame. Hopefully that frame will find the register's location. */ + frame_register_unwind (next_frame, regnum, optimizedp, lvalp, addrp, + realnump, bufferp); } static void -frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache, - struct frame_id *id) +legacy_saved_regs_this_id (struct frame_info *next_frame, + void **this_prologue_cache, + struct frame_id *id) { int fromleaf; CORE_ADDR base; CORE_ADDR pc; + if (frame_relative_level (next_frame) < 0) + { + /* FIXME: cagney/2003-03-14: We've got the extra special case of + 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. */ + (*id).base = read_fp (); + (*id).pc = read_pc (); + return; + } + /* Start out by assuming it's NULL. */ (*id) = null_frame_id; @@ -792,15 +807,14 @@ frame_saved_regs_id_unwind (struct frame_info *next_frame, void **cache, id->base = base; } -const struct frame_unwind trad_frame_unwinder = { - frame_saved_regs_id_unwind, - frame_saved_regs_register_unwind +const struct frame_unwind legacy_saved_regs_unwinder = { + legacy_saved_regs_this_id, + legacy_saved_regs_prev_register }; -const struct frame_unwind *trad_frame_unwind = &trad_frame_unwinder; +const struct frame_unwind *legacy_saved_regs_unwind = &legacy_saved_regs_unwinder; /* Function: deprecated_generic_get_saved_register - Find register number REGNUM relative to FRAME and put its (raw, target format) contents in *RAW_BUFFER. @@ -1496,63 +1510,57 @@ get_prev_frame (struct frame_info *this_frame) prev_frame->pc); /* Find the prev's frame's ID. */ - switch (prev_frame->type) + + /* The callee expects to be invoked with: + + this->unwind->this_id (this->next, &this->cache, &this->id); + + The below is carefully shifted one frame `to the left' so that + both the unwind->this_id and unwind->prev_register methods are + consistently invoked with NEXT_FRAME and THIS_PROLOGUE_CACHE. + + Also note that, while the PC for this new previous frame was + unwound first (see above), the below is the first call that + [potentially] requires analysis of the new previous frame's + prologue. Consequently, it is this call, that typically ends up + initializing the previous frame's prologue cache. */ + prev_frame->unwind->this_id (this_frame, + &prev_frame->prologue_cache, + &prev_frame->id); + + /* Check that the unwound ID is valid. */ + if (!frame_id_p (prev_frame->id)) { - case DUMMY_FRAME: - /* 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. */ - 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: - /* FIXME: cagney/2003-03-04: The below call isn't right. It - should instead be doing something like "prev_frame -> unwind - -> id (this_frame, & prev_frame -> unwind_cache, & prev_frame - -> id)" but that requires more extensive (pending) changes. */ - this_frame->unwind->id (this_frame, &this_frame->unwind_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 `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?)"); - /* 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. */ - break; - default: - internal_error (__FILE__, __LINE__, "bad switch"); + 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. */ + + /* 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. */ + /* 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 |