]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2003-03-04 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Tue, 4 Mar 2003 23:15:24 +0000 (23:15 +0000)
committerAndrew Cagney <cagney@redhat.com>
Tue, 4 Mar 2003 23:15:24 +0000 (23:15 +0000)
* d10v-tdep.c (d10v_frame_unwind_cache): Update to work with
NEXT_FRAME and THIS_CACHE.
(d10v_frame_pc_unwind): Ditto.
(d10v_frame_id_unwind): Ditto.
(saved_regs_unwinder): Ditto.
(d10v_frame_register_unwind): Ditto.
* dummy-frame.c (dummy_frame_register_unwind): Ditto.
(dummy_frame_pc_unwind): Ditto.
(cached_find_dummy_frame): Ditto.
(dummy_frame_id_unwind): Ditto.
(dummy_frame_pop): Ditto.
* sentinel-frame.c (sentinel_frame_register_unwind): Ditto.
(sentinel_frame_pc_unwind): Ditto.
(sentinel_frame_id_unwind): Ditto.
(sentinel_frame_pop): Ditto.
* frame.c (frame_id_unwind): Reinstate function.
* frame.h (frame_id_unwind): Reinstate declaration.
* frame.c (frame_pc_unwind): Pass frame->next to the PC's unwind
method.
(frame_pop, frame_register_unwind): Ditto.
* frame-unwind.h (frame_unwind_id_ftype, frame_unwind_reg_ftype)
(frame_unwind_pc_ftype, frame_unwind_pop_ftype): Re-specify
behavior in terms of PREV_REGNUM, THIS_CACHE and NEXT_FRAME.

gdb/ChangeLog
gdb/d10v-tdep.c
gdb/dummy-frame.c
gdb/frame-unwind.h
gdb/frame.c
gdb/frame.h
gdb/sentinel-frame.c

index d091e2e1dfe0b6cc345d26b1ceb03f935ba7325f..32b799017e5ce77cf2e6b6163e89086edd3f10d2 100644 (file)
@@ -1,3 +1,29 @@
+2003-03-04  Andrew Cagney  <cagney@redhat.com>
+
+       * d10v-tdep.c (d10v_frame_unwind_cache): Update to work with
+       NEXT_FRAME and THIS_CACHE.
+       (d10v_frame_pc_unwind): Ditto.
+       (d10v_frame_id_unwind): Ditto.
+       (saved_regs_unwinder): Ditto.
+       (d10v_frame_register_unwind): Ditto.
+       * dummy-frame.c (dummy_frame_register_unwind): Ditto.
+       (dummy_frame_pc_unwind): Ditto.
+       (cached_find_dummy_frame): Ditto.
+       (dummy_frame_id_unwind): Ditto.
+       (dummy_frame_pop): Ditto.
+       * sentinel-frame.c (sentinel_frame_register_unwind): Ditto.
+       (sentinel_frame_pc_unwind): Ditto.
+       (sentinel_frame_id_unwind): Ditto.
+       (sentinel_frame_pop): Ditto.
+       * frame.c (frame_id_unwind): Reinstate function.
+       * frame.h (frame_id_unwind): Reinstate declaration.
+       * frame.c (frame_pc_unwind): Pass frame->next to the PC's unwind
+       method.
+       (frame_pop, frame_register_unwind): Ditto.
+       * frame-unwind.h (frame_unwind_id_ftype, frame_unwind_reg_ftype)
+       (frame_unwind_pc_ftype, frame_unwind_pop_ftype): Re-specify
+       behavior in terms of PREV_REGNUM, THIS_CACHE and NEXT_FRAME.
+
 2003-03-03  Andrew Cagney  <cagney@redhat.com>
 
        * frame.c (frame_id_unwind): Delete function.
index addf9caee9683b8f2b5ee5119bd98902b7340604..9111aa318d5438955095f64040ec9f8c9f619d7c 100644 (file)
 
 #include "gdb_assert.h"
 
+static void d10v_frame_register_unwind (struct frame_info *next_frame,
+                                       void **this_cache,
+                                       int prev_regnum, int *optimizedp,
+                                       enum lval_type *lvalp,
+                                       CORE_ADDR *addrp,
+                                       int *realnump, void *bufferp);
+
+
 struct frame_extra_info
   {
     CORE_ADDR return_pc;
@@ -616,7 +624,7 @@ d10v_skip_prologue (CORE_ADDR pc)
 
 struct d10v_unwind_cache
 {
-  CORE_ADDR return_pc;
+  CORE_ADDR base;
   int frameless;
   int size;
   CORE_ADDR *saved_regs;
@@ -698,30 +706,30 @@ prologue_find_regs (struct d10v_unwind_cache *info, unsigned short op,
    for it IS the sp for the next frame. */
 
 struct d10v_unwind_cache *
-d10v_frame_unwind_cache (struct frame_info *fi,
-                        void **cache)
+d10v_frame_unwind_cache (struct frame_info *next_frame,
+                        void **this_cache)
 {
-  CORE_ADDR fp, pc;
+  CORE_ADDR pc;
+  ULONGEST sp;
+  ULONGEST base;
   unsigned long op;
   unsigned short op1, op2;
   int i;
   struct d10v_unwind_cache *info;
 
-  if ((*cache))
-    return (*cache);
+  if ((*this_cache))
+    return (*this_cache);
 
   info = FRAME_OBSTACK_ZALLOC (struct d10v_unwind_cache);
-  (*cache) = info;
+  (*this_cache) = info;
   info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
 
   info->frameless = 0;
   info->size = 0;
-  info->return_pc = 0;
 
-  fp = get_frame_base (fi);
   info->next_addr = 0;
 
-  pc = get_pc_function_start (get_frame_pc (fi));
+  pc = get_pc_function_start (frame_pc_unwind (next_frame));
 
   info->uses_frame = 0;
   while (1)
@@ -776,45 +784,40 @@ d10v_frame_unwind_cache (struct frame_info *fi,
 
   info->size = -info->next_addr;
 
-  if (!(fp & 0xffff))
-    fp = d10v_read_sp ();
+  /* Start out with the frame's stack top.  */
+  frame_unwind_unsigned_register (next_frame, SP_REGNUM, &sp);
+  sp = d10v_make_daddr (sp);
 
   for (i = 0; i < NUM_REGS - 1; i++)
     if (info->saved_regs[i])
       {
-       info->saved_regs[i] = fp - (info->next_addr - info->saved_regs[i]);
+       info->saved_regs[i] = sp - (info->next_addr - info->saved_regs[i]);
       }
 
-  if (info->saved_regs[LR_REGNUM])
+  /* Compute the frame's base.  */
+  if (info->saved_regs[FP_REGNUM])
     {
-      CORE_ADDR return_pc 
-       = read_memory_unsigned_integer (info->saved_regs[LR_REGNUM], 
-                                       register_size (current_gdbarch, LR_REGNUM));
-      info->return_pc = d10v_make_iaddr (return_pc);
+      /* The FP was saved, which means that the current FP is live.
+         Unwind its value from the NEXT frame.  */
+      frame_unwind_unsigned_register (next_frame, FP_REGNUM, &base);
     }
-  else
+  else if (info->saved_regs[SP_REGNUM])
     {
-      ULONGEST return_pc;
-      frame_read_unsigned_register (fi, LR_REGNUM, &return_pc);
-      info->return_pc = d10v_make_iaddr (return_pc);
+      /* The SP was saved (this is very unusual), the frame base is
+        just the PREV's frame's TOP-OF-STACK.  */
+      base = read_memory_unsigned_integer (info->saved_regs[SP_REGNUM], 
+                                          register_size (current_gdbarch,
+                                                         SP_REGNUM));
+      info->frameless = 1;
     }
-
-  /* The SP is not normally (ever?) saved, but check anyway */
-  if (!info->saved_regs[SP_REGNUM])
+  else
     {
-      /* if the FP was saved, that means the current FP is valid, */
-      /* otherwise, it isn't being used, so we use the SP instead */
-      if (info->uses_frame)
-       info->saved_regs[SP_REGNUM] 
-         = d10v_read_fp () + info->size;
-      else
-       {
-         info->saved_regs[SP_REGNUM] = fp + info->size;
-         info->frameless = 1;
-         info->saved_regs[FP_REGNUM] = 0;
-       }
+      /* Assume that the FP is this frame's SP but with that pushed
+         stack space added back.  */
+      frame_unwind_unsigned_register (next_frame, SP_REGNUM, &base);
+      base += info->size;
     }
-
+  info->base = d10v_make_daddr (base);
   return info;
 }
 
@@ -1423,95 +1426,93 @@ display_trace (int low, int high)
 
 
 static CORE_ADDR
-d10v_frame_pc_unwind (struct frame_info *frame,
-                     void **cache)
+d10v_frame_pc_unwind (struct frame_info *next_frame,
+                     void **this_cache)
 {
-  struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache);
-  return info->return_pc;
+  /* FIXME: This shouldn't be needed.  Instead a per-architecture
+     method should be called.  */
+  int optimized;
+  enum lval_type lval;
+  CORE_ADDR addr;
+  int realnum;
+  ULONGEST lr;
+  void *buffer = alloca (max_register_size (current_gdbarch));
+  d10v_frame_register_unwind (next_frame, this_cache, LR_REGNUM, 
+                             &optimized, &lval, &addr, &realnum,
+                             buffer);
+  lr = extract_unsigned_integer (buffer, register_size (current_gdbarch,
+                                                       LR_REGNUM));
+  return d10v_make_iaddr (lr);
+                       
 }
 
-/* Given a GDB frame, determine the address of the calling function's
+/* Given the next frame, determine the address of this function's
    frame.  This will be used to create a new GDB frame struct.  */
 
 static void
-d10v_frame_id_unwind (struct frame_info *frame,
-                     void **cache,
-                     struct frame_id *id)
+d10v_frame_id_unwind (struct frame_info *next_frame,
+                     void **this_cache,
+                     struct frame_id *this_id)
 {
-  struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache);
-  CORE_ADDR addr;
+  struct d10v_unwind_cache *info
+    = d10v_frame_unwind_cache (next_frame, this_cache);
+  CORE_ADDR base;
+  CORE_ADDR pc;
 
   /* Start with a NULL frame ID.  */
-  (*id) = null_frame_id;
+  (*this_id) = null_frame_id;
+
+  /* The PC is easy.  */
+  pc = frame_pc_unwind (next_frame);
 
-  if (info->return_pc == IMEM_START
-      || info->return_pc <= IMEM_START
-      || inside_entry_file (info->return_pc))
+  /* This is meant to halt the backtrace at "_start".  Make sure we
+     don't halt it at a generic dummy frame. */
+  if (pc == IMEM_START || pc <= IMEM_START || inside_entry_file (pc))
     {
-      /* This is meant to halt the backtrace at "_start".
-        Make sure we don't halt it at a generic dummy frame. */
       return;
     }
 
+#if 0
   if (!info->saved_regs[FP_REGNUM])
     {
       if (!info->saved_regs[SP_REGNUM]
          || info->saved_regs[SP_REGNUM] == STACK_START)
        return;
 
-      id->base = info->saved_regs[SP_REGNUM];
-      id->pc = info->return_pc;
+      this_id->base = info->saved_regs[SP_REGNUM];
+      this_id->pc = info->return_pc;
     }
 
   addr = read_memory_unsigned_integer (info->saved_regs[FP_REGNUM],
                                       register_size (current_gdbarch, FP_REGNUM));
   if (addr == 0)
     return;
+#endif
 
-  id->base = d10v_make_daddr (addr);
-  id->pc = info->return_pc;
+  /* Hopefully the prolog analysis has correctly determined the
+     frame's base.  */
+  this_id->base = info->base;
+  this_id->pc = pc;
 }
 
 static void
-saved_regs_unwinder (struct frame_info *frame,
+saved_regs_unwinder (struct frame_info *next_frame,
                     CORE_ADDR *saved_regs,
-                    int regnum, int *optimizedp,
+                    int prev_regnum, int *optimizedp,
                     enum lval_type *lvalp, CORE_ADDR *addrp,
                     int *realnump, void *bufferp)
 {
-  /* If we're using generic dummy frames, we'd better not be in a call
-     dummy.  (generic_call_dummy_register_unwind ought to have been called
-     instead.)  */
-  gdb_assert (!(DEPRECATED_USE_GENERIC_DUMMY_FRAMES
-               && (get_frame_type (frame) == DUMMY_FRAME)));
-
-  if (saved_regs[regnum] != 0)
+  if (saved_regs[prev_regnum] != 0)
     {
-      if (regnum == SP_REGNUM)
+      *optimizedp = 0;
+      *lvalp = lval_memory;
+      *addrp = saved_regs[prev_regnum];
+      *realnump = -1;
+      if (bufferp != NULL)
        {
-         /* SP register treated specially.  */
-         *optimizedp = 0;
-         *lvalp = not_lval;
-         *addrp = 0;
-         *realnump = -1;
-         if (bufferp != NULL)
-           store_address (bufferp, register_size (current_gdbarch, regnum),
-                          saved_regs[regnum]);
-       }
-      else
-       {
-         /* Any other register is saved in memory, fetch it but cache
-            a local copy of its value.  */
-         *optimizedp = 0;
-         *lvalp = lval_memory;
-         *addrp = saved_regs[regnum];
-         *realnump = -1;
-         if (bufferp != NULL)
-           {
-             /* Read the value in from memory.  */
-             read_memory (saved_regs[regnum], bufferp,
-                          register_size (current_gdbarch, regnum));
-           }
+         /* Read the value in from memory.  */
+         read_memory (saved_regs[prev_regnum], bufferp,
+                      register_size (current_gdbarch, prev_regnum));
        }
       return;
     }
@@ -1520,20 +1521,23 @@ saved_regs_unwinder (struct frame_info *frame,
      value.  If a value is needed, pass the request on down the chain;
      otherwise just return an indication that the value is in the same
      register as the next frame.  */
-  frame_register (frame, regnum, optimizedp, lvalp, addrp,
-                 realnump, bufferp);
+  frame_register_unwind (next_frame, prev_regnum, optimizedp, lvalp, addrp,
+                        realnump, bufferp);
 }
 
 
 static void
-d10v_frame_register_unwind (struct frame_info *frame,
-                           void **cache,
-                           int regnum, int *optimizedp,
+d10v_frame_register_unwind (struct frame_info *next_frame,
+                           void **this_cache,
+                           int prev_regnum, int *optimizedp,
                            enum lval_type *lvalp, CORE_ADDR *addrp,
                            int *realnump, void *bufferp)
 {
-  struct d10v_unwind_cache *info = d10v_frame_unwind_cache (frame, cache);
-  saved_regs_unwinder (frame, info->saved_regs, regnum, optimizedp,
+  struct d10v_unwind_cache *info
+    = d10v_frame_unwind_cache (next_frame, this_cache);
+  if (prev_regnum == PC_REGNUM)
+    prev_regnum = LR_REGNUM;
+  saved_regs_unwinder (next_frame, info->saved_regs, prev_regnum, optimizedp,
                       lvalp, addrp, realnump, bufferp);
 }
 
index 5b638306fd3956ed7733e96f0308e92d7e3fecc8..6812ed92d1e769ee40523a19fbe668b4a2d7c017 100644 (file)
@@ -105,11 +105,12 @@ find_dummy_frame (CORE_ADDR pc, CORE_ADDR fp)
 }
 
 struct dummy_frame *
-cached_find_dummy_frame (struct frame_info *frame, void **cache)
+cached_find_dummy_frame (struct frame_info *next_frame, void **this_cache)
 {
-  if ((*cache) == NULL)
-    (*cache) = find_dummy_frame (get_frame_pc (frame), get_frame_base (frame));
-  return (*cache);
+  if ((*this_cache) == NULL)
+    (*this_cache) = find_dummy_frame (frame_pc_unwind (next_frame),
+                                     frame_id_unwind (next_frame).base);
+  return (*this_cache);
 }
 
 struct regcache *
@@ -286,13 +287,13 @@ discard_innermost_dummy (struct dummy_frame **stack)
    dummy stack frame. */
 
 static void
-dummy_frame_pop (struct frame_info *fi, void **cache,
+dummy_frame_pop (struct frame_info *next_frame, void **this_cache,
                 struct regcache *regcache)
 {
-  struct dummy_frame *dummy = cached_find_dummy_frame (fi, cache);
+  struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache);
 
   /* If it isn't, what are we even doing here?  */
-  gdb_assert (get_frame_type (fi) == DUMMY_FRAME);
+  /* gdb_assert (get_frame_type (fi) == DUMMY_FRAME); */
 
   if (dummy == NULL)
     error ("Can't pop dummy frame!");
@@ -344,12 +345,12 @@ generic_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
    register value is taken from the local copy of the register buffer.  */
 
 static void
-dummy_frame_register_unwind (struct frame_info *frame, void **cache,
-                            int regnum, int *optimized,
+dummy_frame_register_unwind (struct frame_info *next_frame, void **this_cache,
+                            int prev_regnum, int *optimized,
                             enum lval_type *lvalp, CORE_ADDR *addrp,
                             int *realnum, void *bufferp)
 {
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
+  struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache);
   gdb_assert (dummy != NULL);
 
   /* Describe the register's location.  Generic dummy frames always
@@ -366,7 +367,7 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache,
       /* Use the regcache_cooked_read() method so that it, on the fly,
          constructs either a raw or pseudo register from the raw
          register cache.  */
-      regcache_cooked_read (dummy->regcache, regnum, bufferp);
+      regcache_cooked_read (dummy->regcache, prev_regnum, bufferp);
     }
 }
 
@@ -374,10 +375,10 @@ dummy_frame_register_unwind (struct frame_info *frame, void **cache,
    previous frame.  */
 
 static CORE_ADDR
-dummy_frame_pc_unwind (struct frame_info *frame,
-                      void **cache)
+dummy_frame_pc_unwind (struct frame_info *next_frame,
+                      void **this_cache)
 {
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
+  struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache);
   /* Oops!  In a dummy-frame but can't find the stack dummy.  Pretend
      that the frame doesn't unwind.  Should this function instead
      return a has-no-caller indication?  */
@@ -391,18 +392,18 @@ dummy_frame_pc_unwind (struct frame_info *frame,
    (the frame that the dummy has the saved state of).  */
 
 static void
-dummy_frame_id_unwind (struct frame_info *frame,
-                      void **cache,
-                      struct frame_id *id)
+dummy_frame_id_unwind (struct frame_info *next_frame,
+                      void **this_cache,
+                      struct frame_id *this_id)
 {
-  struct dummy_frame *dummy = cached_find_dummy_frame (frame, cache);
+  struct dummy_frame *dummy = cached_find_dummy_frame (next_frame, this_cache);
   /* Oops!  In a dummy-frame but can't find the stack dummy.  Pretend
      that the frame doesn't unwind.  Should this function instead
      return a has-no-caller indication?  */
   if (dummy == NULL)
-    (*id) = null_frame_id;
+    (*this_id) = null_frame_id;
   else
-    (*id) = dummy->id;
+    (*this_id) = dummy->id;
 }
 
 static struct frame_unwind dummy_frame_unwind =
index 2c67c969fb1a8177de6aadebb56026bf605a3a38..0ee0bc366d632bbd474510bad5736ee005d6ced6 100644 (file)
@@ -47,54 +47,102 @@ extern const struct frame_unwind *frame_unwind_find_by_pc (struct gdbarch
                                                           *gdbarch,
                                                           CORE_ADDR pc);
 
-/* Return the location (and possibly value) of REGNUM for the previous
-   (older, up) frame.  All parameters except VALUEP can be assumed to
-   be non NULL.  When VALUEP is NULL, just the location of the
-   register should be returned.
-
-   UNWIND_CACHE is provided as mechanism for implementing a per-frame
-   local cache.  It's initial value being NULL.  Memory for that cache
-   should be allocated using frame_obstack_zalloc().
-
-   Register window architectures (eg SPARC) should note that REGNUM
-   identifies the register for the previous frame.  For instance, a
-   request for the value of "o1" for the previous frame would be found
-   in the register "i1" in this FRAME.  */
-
-typedef void (frame_unwind_reg_ftype) (struct frame_info * frame,
-                                      void **unwind_cache,
-                                      int regnum,
+/* The following unwind functions all assume a frame chain like:
+   (outer) prev <-> this <-> next (inner); Even though some unwind to
+   THIS frame (frame ID) and others unwind the PREV frame, they are
+   all, consistently passed NEXT frame and THIS cache.
+
+   The intent is to clarify the relationship between NEXT frame and
+   THIS cache.  It is, of course, at the expense of confusing somewhat
+   the expected unwind behavior of PC/REG unwind VS ID unwind.  Sigh.  */
+
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+   use the NEXT frame, and its register unwind method, to determine
+   the frame ID of THIS frame.
+
+   A frame ID provides an invariant that can be used to re-identify an
+   instance of a frame.  It is a combination of the frame's `base' and
+   the frame's function's code.
+
+   Traditionally, THIS frame's ID was determined by examining THIS
+   frame's function's prologue and identifying which register/offset
+   are being used as THIS frame's base.
+
+   THIS_CACHE can be used to share any prolog analysis data with the
+   other unwind methods.  Memory for that cache should be allocated
+   using frame_obstack_zalloc().  */
+
+typedef void (frame_unwind_id_ftype) (struct frame_info *next_frame,
+                                     void **this_cache,
+                                     struct frame_id *this_id);
+
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+   use the NEXT frame, and its register unwind method, to unwind THIS
+   frame's registers, returning the value of REGNUM in PREV frame.
+
+   Traditionally, THIS frame's registers were unwound by examining
+   THIS frame's function's prologue and identifying which registers
+   that prolog code saved on the stack.
+
+   Ex: Assuming THIS is a frameless function that has saved the return
+   address (to PREV) in R1, then: a request to unwind THIS's PC
+   (returning the value of PC in PREV), becomes a request for the
+   value of R1 in THIS (that is where the value was saved), which
+   becomes a request to unwind R1 from NEXT.
+
+   THIS_CACHE can be used to share any prologue analysis data with the
+   other unwind methods.  Memory for that cache should be allocated
+   using frame_obstack_zalloc().  */
+
+typedef void (frame_unwind_reg_ftype) (struct frame_info *next_frame,
+                                      void **this_cache,
+                                      int prev_regnum,
                                       int *optimized,
                                       enum lval_type * lvalp,
                                       CORE_ADDR *addrp,
                                       int *realnump, void *valuep);
 
-/* Same as for registers above, but return the address at which the
-   calling frame would resume.  */
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+   use the NEXT frame, and its register unwind method, to unwind THIS
+   frame's PC, returning the value of PC (the return address) in PREV
+   frame.
 
-typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info * frame,
-                                          void **unwind_cache);
+   Traditionally, THIS frame's PC was unwound by examining THIS
+   frame's function prolog and identifying where (in a register or on
+   the stack) that return address was saved.
 
-/* Same as for registers above, but return the ID of the frame that
-   called this one.  */
+   Please note that this per-frame method may be superseeded by an
+   architecture specific method that determines the unwound PC (aka
+   return address) using just the register unwind methods.
 
-typedef void (frame_unwind_id_ftype) (struct frame_info * frame,
-                                     void **unwind_cache,
-                                     struct frame_id * id);
+   THIS_CACHE can be used to share any prologue analysis data with the
+   other unwind methods.  Memory for that cache should be allocated
+   using frame_obstack_zalloc().  */
 
-/* Discard the frame by restoring the registers (in regcache) back to
-   that of the caller.  */
-/* NOTE: cagney/2003-01-19: While at present the callers all pop each
+typedef CORE_ADDR (frame_unwind_pc_ftype) (struct frame_info *next_frame,
+                                          void **this_cache);
+
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
+   use the NEXT frame, and its register unwind method, to unwind THIS
+   frame's entire stack, writing PREV's frames register values into
+   REGCACHE.
+
+   NOTE: cagney/2003-01-19: While at present the callers all pop each
    frame in turn, the implementor should try to code things so that
-   any frame can be popped directly.  */
-/* FIXME: cagney/2003-01-19: Since both FRAME and REGCACHE refer to a
+   any frame can be popped directly.
+
+   FIXME: cagney/2003-01-19: Since both FRAME and REGCACHE refer to a
    common register cache, care must be taken when restoring the
    registers.  The `correct fix' is to first first save the registers
    in a scratch cache, and second write that scratch cache back to to
-   the real register cache.  */
+   the real register cache.
+
+   FIXME: cagney/2003-03-04: Isn't this entire function redundant?
+   Shouldn't the code instead just iterate through the restore
+   reggroup unwinding those registers?  */
 
-typedef void (frame_unwind_pop_ftype) (struct frame_info *frame,
-                                      void **unwind_cache,
+typedef void (frame_unwind_pop_ftype) (struct frame_info *next_frame,
+                                      void **this_cache,
                                       struct regcache *regcache);
 
 struct frame_unwind
index a8c3ce903d47d7ba520eb41bdcd76b5538d8e868..d70ac9653deebfefb4725bad36706dc8a2d1772e 100644 (file)
@@ -135,14 +135,27 @@ frame_find_by_id (struct frame_id id)
 }
 
 CORE_ADDR
-frame_pc_unwind (struct frame_info *frame)
+frame_pc_unwind (struct frame_info *this_frame)
 {
-  if (!frame->pc_unwind_cache_p)
+  if (!this_frame->pc_unwind_cache_p)
     {
-      frame->pc_unwind_cache = frame->unwind->pc (frame, &frame->unwind_cache);
-      frame->pc_unwind_cache_p = 1;
+      this_frame->pc_unwind_cache
+       = this_frame->unwind->pc (this_frame->next, &this_frame->unwind_cache);
+      this_frame->pc_unwind_cache_p = 1;
     }
-  return frame->pc_unwind_cache;
+  return this_frame->pc_unwind_cache;
+}
+
+struct frame_id
+frame_id_unwind (struct frame_info *this_frame)
+{
+  if (!this_frame->id_unwind_cache_p)
+    {
+      this_frame->unwind->id (this_frame->next, &this_frame->unwind_cache,
+                             &this_frame->id_unwind_cache);
+      this_frame->id_unwind_cache_p = 1;
+    }
+  return this_frame->id_unwind_cache;
 }
 
 void
@@ -154,12 +167,12 @@ frame_pop (struct frame_info *frame)
      values are needed to restore other registers.  Instead, this code
      should pass in a scratch cache and, as a second step, restore the
      registers using that.  */
-  frame->unwind->pop (frame, &frame->unwind_cache, current_regcache);
+  frame->unwind->pop (frame->next, &frame->unwind_cache, current_regcache);
   flush_cached_frames ();
 }
 
 void
-frame_register_unwind (struct frame_info *frame, int regnum,
+frame_register_unwind (struct frame_info *this_frame, int prev_regnum,
                       int *optimizedp, enum lval_type *lvalp,
                       CORE_ADDR *addrp, int *realnump, void *bufferp)
 {
@@ -177,11 +190,13 @@ frame_register_unwind (struct frame_info *frame, int regnum,
      is broken.  There is always a frame.  If there, for some reason,
      isn't, there is some pretty busted code as it should have
      detected the problem before calling here.  */
-  gdb_assert (frame != NULL);
+  gdb_assert (this_frame != NULL && this_frame->next != NULL);
 
-  /* Ask this frame to unwind its register.  */
-  frame->unwind->reg (frame, &frame->unwind_cache, regnum,
-                     optimizedp, lvalp, addrp, realnump, bufferp);
+  /* Ask this frame's register unwinder to return the value of
+     PREV_REGNUM using register values unwound from the NEXT frame.  */
+  this_frame->unwind->reg (this_frame->next, &this_frame->unwind_cache,
+                          prev_regnum, optimizedp, lvalp, addrp, realnump,
+                          bufferp);
 }
 
 void
@@ -1336,8 +1351,8 @@ get_prev_frame (struct frame_info *next_frame)
   {
     /* FIXME: cagney/2002-12-18: Instead of this hack, should just
        save the frame ID directly.  */
-    struct frame_id id = prev_frame->unwind->id (next_frame,
-                                                &prev_frame->unwind_cache);
+    struct frame_id id;
+    prev_frame->unwind->id (next_frame, &prev_frame->unwind_cache, &id);
     /* Check that the unwound ID is valid.  As of 2003-02-24 the
        x86-64 was returning an invalid frame ID when trying to do an
        unwind a sentinel frame that belonged to a frame dummy.  */
index 8dd5c93341118af1a597275997e194d7932962e4..bd20ba7aec1ba101d151359e733a4165d422bc9f 100644 (file)
@@ -310,6 +310,10 @@ extern const char *frame_map_regnum_to_name (int regnum);
 
 extern CORE_ADDR frame_pc_unwind (struct frame_info *frame);
 
+/* Unwind the frame ID.  Return an ID that uniquely identifies the
+   caller's frame.  */
+extern struct frame_id frame_id_unwind (struct frame_info *frame);
+
 /* Discard the specified frame.  Restoring the registers to the state
    of the caller.  */
 extern void frame_pop (struct frame_info *frame);
index fe11d8a6f43ac10c5f48001616b889ba9b507e79..ef8113da4e4204119105f49d785a76dcdd58621b 100644 (file)
@@ -45,19 +45,25 @@ sentinel_frame_cache (struct regcache *regcache)
 /* Here the register value is taken direct from the register cache.  */
 
 void
-sentinel_frame_register_unwind (struct frame_info *frame,
-                               void **unwind_cache,
-                               int regnum, int *optimized,
+sentinel_frame_register_unwind (struct frame_info *next_frame,
+                               void **this_cache,
+                               int prev_regnum, int *optimized,
                                enum lval_type *lvalp, CORE_ADDR *addrp,
                                int *realnum, void *bufferp)
 {
-  struct frame_unwind_cache *cache = *unwind_cache;
+  /* Hey don't let on but, for the sentinel frame, next_frame->next ==
+     next_frame.  Fortunatly, that local knowledge isn't needed,
+     instead THIS_CACHE contains all the information needed to find
+     the frame's thread's REGCACHE and that REGCACHE is then accessed
+     directly.  */
+  struct frame_unwind_cache *cache = *this_cache;
+
   /* Describe the register's location.  A reg-frame maps all registers
      onto the corresponding hardware register.  */
   *optimized = 0;
   *lvalp = lval_register;
-  *addrp = REGISTER_BYTE (regnum);
-  *realnum = regnum;
+  *addrp = REGISTER_BYTE (prev_regnum);
+  *realnum = prev_regnum;
 
   /* If needed, find and return the value of the register.  */
   if (bufferp != NULL)
@@ -66,13 +72,13 @@ sentinel_frame_register_unwind (struct frame_info *frame,
       /* Use the regcache_cooked_read() method so that it, on the fly,
          constructs either a raw or pseudo register from the raw
          register cache.  */
-      regcache_cooked_read (cache->regcache, regnum, bufferp);
+      regcache_cooked_read (cache->regcache, prev_regnum, bufferp);
     }
 }
 
 CORE_ADDR
-sentinel_frame_pc_unwind (struct frame_info *frame,
-                         void **cache)
+sentinel_frame_pc_unwind (struct frame_info *next_frame,
+                         void **this_cache)
 {
   /* FIXME: cagney/2003-01-08: This should be using a per-architecture
      method that doesn't suffer from DECR_PC_AFTER_BREAK problems.
@@ -82,21 +88,16 @@ sentinel_frame_pc_unwind (struct frame_info *frame,
 }
 
 void
-sentinel_frame_id_unwind (struct frame_info *frame,
-                         void **cache,
-                         struct frame_id *id)
+sentinel_frame_id_unwind (struct frame_info *next_frame,
+                         void **this_cache,
+                         struct frame_id *this_id)
 {
-  /* FIXME: cagney/2003-01-08: This should be using a per-architecture
-     method that doesn't suffer from DECR_PC_AFTER_BREAK problems.
-     Such a method would take unwind_cache, regcache and stop reason
-     parameters.  */
-  id->base = read_fp ();
-  id->pc = read_pc ();
+  internal_error (__FILE__, __LINE__, "sentinel_frame_id_unwind called");
 }
 
 static void
-sentinel_frame_pop (struct frame_info *frame,
-                   void **cache,
+sentinel_frame_pop (struct frame_info *next_frame,
+                   void **this_cache,
                    struct regcache *regcache)
 {
   internal_error (__FILE__, __LINE__, "Function sentinal_frame_pop called");