OSDN Git Service

2004-11-08 Andrew Cagney <cagney@gnu.org>
authorAndrew Cagney <cagney@redhat.com>
Tue, 9 Nov 2004 01:16:42 +0000 (01:16 +0000)
committerAndrew Cagney <cagney@redhat.com>
Tue, 9 Nov 2004 01:16:42 +0000 (01:16 +0000)
* sentinel-frame.c (sentinel_frame_prev_pc): New function.
(sentinel_frame_unwinder): Add the prev_pc method.
* frame.c (frame_pc_unwind): Use the per-frame pc unwinder when
available.  Do not handle the sentinel-frame case.
* frame-unwind.h (frame_prev_register_ftype): Define.
(struct frame_unwind): Add prev_pc;

gdb/ChangeLog
gdb/frame-unwind.h
gdb/frame.c
gdb/sentinel-frame.c

index 552f75d..e5207e7 100644 (file)
@@ -1,3 +1,12 @@
+2004-11-08  Andrew Cagney  <cagney@gnu.org>
+
+       * sentinel-frame.c (sentinel_frame_prev_pc): New function.
+       (sentinel_frame_unwinder): Add the prev_pc method.
+       * frame.c (frame_pc_unwind): Use the per-frame pc unwinder when
+       available.  Do not handle the sentinel-frame case.
+       * frame-unwind.h (frame_prev_register_ftype): Define.
+       (struct frame_unwind): Add prev_pc;
+
 2004-11-08  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        * configure.in: Check for ncurses/term.h.
index 12d6dd2..74c0a4a 100644 (file)
@@ -118,6 +118,14 @@ typedef void (frame_prev_register_ftype) (struct frame_info *next_frame,
                                          CORE_ADDR *addrp,
                                          int *realnump, void *valuep);
 
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+   use the NEXT frame, and its register unwind method, to return the PREV
+   frame's program-counter.  */
+
+typedef CORE_ADDR (frame_prev_pc_ftype) (struct frame_info *next_frame,
+                                        void **this_prologue_cache);
+
+
 struct frame_unwind
 {
   /* The frame's type.  Should this instead be a collection of
@@ -129,6 +137,7 @@ struct frame_unwind
   frame_prev_register_ftype *prev_register;
   const struct frame_data *unwind_data;
   frame_sniffer_ftype *sniffer;
+  frame_prev_pc_ftype *prev_pc;
 };
 
 /* Register a frame unwinder, _prepending_ it to the front of the
index d9de0e6..61a9520 100644 (file)
@@ -390,7 +390,15 @@ frame_pc_unwind (struct frame_info *this_frame)
   if (!this_frame->prev_pc.p)
     {
       CORE_ADDR pc;
-      if (gdbarch_unwind_pc_p (current_gdbarch))
+      if (this_frame->unwind == NULL)
+       this_frame->unwind
+         = frame_unwind_find_by_frame (this_frame->next,
+                                       &this_frame->prologue_cache);
+      if (this_frame->unwind->prev_pc != NULL)
+       /* A per-frame unwinder, prefer it.  */
+       pc = this_frame->unwind->prev_pc (this_frame->next,
+                                         &this_frame->prologue_cache);
+      else if (gdbarch_unwind_pc_p (current_gdbarch))
        {
          /* The right way.  The `pure' way.  The one true way.  This
             method depends solely on the register-unwind code to
@@ -410,17 +418,8 @@ frame_pc_unwind (struct frame_info *this_frame)
             different ways that a PC could be unwound.  */
          pc = gdbarch_unwind_pc (current_gdbarch, this_frame);
        }
-      else if (this_frame->level < 0)
-       {
-         /* FIXME: cagney/2003-03-06: Old code and a sentinel
-             frame.  Do like was always done.  Fetch the PC's value
-             directly from the global registers array (via read_pc).
-             This assumes that this frame belongs to the current
-             global register cache.  The assumption is dangerous.  */
-         pc = read_pc ();
-       }
       else
-       internal_error (__FILE__, __LINE__, "No gdbarch_unwind_pc method");
+       internal_error (__FILE__, __LINE__, "No unwind_pc method");
       this_frame->prev_pc.value = pc;
       this_frame->prev_pc.p = 1;
       if (frame_debug)
index f1e5c7f..b17bc82 100644 (file)
@@ -81,11 +81,22 @@ sentinel_frame_this_id (struct frame_info *next_frame,
   internal_error (__FILE__, __LINE__, "sentinel_frame_this_id called");
 }
 
+static CORE_ADDR
+sentinel_frame_prev_pc (struct frame_info *next_frame,
+                       void **this_prologue_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (next_frame);
+  return gdbarch_unwind_pc (gdbarch, next_frame);
+}
+
 const struct frame_unwind sentinel_frame_unwinder =
 {
   SENTINEL_FRAME,
   sentinel_frame_this_id,
-  sentinel_frame_prev_register
+  sentinel_frame_prev_register,
+  NULL, /* unwind_data */
+  NULL, /* sniffer */
+  sentinel_frame_prev_pc,
 };
 
 const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder;