This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]