diff options
Diffstat (limited to 'gdb/frame.c')
-rw-r--r-- | gdb/frame.c | 180 |
1 files changed, 69 insertions, 111 deletions
diff --git a/gdb/frame.c b/gdb/frame.c index 002a306..3050a58 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 |