stop overallocating write-through regcaches

Pedro Alves pedro@codesourcery.com
Tue Jan 25 12:49:00 GMT 2011


I was looking at regcache.c to add graceful support for
unavailable/uncollected registers (there's already some support
in, btw), and I noticed some old FIXMEs around code I'll be touching.
This patch fixes them.

Raw/write-through regcaches don't need to allocate memory for the
pseudo registers.  We used to need to overallocate due to some
legacy code, but,

- write_register_bytes is long gone from the tree,

>  /* FIXME: cagney/2002-08-13: Overallocate the register_valid_p
>    array.  This pretects GDB from erant code that accesses elements
>    of the global register_valid_p[] array in the range 

- regcache_valid_p is nowadays a function, and it has asserts in place
that would trigger  if such bad accesses were still in the tree.

Tested on x86_64-linux and applied.

-- 
Pedro Alves

2011-01-25  Pedro Alves  <pedro@codesourcery.com>

	gdb/
	* regcache.c (struct regcache_descr): Remove outdated comment.
	(init_regcache_descr): Remove sizeof_raw_register_valid_p
	overallocate hack.
	(regcache_xmalloc): Rename to ...
	(regcache_xmalloc_1): ... this.  Add `readonly_p' parameter.
	Allocate the regcache type accordingly.
	(regcache_xmalloc): New as wrapper around regcache_xmalloc_1.
	(regcache_xfree): Asser the source is also readonly.  Copy sizeof
	cooked registers, not raw.
	(regcache_dup_no_passthrough): Delete.
	(get_thread_arch_regcache): Use regcache_xmalloc_1.
	* h8300-tdep.c (h8300_push_dummy_call): Tweak comment to not
	mention obsolete write_register_bytes.
	* regcache.h (regcache_dup_no_passthrough): Delete declaration.

---
 gdb/h8300-tdep.c |    5 +--
 gdb/regcache.c   |   87 
++++++++++++++++++++++++++++---------------------------
 gdb/regcache.h   |    1 
 3 files changed, 47 insertions(+), 46 deletions(-)

Index: src/gdb/regcache.c
===================================================================
--- src.orig/gdb/regcache.c	2011-01-13 15:07:35.000000000 +0000
+++ src/gdb/regcache.c	2011-01-25 11:57:57.657639997 +0000
@@ -67,10 +67,8 @@ struct regcache_descr
 
   /* Offset and size (in 8 bit bytes), of reach register in the
      register cache.  All registers (including those in the range
-     [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an offset.
-     Assigning all registers an offset makes it possible to keep
-     legacy code, such as that found in read_register_bytes() and
-     write_register_bytes() working.  */
+     [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an
+     offset.  */
   long *register_offset;
   long *sizeof_register;
 
@@ -108,12 +106,7 @@ init_regcache_descr (struct gdbarch *gdb
   /* Construct a strictly RAW register cache.  Don't allow pseudo's
      into the register cache.  */
   descr->nr_raw_registers = gdbarch_num_regs (gdbarch);
-
-  /* FIXME: cagney/2002-08-13: Overallocate the register_valid_p
-     array.  This pretects GDB from erant code that accesses elements
-     of the global register_valid_p[] array in the range 
-     [gdbarch_num_regs .. gdbarch_num_regs + gdbarch_num_pseudo_regs).  */
-  descr->sizeof_raw_register_valid_p = descr->sizeof_cooked_register_valid_p;
+  descr->sizeof_raw_register_valid_p = gdbarch_num_regs (gdbarch);
 
   /* Lay out the register cache.
 
@@ -129,24 +122,27 @@ init_regcache_descr (struct gdbarch *gdb
       = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long);
     descr->register_offset
       = GDBARCH_OBSTACK_CALLOC (gdbarch, descr->nr_cooked_registers, long);
-    for (i = 0; i < descr->nr_cooked_registers; i++)
+    for (i = 0; i < descr->nr_raw_registers; i++)
+      {
+	descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
+	descr->register_offset[i] = offset;
+	offset += descr->sizeof_register[i];
+	gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]);
+      }
+    /* Set the real size of the raw register cache buffer.  */
+    descr->sizeof_raw_registers = offset;
+
+    for (; i < descr->nr_cooked_registers; i++)
       {
 	descr->sizeof_register[i] = TYPE_LENGTH (descr->register_type[i]);
 	descr->register_offset[i] = offset;
 	offset += descr->sizeof_register[i];
 	gdb_assert (MAX_REGISTER_SIZE >= descr->sizeof_register[i]);
       }
-    /* Set the real size of the register cache buffer.  */
+    /* Set the real size of the readonly register cache buffer.  */
     descr->sizeof_cooked_registers = offset;
   }
 
-  /* FIXME: cagney/2002-05-22: Should only need to allocate space for
-     the raw registers.  Unfortunately some code still accesses the
-     register array directly using the global registers[].  Until that
-     code has been purged, play safe and over allocating the register
-     buffer.  Ulgh!  */
-  descr->sizeof_raw_registers = descr->sizeof_cooked_registers;
-
   return descr;
 }
 
@@ -215,8 +211,9 @@ struct regcache
   ptid_t ptid;
 };
 
-struct regcache *
-regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace)
+static struct regcache *
+regcache_xmalloc_1 (struct gdbarch *gdbarch, struct address_space *aspace,
+		    int readonly_p)
 {
   struct regcache_descr *descr;
   struct regcache *regcache;
@@ -225,16 +222,32 @@ regcache_xmalloc (struct gdbarch *gdbarc
   descr = regcache_descr (gdbarch);
   regcache = XMALLOC (struct regcache);
   regcache->descr = descr;
-  regcache->registers
-    = XCALLOC (descr->sizeof_raw_registers, gdb_byte);
-  regcache->register_valid_p
-    = XCALLOC (descr->sizeof_raw_register_valid_p, gdb_byte);
+  regcache->readonly_p = readonly_p;
+  if (readonly_p)
+    {
+      regcache->registers
+	= XCALLOC (descr->sizeof_cooked_registers, gdb_byte);
+      regcache->register_valid_p
+	= XCALLOC (descr->sizeof_cooked_register_valid_p, gdb_byte);
+    }
+  else
+    {
+      regcache->registers
+	= XCALLOC (descr->sizeof_raw_registers, gdb_byte);
+      regcache->register_valid_p
+	= XCALLOC (descr->sizeof_raw_register_valid_p, gdb_byte);
+    }
   regcache->aspace = aspace;
-  regcache->readonly_p = 1;
   regcache->ptid = minus_one_ptid;
   return regcache;
 }
 
+struct regcache *
+regcache_xmalloc (struct gdbarch *gdbarch, struct address_space *aspace)
+{
+  return regcache_xmalloc_1 (gdbarch, aspace, 1);
+}
+
 void
 regcache_xfree (struct regcache *regcache)
 {
@@ -382,11 +395,12 @@ regcache_cpy_no_passthrough (struct regc
   /* NOTE: cagney/2002-05-17: Don't let the caller do a no-passthrough
      move of data into the current regcache.  Doing this would be
      silly - it would mean that valid_p would be completely invalid.  */
-  gdb_assert (dst->readonly_p);
+  gdb_assert (dst->readonly_p && src->readonly_p);
 
-  memcpy (dst->registers, src->registers, dst->descr->sizeof_raw_registers);
+  memcpy (dst->registers, src->registers,
+	  dst->descr->sizeof_cooked_registers);
   memcpy (dst->register_valid_p, src->register_valid_p,
-	  dst->descr->sizeof_raw_register_valid_p);
+	  dst->descr->sizeof_cooked_register_valid_p);
 }
 
 struct regcache *
@@ -399,16 +413,6 @@ regcache_dup (struct regcache *src)
   return newbuf;
 }
 
-struct regcache *
-regcache_dup_no_passthrough (struct regcache *src)
-{
-  struct regcache *newbuf;
-
-  newbuf = regcache_xmalloc (src->descr->gdbarch, get_regcache_aspace (src));
-  regcache_cpy_no_passthrough (newbuf, src);
-  return newbuf;
-}
-
 int
 regcache_valid_p (const struct regcache *regcache, int regnum)
 {
@@ -459,9 +463,8 @@ get_thread_arch_regcache (ptid_t ptid, s
 	&& get_regcache_arch (list->regcache) == gdbarch)
       return list->regcache;
 
-  new_regcache = regcache_xmalloc (gdbarch,
-				   target_thread_address_space (ptid));
-  new_regcache->readonly_p = 0;
+  new_regcache = regcache_xmalloc_1 (gdbarch,
+				     target_thread_address_space (ptid), 0);
   new_regcache->ptid = ptid;
   gdb_assert (new_regcache->aspace != NULL);
 
Index: src/gdb/h8300-tdep.c
===================================================================
--- src.orig/gdb/h8300-tdep.c	2011-01-13 15:07:22.000000000 +0000
+++ src/gdb/h8300-tdep.c	2011-01-25 11:57:57.657639997 +0000
@@ -698,9 +698,8 @@ h8300_push_dummy_call (struct gdbarch *g
 	  else
 	    {
 	      /* Heavens to Betsy --- it's really going in registers!
-	         It would be nice if we could use write_register_bytes
-	         here, but on the h8/300s, there are gaps between
-	         the registers in the register file.  */
+	         Note that on the h8/300s, there are gaps between the
+	         registers in the register file.  */
 	      int offset;
 
 	      for (offset = 0; offset < padded_len; offset += wordsize)
Index: src/gdb/regcache.h
===================================================================
--- src.orig/gdb/regcache.h	2011-01-13 15:07:35.000000000 +0000
+++ src/gdb/regcache.h	2011-01-25 11:58:34.307639992 +0000
@@ -154,7 +154,6 @@ extern void regcache_restore (struct reg
    only transfer values already in the cache.  */
 
 extern struct regcache *regcache_dup (struct regcache *regcache);
-extern struct regcache *regcache_dup_no_passthrough (struct regcache *);
 extern void regcache_cpy (struct regcache *dest, struct regcache *src);
 extern void regcache_cpy_no_passthrough (struct regcache *dest,
 					 struct regcache *src);



More information about the Gdb-patches mailing list