This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[commit] Remove frame_unwind_address_in_block
- From: Daniel Jacobowitz <drow at false dot org>
- To: gdb-patches at sourceware dot org
- Date: Tue, 15 Jul 2008 14:44:41 -0400
- Subject: [commit] Remove frame_unwind_address_in_block
Another unwind function removal patch. Only
get_frame_address_in_block is called now. A side benefit to this
rewrite is that we can delay getting the type of the current frame,
since its next frame will be the sentinel; this saves a memory read.
Also tested on x86_64-linux and committed.
--
Daniel Jacobowitz
CodeSourcery
2008-07-15 Daniel Jacobowitz <dan@codesourcery.com>
* 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.
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.84
diff -u -p -r1.84 dwarf2-frame.c
--- dwarf2-frame.c 3 May 2008 23:24:17 -0000 1.84
+++ dwarf2-frame.c 15 Jul 2008 18:37:53 -0000
@@ -900,7 +900,7 @@ dwarf2_frame_cache (struct frame_info *t
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);
Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.245
diff -u -p -r1.245 frame.c
--- frame.c 15 Jul 2008 18:32:05 -0000 1.245
+++ frame.c 15 Jul 2008 18:37:53 -0000
@@ -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);
+ CORE_ADDR pc = get_frame_pc (this_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;
-}
+ struct frame_info *next_frame = this_frame->next;
-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));
+ /* 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;
Index: frame.h
===================================================================
RCS file: /cvs/src/src/gdb/frame.h,v
retrieving revision 1.165
diff -u -p -r1.165 frame.h
--- frame.h 15 Jul 2008 18:32:05 -0000 1.165
+++ frame.h 15 Jul 2008 18:37:53 -0000
@@ -281,13 +281,6 @@ extern CORE_ADDR get_frame_pc (struct fr
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. */
Index: hppa-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/hppa-tdep.c,v
retrieving revision 1.253
diff -u -p -r1.253 hppa-tdep.c
--- hppa-tdep.c 15 Jul 2008 18:32:05 -0000 1.253
+++ hppa-tdep.c 15 Jul 2008 18:37:53 -0000
@@ -1792,7 +1792,7 @@ hppa_find_unwind_entry_in_block (struct
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