* dwarf2-frame.c (dwarf2_frame_cache): Update comment.
authorDaniel Jacobowitz <drow@false.org>
Tue, 15 Jul 2008 18:40:03 +0000 (18:40 +0000)
committerDaniel Jacobowitz <drow@false.org>
Tue, 15 Jul 2008 18:40:03 +0000 (18:40 +0000)
* 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
gdb/dwarf2-frame.c
gdb/frame.c
gdb/frame.h
gdb/hppa-tdep.c

index fde0a10710c50c6a8f6aecefb7689431d4d0a38e..4715b19d5d09aeed65ac5d3bd0b14e34cf74b25d 100644 (file)
@@ -1,3 +1,13 @@
+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.
+
 2008-07-15  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * frame.c (frame_func_unwind): Delete.
index 3385bdb0f33b7050abf70d17bd45cb2e6401f615..bd1127cc218f08bf1c5c4ec0f1cd805d48600aa3 100644 (file)
@@ -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);
index 9f4aafe36aad896ab5088d49934e39bb5cf43f16..e387b47cf3b9a17c509b38dc1f528355bd44bab2 100644 (file)
@@ -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;
 
index b157ee533d4884acffb9aaf12a9d303c277e0c63..579b4237da099c04884a3c40b2997ede036a7444 100644 (file)
@@ -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.  */
 
index 8e9b507217feb76d6605e3cbc73642e54bc95773..ace04a3d93dc9f177f6694b74d60526eb0b5b3fa 100644 (file)
@@ -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