]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2003-01-11 Andrew Cagney <ac131313@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Sun, 12 Jan 2003 00:06:19 +0000 (00:06 +0000)
committerAndrew Cagney <cagney@redhat.com>
Sun, 12 Jan 2003 00:06:19 +0000 (00:06 +0000)
* frame.c (deprecated_update_frame_pc_hack)
(deprecated_update_frame_base_hack): Also update the next frame's
ID/PC cache.
(create_sentinel_frame): Link the sentinel frame to itself.
* frame.h: Expand comments describing update PC and FP hacks.
* frame.c (get_prev_frame): Add comment explaining why
INIT_EXTRA_FRAME_INFO call is needed.
(legacy_get_prev_frame): Use get_next_frame.

gdb/ChangeLog
gdb/frame.c
gdb/frame.h

index 7f562ccd1eded4a16417e7193482258befe4d2cb..41389f08a72d70c4be59bf244fa7e4d49a4c86e5 100644 (file)
@@ -1,3 +1,14 @@
+2003-01-11  Andrew Cagney  <ac131313@redhat.com>
+
+       * frame.c (deprecated_update_frame_pc_hack)
+       (deprecated_update_frame_base_hack): Also update the next frame's
+       ID/PC cache.
+       (create_sentinel_frame): Link the sentinel frame to itself.
+       * frame.h: Expand comments describing update PC and FP hacks.
+       * frame.c (get_prev_frame): Add comment explaining why
+       INIT_EXTRA_FRAME_INFO call is needed.
+       (legacy_get_prev_frame): Use get_next_frame.
+       
 2003-01-10  Andrew Cagney  <ac131313@redhat.com>
 
        * frame.c (create_sentinel_frame): Initialize sentinel frame's PC.
index 0bac5808a2dbdf3ade61eabfc06b10ed0a0971cc..daa243a84781ed21ae999bf9cd322587954a4e8e 100644 (file)
@@ -57,6 +57,29 @@ get_frame_id (struct frame_info *fi)
     }
 }
 
+struct frame_id
+frame_id_unwind (struct frame_info *frame)
+{
+  if (!frame->id_unwind_cache_p)
+    {
+      frame->id_unwind (frame, &frame->unwind_cache, &frame->id_unwind_cache);
+      frame->id_unwind_cache_p = 1;
+    }
+  return frame->id_unwind_cache;
+}
+
+void
+deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
+{
+  /* See comment in "frame.h".  */
+  frame->frame = base;
+  gdb_assert (frame->next != NULL);
+  gdb_assert (frame->next->id_unwind_cache_p);
+  gdb_assert (frame->next->pc_unwind_cache_p);
+  frame->next->id_unwind_cache.base = base;
+  frame->next->id_unwind_cache.pc = frame->next->pc_unwind_cache;
+}
+
 const struct frame_id null_frame_id; /* All zeros.  */
 
 struct frame_id
@@ -125,28 +148,6 @@ frame_find_by_id (struct frame_id id)
   return NULL;
 }
 
-CORE_ADDR
-frame_pc_unwind (struct frame_info *frame)
-{
-  if (!frame->pc_unwind_cache_p)
-    {
-      frame->pc_unwind_cache = frame->pc_unwind (frame, &frame->unwind_cache);
-      frame->pc_unwind_cache_p = 1;
-    }
-  return frame->pc_unwind_cache;
-}
-
-struct frame_id
-frame_id_unwind (struct frame_info *frame)
-{
-  if (!frame->id_unwind_cache_p)
-    {
-      frame->id_unwind (frame, &frame->unwind_cache, &frame->id_unwind_cache);
-      frame->id_unwind_cache_p = 1;
-    }
-  return frame->id_unwind_cache;
-}
-
 
 void
 frame_register_unwind (struct frame_info *frame, int regnum,
@@ -411,6 +412,10 @@ create_sentinel_frame (struct regcache *regcache)
   frame->pc_unwind = sentinel_frame_pc_unwind;
   frame->id_unwind = sentinel_frame_id_unwind;
   frame->register_unwind = sentinel_frame_register_unwind;
+  /* Link this frame back to itself.  The frame is self referential
+     (the unwound PC is the same as the pc for instance, so make it
+     so.  */
+  frame->next = frame;
   /* Always unwind the PC as part of creating this frame.  This
      ensures that the frame's PC points into something valid.  */
   /* FIXME: cagney/2003-01-10: Problem here.  Unwinding a sentinel
@@ -686,6 +691,9 @@ legacy_get_prev_frame (struct frame_info *next_frame)
   struct frame_info *prev;
   int fromleaf;
 
+  /* This code doesn't work with the sentinal frame.  */
+  gdb_assert (next_frame->level >= 0);
+
   /* On some machines it is possible to call a function without
      setting up a stack frame for it.  On these machines, we
      define this macro to take two args; a frameinfo pointer
@@ -695,7 +703,7 @@ legacy_get_prev_frame (struct frame_info *next_frame)
   /* Still don't want to worry about this except on the innermost
      frame.  This macro will set FROMLEAF if NEXT_FRAME is a frameless
      function invocation.  */
-  if (next_frame->next == NULL)
+  if (get_next_frame (next_frame) == NULL)
     /* FIXME: 2002-11-09: Frameless functions can occure anywhere in
        the frame chain, not just the inner most frame!  The generic,
        per-architecture, frame code should handle this and the below
@@ -906,7 +914,15 @@ get_prev_frame (struct frame_info *next_frame)
      NOTE: cagney/2003-01-10: Talk about code behaving badly.  Check
      block_innermost_frame().  It does the sequence: frame = NULL;
      while (1) { frame = get_prev_frame (frame); .... }.  Ulgh!  Why
-     it couldn't be written better, I don't know.  */
+     it couldn't be written better, I don't know.
+
+     NOTE: cagney/2003-01-11: I suspect what is happening is
+     block_innermost_frame() is, when the target has no state
+     (registers, memory, ...), still calling this function.  The
+     assumption being that this function will return NULL indicating
+     that a frame isn't possible, rather than checking that the target
+     has state and then calling get_current_frame() and
+     get_prev_frame().  This is a guess mind.  */
   if (next_frame == NULL)
     {
       /* NOTE: cagney/2002-11-09: There was a code segment here that
@@ -957,7 +973,7 @@ get_prev_frame (struct frame_info *next_frame)
   if ((DEPRECATED_INIT_FRAME_PC_P ()
        || DEPRECATED_INIT_FRAME_PC_FIRST_P ())
       && next_frame->level >= 0)
-    /* Don't try to unwind the sentinal frame using the old code.  */
+     /* Don't try to unwind the sentinal frame using the old code.  */
     return legacy_get_prev_frame (next_frame);
 
   /* Allocate the new frame but do not wire it in.  Some (bad) code in
@@ -1024,6 +1040,8 @@ get_prev_frame (struct frame_info *next_frame)
      Instead of initializing extra info, all frames will use the
      frame_cache (passed to the unwind functions) to store extra frame
      info.  */
+  /* NOTE: cagney/2003-01-11: Legacy targets, when having the sentinel
+     frame unwound, rely on this call.  */
   if (INIT_EXTRA_FRAME_INFO_P ())
     /* NOTE: This code doesn't bother trying to sort out frameless
        functions.  That is left to the target.  */
@@ -1035,9 +1053,39 @@ get_prev_frame (struct frame_info *next_frame)
 CORE_ADDR
 get_frame_pc (struct frame_info *frame)
 {
+  /* This should just call frame_pc_unwind().  */
   return frame->pc;
 }
 
+CORE_ADDR
+frame_pc_unwind (struct frame_info *frame)
+{
+  if (!frame->pc_unwind_cache_p)
+    {
+      frame->pc_unwind_cache = frame->pc_unwind (frame, &frame->unwind_cache);
+      frame->pc_unwind_cache_p = 1;
+    }
+  return frame->pc_unwind_cache;
+}
+
+void
+deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
+{
+  /* See comment in "frame.h".  */
+  frame->pc = pc;
+  gdb_assert (frame->next != NULL);
+  /* Got a bucket?  Legacy code that handles dummy frames directly
+     doesn't always use the unwind function to determine the dummy
+     frame's PC.  Consequently, it is possible for this function to be
+     called when the next frame's pc unwind cache isn't valid.  */
+  if (frame->next->pc_unwind_cache_p)
+    frame->next->pc_unwind_cache = pc;
+  /* Since the PC is unwound before the frame ID, only need to update
+     the frame ID's PC when it has been unwound.  */
+  if (frame->next->id_unwind_cache_p)
+    frame->next->id_unwind_cache.pc = pc;
+}
+
 static int
 pc_notcurrent (struct frame_info *frame)
 {
@@ -1140,20 +1188,6 @@ frame_extra_info_zalloc (struct frame_info *fi, long size)
   return fi->extra_info;
 }
 
-void
-deprecated_update_frame_pc_hack (struct frame_info *frame, CORE_ADDR pc)
-{
-  /* See comment in "frame.h".  */
-  frame->pc = pc;
-}
-
-void
-deprecated_update_frame_base_hack (struct frame_info *frame, CORE_ADDR base)
-{
-  /* See comment in "frame.h".  */
-  frame->frame = base;
-}
-
 void
 deprecated_set_frame_saved_regs_hack (struct frame_info *frame,
                                      CORE_ADDR *saved_regs)
index 98dace6cb1ee45daea380df0e7da22d6fe6e0963..f77a05edf63874e2253807e574bf5b6dc00836b1 100644 (file)
@@ -663,17 +663,22 @@ extern struct frame_extra_info *get_frame_extra_info (struct frame_info *fi);
 extern CORE_ADDR *frame_saved_regs_zalloc (struct frame_info *);
 extern CORE_ADDR *get_frame_saved_regs (struct frame_info *);
 
-/* FIXME: cagney/2002-12-06: Has the PC in the current frame changed?
-   "infrun.c", Thanks to DECR_PC_AFTER_BREAK, can change the PC after
-   the initial frame create.  This puts things back in sync.  */
+/* FIXME: cagney/2003-01-11: Fix up this frame's frame ID / PC (which
+   is cached in the next frame).  The problem here is with read_fp()/
+   FRAME_CHAIN() and read_pc() / FRAME_SAVED_PC.  Legacy code, instead
+   of returning the correct frame base from the word go, returns a
+   draft frame base and then fixes it up in INIT_FRAME_PC,
+   INIT_FRAME_PC_FIRST or INIT_EXTRA_FRAME_INFO.  Back patch the next
+   frame's frame ID so that it will now return the correct id.
+
+   For the PC, the problems are caused by DECR_PC_AFTER_BREAK and
+   DECR_PC_AFTER_HW_BREAK.
+
+   For the FP, the problems are caused by GDB requesting the FP
+   instead of the SP and, as a consequence, code trying to avoid the
+   overhead of unnecessary prologue analysis.  */
 extern void deprecated_update_frame_pc_hack (struct frame_info *frame,
                                             CORE_ADDR pc);
-
-/* FIXME: cagney/2002-12-18: Has the frame's base changed?  Or to be
-   more exact, whas that initial guess at the frame's base as returned
-   by read_fp() wrong.  If it was, fix it.  This shouldn't be
-   necessary since the code should be getting the frame's base correct
-   from the outset.  */
 extern void deprecated_update_frame_base_hack (struct frame_info *frame,
                                               CORE_ADDR base);