This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[offbyone] Merge in posted frame_pop patch


Just FYI,

This merges the just posted frame_pop patch (and the associated regcache change) into my offbyone branch.

Andrew
2003-03-10  Andrew Cagney  <cagney at redhat dot com>

	* frame.c: Merge in posted frame_pop patch.
	* regcache.h, regcache.c: Merge with mainline.

Index: frame.c
===================================================================
RCS file: /cvs/src/src/gdb/frame.c,v
retrieving revision 1.71.2.5
diff -u -r1.71.2.5 frame.c
--- frame.c	7 Mar 2003 14:24:29 -0000	1.71.2.5
+++ frame.c	10 Mar 2003 20:57:58 -0000
@@ -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 @@
   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: regcache.c
===================================================================
RCS file: /cvs/src/src/gdb/regcache.c,v
retrieving revision 1.71.2.1
diff -u -r1.71.2.1 regcache.c
--- regcache.c	7 Mar 2003 14:24:29 -0000	1.71.2.1
+++ regcache.c	10 Mar 2003 20:58:00 -0000
@@ -389,59 +389,79 @@
 }
 
 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 @@
   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 @@
 {
   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: regcache.h
===================================================================
RCS file: /cvs/src/src/gdb/regcache.h,v
retrieving revision 1.29
diff -u -r1.29 regcache.h
--- regcache.h	28 Feb 2003 17:47:43 -0000	1.29
+++ regcache.h	10 Mar 2003 20:58:00 -0000
@@ -155,15 +155,19 @@
 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.  */
+/* 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.  */
 
-extern void regcache_save (struct regcache *dst, struct regcache *src);
-extern void regcache_restore (struct regcache *dst, struct regcache *src);
+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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]