summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cagney <cagney@redhat.com>2003-03-13 21:43:34 +0000
committerAndrew Cagney <cagney@redhat.com>2003-03-13 21:43:34 +0000
commit5422b5d2fa74279625100e408edc6e31b9e57b03 (patch)
treee4b579eaebecd246483a3ae141d6939e0e13bdcc
parent01d8344e9f2cae907cbea8a79e9854ca8e72a36b (diff)
downloadbinutils-gdb-offbyone-20030313-branch.tar.gz
2003-03-13 Andrew Cagney <cagney@redhat.com>offbyone-20030313-branch
* frame.c (legacy_saved_regs_this_id): Handle a sentinel frame. (get_prev_frame): Simplify. Frame ID logic moved to dummy_frame_this_id and legacy_saved_regs_this_id.
-rw-r--r--gdb/ChangeLog4
-rw-r--r--gdb/frame.c180
2 files changed, 73 insertions, 111 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c634d4cbde9..5565723af9e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,9 @@
2003-03-13 Andrew Cagney <cagney@redhat.com>
+ * frame.c (legacy_saved_regs_this_id): Handle a sentinel frame.
+ (get_prev_frame): Simplify. Frame ID logic moved to
+ dummy_frame_this_id and legacy_saved_regs_this_id.
+
* 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.
diff --git a/gdb/frame.c b/gdb/frame.c
index 002a306fb62..3050a58104d 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -745,30 +745,40 @@ 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;
/* Start out by assuming it's NULL. */
(*id) = null_frame_id;
- if (frame_relative_level (next_frame) <= 0)
- /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
- the frame chain, not just the inner most frame! The generic,
- per-architecture, frame code should handle this and the below
- should simply be removed. */
- fromleaf = FRAMELESS_FUNCTION_INVOCATION (next_frame);
- else
- fromleaf = 0;
-
- if (fromleaf)
- /* A frameless inner-most frame. The `FP' (which isn't an
- architecture frame-pointer register!) of the caller is the same
- as the callee. */
- /* FIXME: 2002-11-09: There isn't any reason to special case this
- edge condition. Instead the per-architecture code should hande
- it locally. */
- base = get_frame_base (next_frame);
+ if (frame_relative_level (next_frame) < 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. */
+ base = read_fp ();
+ pc = read_pc ();
+ }
+ else if (frame_relative_level (next_frame) == 0
+ && FRAMELESS_FUNCTION_INVOCATION (next_frame))
+ {
+ /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
+ the frame chain, not just the inner most frame! The generic,
+ per-architecture, frame code should handle this and the below
+ should simply be removed. */
+ /* A frameless inner-most frame. The `FP' (which isn't an
+ architecture frame-pointer register!) of the caller is the
+ same as the callee. */
+ /* FIXME: 2002-11-09: There isn't any reason to special case
+ this edge condition. Instead the per-architecture code
+ should hande it locally. */
+ base = get_frame_base (next_frame);
+ /* FIXME: cagney/2002-06-08: This should probably return the frame's
+ function and not the PC (a.k.a. resume address). */
+ pc = frame_pc_unwind (next_frame);
+ }
else
{
/* Two macros defined in tm.h specify the machine-dependent
@@ -788,16 +798,12 @@ legacy_saved_regs_this_id (struct frame_info *next_frame,
main. */
gdb_assert (FRAME_CHAIN_P ());
base = FRAME_CHAIN (next_frame);
-
if (!frame_chain_valid (base, next_frame))
return;
+ /* FIXME: cagney/2002-06-08: This should probably return the
+ frame's function and not the PC (a.k.a. resume address). */
+ pc = frame_pc_unwind (next_frame);
}
- if (base == 0)
- return;
-
- /* FIXME: cagney/2002-06-08: This should probably return the frame's
- function and not the PC (a.k.a. resume address). */
- pc = frame_pc_unwind (next_frame);
id->pc = pc;
id->base = base;
}
@@ -1385,97 +1391,49 @@ get_prev_frame (struct frame_info *this_frame)
prev_frame->pc);
/* Find the prev's frame's ID. */
- switch (prev_frame->type)
- {
- 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. */
- 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;
- }
- break;
- case NORMAL_FRAME:
- case SIGTRAMP_FRAME:
- /* The callee expects to be invoked with:
- this->unwind->this_id (this->next, &this->cache, &this->id);
+ /* The callee expects to be invoked with:
- 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.
+ 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))
- {
- 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");
+ 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))
+ {
+ 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?)");
+
+ /* 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