]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2003-03-10 Andrew Cagney <cagney@redhat.com>
authorAndrew Cagney <cagney@redhat.com>
Mon, 10 Mar 2003 21:00:56 +0000 (21:00 +0000)
committerAndrew Cagney <cagney@redhat.com>
Mon, 10 Mar 2003 21:00:56 +0000 (21:00 +0000)
* frame.c: Merge in posted frame_pop patch.
* regcache.h, regcache.c: Merge with mainline.

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

index 8b9d6f67b5cd96d9f714e841b7693e24958c6c72..8a1224fb71b7dde7268120939fcc8f19b01673f8 100644 (file)
@@ -1,3 +1,9 @@
+2003-03-10  Andrew Cagney  <cagney@redhat.com>
+
+       * frame.c (frame_pop): Merge with mainline
+       (do_frame_unwind_register): Merge with mainline.
+       * regcache.h, regcache.c: Merge with mainline.
+
 2003-03-06  Andrew Cagney  <cagney@redhat.com>
 
        * d10v-tdep.c (d10v_frame_pop): Delete function.
index 1a1c050a01a2266818c68b5f7d3a2dbf18004ed9..b891463c685f9f1f76ebb5838abc07481315133c 100644 (file)
@@ -38,7 +38,6 @@
 #include "frame-unwind.h"
 #include "command.h"
 #include "gdbcmd.h"
-#include "reggroups.h"
 
 /* Flag to control debugging.  */
 
@@ -186,42 +185,44 @@ frame_pc_unwind (struct frame_info *this_frame)
   return this_frame->pc_unwind_cache;
 }
 
+static int
+do_frame_unwind_register (void *src, int regnum, void *buf)
+{
+  frame_unwind_register (src, regnum, buf);
+  return 1;
+}
+
 void
 frame_pop (struct frame_info *this_frame)
 {
+  struct regcache *scratch_regcache;
+  struct cleanup *cleanups;
+
   if (POP_FRAME_P ())
     {
+      /* A legacy architecture that has implemented a custom pop
+        function.  All new architectures should instead be using the
+        generic code below.  */
       POP_FRAME;
     }
   else
     {
-      /* Note, the dummy-frame code does something very similar to
-         this.  Perhaphs a common routine is in order.  */
-      struct regcache *scratch_regcache = regcache_xmalloc (current_gdbarch);
-      struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch_regcache);
-      void *buf = alloca (max_register_size (current_gdbarch));
-      int regnum;
-
-      /* Copy over any registers (identified by their membership in
-        the save_reggroup) and mark them as valid.  The full [0
-        .. NUM_REGS+NUM_PSEUDO_REGS) range is checked since some
-        architectures need to save/restore `cooked' registers that
-        live in memory.  */
-      for (regnum = 0; regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
-       {
-         if (gdbarch_register_reggroup_p (current_gdbarch, regnum,
-                                          save_reggroup))
-           {
-             frame_unwind_register (this_frame, regnum, buf);
-             regcache_cooked_write (scratch_regcache, regnum, buf);
-           }
-       }
-
-      /* Now write the unwound registers, en-mass, back into the
-         regcache.  */
-      regcache_cpy (current_regcache, scratch_regcache);
+      /* Make a copy of all the register values unwound from this
+        frame.  Save them in a scratch buffer so that there isn't a
+        race betweening trying to extract the old values from the
+        current_regcache while, at the same time writing new values
+        into that same cache.  */
+      struct regcache *scratch = regcache_xmalloc (current_gdbarch);
+      struct cleanup *cleanups = make_cleanup_regcache_xfree (scratch);
+      regcache_save (scratch, do_frame_unwind_register, this_frame);
+      /* Now copy those saved registers into the current regcache.
+         Here, regcache_cpy() calls regcache_restore().  */
+      regcache_cpy (current_regcache, scratch);
       do_cleanups (cleanups);
     }
+  /* We've made right mess of GDB's local state, just discard
+     everything.  */
+  target_store_registers (-1);
   flush_cached_frames ();
 }
 
index 1b862e187eb1f89666c7c23e7d1987d3a9f452f1..5475cf681ef24a6a724c68ecbc94b5c8129b2bba 100644 (file)
@@ -389,59 +389,79 @@ register_buffer (struct regcache *regcache, int regnum)
 }
 
 void
-regcache_save (struct regcache *dst, struct regcache *src)
+regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read,
+              void *src)
 {
   struct gdbarch *gdbarch = dst->descr->gdbarch;
+  void *buf = alloca (max_register_size (gdbarch));
   int regnum;
-  /* The SRC and DST register caches had better belong to the same
-     architecture.  */
-  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
   /* The DST should be `read-only', if it wasn't then the save would
-     end up trying to write the register values out through to the
+     end up trying to write the register values back out to the
      target.  */
-  gdb_assert (!src->readonly_p);
   gdb_assert (dst->readonly_p);
   /* Clear the dest.  */
   memset (dst->registers, 0, dst->descr->sizeof_cooked_registers);
   memset (dst->register_valid_p, 0, dst->descr->sizeof_cooked_register_valid_p);
   /* Copy over any registers (identified by their membership in the
-     save_reggroup) and mark them as valid.  The full [0
-     .. NUM_REGS+NUM_PSEUDO_REGS) range is checked since some
-     architectures need to save/restore `cooked' registers that live
-     in memory.  */
+     save_reggroup) and mark them as valid.  The full [0 .. NUM_REGS +
+     NUM_PSEUDO_REGS) range is checked since some architectures need
+     to save/restore `cooked' registers that live in memory.  */
   for (regnum = 0; regnum < dst->descr->nr_cooked_registers; regnum++)
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, save_reggroup))
        {
-         regcache_cooked_read (src, regnum, register_buffer (dst, regnum));
-         dst->register_valid_p[regnum] = 1;
+         int valid = cooked_read (src, regnum, buf);
+         if (valid)
+           {
+             memcpy (register_buffer (dst, regnum), buf,
+                     register_size (gdbarch, regnum));
+             dst->register_valid_p[regnum] = 1;
+           }
        }
     }
 }
 
 void
-regcache_restore (struct regcache *dst, struct regcache *src)
+regcache_restore (struct regcache *dst,
+                 regcache_cooked_read_ftype *cooked_read,
+                 void *src)
 {
   struct gdbarch *gdbarch = dst->descr->gdbarch;
+  void *buf = alloca (max_register_size (gdbarch));
   int regnum;
-  gdb_assert (src->descr->gdbarch == dst->descr->gdbarch);
+  /* The dst had better not be read-only.  If it is, the `restore'
+     doesn't make much sense.  */
   gdb_assert (!dst->readonly_p);
-  gdb_assert (src->readonly_p);
   /* Copy over any registers, being careful to only restore those that
-     were both saved and need to be restored.  The full [0
-     .. NUM_REGS+NUM_PSEUDO_REGS) range is checked since some
-     architectures need to save/restore `cooked' registers that live
-     in memory.  */
-  for (regnum = 0; regnum < src->descr->nr_cooked_registers; regnum++)
+     were both saved and need to be restored.  The full [0 .. NUM_REGS
+     + NUM_PSEUDO_REGS) range is checked since some architectures need
+     to save/restore `cooked' registers that live in memory.  */
+  for (regnum = 0; regnum < dst->descr->nr_cooked_registers; regnum++)
     {
-      if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup)
-         && src->register_valid_p[regnum])
+      if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
        {
-         regcache_cooked_write (dst, regnum, register_buffer (src, regnum));
+         int valid = cooked_read (src, regnum, buf);
+         if (valid)
+           regcache_cooked_write (dst, regnum, buf);
        }
     }
 }
 
+static int
+do_cooked_read (void *src, int regnum, void *buf)
+{
+  struct regcache *regcache = src;
+  if (!regcache_valid_p (regcache, regnum)
+      && regcache->readonly_p)
+    /* Don't even think about fetching a register from a read-only
+       cache when the register isn't yet valid.  There isn't a target
+       from which the register value can be fetched.  */
+    return 0;
+  regcache_cooked_read (regcache, regnum, buf);
+  return 1;
+}
+
+
 void
 regcache_cpy (struct regcache *dst, struct regcache *src)
 {
@@ -452,9 +472,9 @@ regcache_cpy (struct regcache *dst, struct regcache *src)
   gdb_assert (src != dst);
   gdb_assert (src->readonly_p || dst->readonly_p);
   if (!src->readonly_p)
-    regcache_save (dst, src);
+    regcache_save (dst, do_cooked_read, src);
   else if (!dst->readonly_p)
-    regcache_restore (dst, src);
+    regcache_restore (dst, do_cooked_read, src);
   else
     regcache_cpy_no_passthrough (dst, src);
 }
@@ -929,14 +949,7 @@ regcache_raw_write (struct regcache *regcache, int regnum, const void *buf)
 {
   gdb_assert (regcache != NULL && buf != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
-
-  if (regcache->readonly_p)
-    {
-      memcpy (register_buffer (regcache, regnum), buf,
-             regcache->descr->sizeof_register[regnum]);
-      regcache->register_valid_p[regnum] = 1;
-      return;
-    }
+  gdb_assert (!regcache->readonly_p);
 
   if (regcache->descr->legacy_p)
     {
index ee1050536056de08f98bd908332c3aa7a3311f6d..dd629383bebe1b00dad3662ab7d6ef21fe028a06 100644 (file)
@@ -155,15 +155,19 @@ extern int max_register_size (struct gdbarch *gdbarch);
 extern int register_size (struct gdbarch *gdbarch, int regnum);
 
 
-/* Save/restore a register cache.  The registers saved/restored is
-   determined by the save_reggroup and restore_reggroup (although you
-   can't restore a register that wasn't saved as well :-).  You can
-   only save to a read-only cache (default from regcache_xmalloc())
-   from a live cache and you can only restore from a read-only cache
-   to a live cache.  */
-
-extern void regcache_save (struct regcache *dst, struct regcache *src);
-extern void regcache_restore (struct regcache *dst, struct regcache *src);
+/* Save/restore a register cache.  The set of registers saved /
+   restored into the DST regcache determined by the save_reggroup /
+   restore_reggroup respectively.  COOKED_READ returns zero iff the
+   register's value can't be returned.  */
+
+typedef int (regcache_cooked_read_ftype) (void *src, int regnum, void *buf);
+
+extern void regcache_save (struct regcache *dst,
+                          regcache_cooked_read_ftype *cooked_read,
+                          void *src);
+extern void regcache_restore (struct regcache *dst,
+                             regcache_cooked_read_ftype *cooked_read,
+                             void *src);
 
 /* Copy/duplicate the contents of a register cache.  By default, the
    operation is pass-through.  Writes to DST and reads from SRC will