From ad1193e7adcb51147335bf83e6229b3ea47bb4b8 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Tue, 15 Jul 2008 18:40:03 +0000 Subject: [PATCH] * dwarf2-frame.c (dwarf2_frame_cache): Update comment. * frame.c (frame_unwind_address_in_block): Delete. (get_frame_address_in_block): Do not use it. Check the type of the next frame first. (frame_cleanup_after_sniffer): Update comment. * frame.h (frame_unwind_address_in_block): Delete prototype. * hppa-tdep.c (hppa_find_unwind_entry_in_block): Update comment. --- gdb/ChangeLog | 10 +++++++ gdb/dwarf2-frame.c | 2 +- gdb/frame.c | 77 +++++++++++++++++++++++++++++++----------------------- gdb/frame.h | 7 ----- gdb/hppa-tdep.c | 2 +- 5 files changed, 56 insertions(+), 42 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index fde0a10..4715b19 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,15 @@ 2008-07-15 Daniel Jacobowitz + * dwarf2-frame.c (dwarf2_frame_cache): Update comment. + * frame.c (frame_unwind_address_in_block): Delete. + (get_frame_address_in_block): Do not use it. Check the type + of the next frame first. + (frame_cleanup_after_sniffer): Update comment. + * frame.h (frame_unwind_address_in_block): Delete prototype. + * hppa-tdep.c (hppa_find_unwind_entry_in_block): Update comment. + +2008-07-15 Daniel Jacobowitz + * frame.c (frame_func_unwind): Delete. (get_frame_func): Do not use it. * frame.h (frame_func_unwind): Delete prototype. diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 3385bdb..bd1127c 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -900,7 +900,7 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) instruction in the associated delay slot). This should only be done for "normal" frames and not for resume-type frames (signal handlers, sentinel frames, dummy frames). The function - frame_unwind_address_in_block does just this. It's not clear how + get_frame_address_in_block does just this. It's not clear how reliable the method is though; there is the potential for the register state pre-call being different to that on return. */ fs->pc = get_frame_address_in_block (this_frame); diff --git a/gdb/frame.c b/gdb/frame.c index 9f4aafe..e387b47 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1536,43 +1536,54 @@ get_frame_pc (struct frame_info *frame) return frame_pc_unwind (frame->next); } -/* Return an address that falls within NEXT_FRAME's caller's code - block, assuming that the caller is a THIS_TYPE frame. */ +/* Return an address that falls within THIS_FRAME's code block. */ CORE_ADDR -frame_unwind_address_in_block (struct frame_info *next_frame, - enum frame_type this_type) +get_frame_address_in_block (struct frame_info *this_frame) { /* A draft address. */ - CORE_ADDR pc = frame_pc_unwind (next_frame); - - /* If NEXT_FRAME was called by a signal frame or dummy frame, then - we shold not adjust the unwound PC. These frames may not call - their next frame in the normal way; the operating system or GDB - may have pushed their resume address manually onto the stack, so - it may be the very first instruction. Even if the resume address - was not manually pushed, they expect to be returned to. */ - if (this_type != NORMAL_FRAME) - return pc; - - /* If THIS frame is not inner most (i.e., NEXT isn't the sentinel), - and NEXT is `normal' (i.e., not a sigtramp, dummy, ....) THIS - frame's PC ends up pointing at the instruction following the - "call". Adjust that PC value so that it falls on the call - instruction (which, hopefully, falls within THIS frame's code - block). So far it's proved to be a very good approximation. See - get_frame_type() for why ->type can't be used. */ - if (next_frame->level >= 0 - && get_frame_type (next_frame) == NORMAL_FRAME) - --pc; - return pc; -} + CORE_ADDR pc = get_frame_pc (this_frame); -CORE_ADDR -get_frame_address_in_block (struct frame_info *this_frame) -{ - return frame_unwind_address_in_block (this_frame->next, - get_frame_type (this_frame)); + struct frame_info *next_frame = this_frame->next; + + /* Calling get_frame_pc returns the resume address for THIS_FRAME. + Normally the resume address is inside the body of the function + associated with THIS_FRAME, but there is a special case: when + calling a function which the compiler knows will never return + (for instance abort), the call may be the very last instruction + in the calling function. The resume address will point after the + call and may be at the beginning of a different function + entirely. + + If THIS_FRAME is a signal frame or dummy frame, then we should + not adjust the unwound PC. For a dummy frame, GDB pushed the + resume address manually onto the stack. For a signal frame, the + OS may have pushed the resume address manually and invoked the + handler (e.g. GNU/Linux), or invoked the trampoline which called + the signal handler - but in either case the signal handler is + expected to return to the trampoline. So in both of these + cases we know that the resume address is executable and + related. So we only need to adjust the PC if THIS_FRAME + is a normal function. + + If the program has been interrupted while THIS_FRAME is current, + then clearly the resume address is inside the associated + function. There are three kinds of interruption: debugger stop + (next frame will be SENTINEL_FRAME), operating system + signal or exception (next frame will be SIGTRAMP_FRAME), + or debugger-induced function call (next frame will be + DUMMY_FRAME). So we only need to adjust the PC if + NEXT_FRAME is a normal function. + + We check the type of NEXT_FRAME first, since it is already + known; frame type is determined by the unwinder, and since + we have THIS_FRAME we've already selected an unwinder for + NEXT_FRAME. */ + if (get_frame_type (next_frame) == NORMAL_FRAME + && get_frame_type (this_frame) == NORMAL_FRAME) + return pc - 1; + + return pc; } static int @@ -1835,7 +1846,7 @@ frame_cleanup_after_sniffer (void *arg) /* Clear cached fields dependent on the unwinder. The previous PC is independent of the unwinder, but the previous - function is not (see frame_unwind_address_in_block). */ + function is not (see get_frame_address_in_block). */ frame->prev_func.p = 0; frame->prev_func.addr = 0; diff --git a/gdb/frame.h b/gdb/frame.h index b157ee5..579b423 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -281,13 +281,6 @@ extern CORE_ADDR get_frame_pc (struct frame_info *); extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame); -/* Similar to get_frame_address_in_block, find an address in the - block which logically called NEXT_FRAME, assuming it is a THIS_TYPE - frame. */ - -extern CORE_ADDR frame_unwind_address_in_block (struct frame_info *next_frame, - enum frame_type this_type); - /* The frame's inner-most bound. AKA the stack-pointer. Confusingly known as top-of-stack. */ diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 8e9b507..ace04a3 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1792,7 +1792,7 @@ hppa_find_unwind_entry_in_block (struct frame_info *this_frame) CORE_ADDR pc = get_frame_address_in_block (this_frame); /* FIXME drow/20070101: Calling gdbarch_addr_bits_remove on the - result of frame_unwind_address_in_block implies a problem. + result of get_frame_address_in_block implies a problem. The bits should have been removed earlier, before the return value of frame_pc_unwind. That might be happening already; if it isn't, it should be fixed. Then this call can be -- 2.7.4