]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/gdbserver/
authorPedro Alves <palves@redhat.com>
Fri, 28 Jan 2011 13:36:32 +0000 (13:36 +0000)
committerPedro Alves <palves@redhat.com>
Fri, 28 Jan 2011 13:36:32 +0000 (13:36 +0000)
* regcache.c (init_register_cache): Initialize
regcache->register_status.
(free_register_cache): Release regcache->register_status.
(regcache_cpy): Copy register_status.
(registers_to_string): Print 'x's for unavailable registers.
(supply_register): Mark the register's status valid or
unavailable, depending on whether a buffer was passed in or not.
(supply_register_zeroed): New.
(supply_regblock): Mark the registers' status valid or
unavailable, depending on whether a buffer was passed in or not.
* regcache.h (REG_UNAVAILABLE, REG_VALID): New defines.
(struct regcache): New `register_status' field.
(supply_register_zeroed): Declare.
* i387-fp.c (i387_xsave_to_cache): Zero out registers using
supply_register_zeroed, rather than passing a NULL buffer to
supply_register.
* tracepoint.c (fetch_traceframe_registers): Update comment.

gdb/gdbserver/ChangeLog
gdb/gdbserver/i387-fp.c
gdb/gdbserver/regcache.c
gdb/gdbserver/regcache.h
gdb/gdbserver/tracepoint.c

index 39eb4e76afade8a7ec9e5db5cb03b456a2b30cdb..79ed9096e4114bcebef70febdc97670838b784a7 100644 (file)
@@ -1,3 +1,23 @@
+2011-01-28  Pedro Alves  <pedro@codesourcery.com>
+
+       * regcache.c (init_register_cache): Initialize
+       regcache->register_status.
+       (free_register_cache): Release regcache->register_status.
+       (regcache_cpy): Copy register_status.
+       (registers_to_string): Print 'x's for unavailable registers.
+       (supply_register): Mark the register's status valid or
+       unavailable, depending on whether a buffer was passed in or not.
+       (supply_register_zeroed): New.
+       (supply_regblock): Mark the registers' status valid or
+       unavailable, depending on whether a buffer was passed in or not.
+       * regcache.h (REG_UNAVAILABLE, REG_VALID): New defines.
+       (struct regcache): New `register_status' field.
+       (supply_register_zeroed): Declare.
+       * i387-fp.c (i387_xsave_to_cache): Zero out registers using
+       supply_register_zeroed, rather than passing a NULL buffer to
+       supply_register.
+       * tracepoint.c (fetch_traceframe_registers): Update comment.
+
 2011-01-28  Pedro Alves  <pedro@codesourcery.com>
 
        * i387-fp.c (i387_xsave_to_cache): Make passing NULL as register
index 3dfe06be3b5baa61129d24a2dfd88cc7c256634b..80b5de66f0da8330735725515052377c43cf1408 100644 (file)
@@ -482,7 +482,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
       if ((clear_bv & I386_XSTATE_X87) != 0)
        {
          for (i = 0; i < 8; i++)
-           supply_register (regcache, i + st0_regnum, NULL);
+           supply_register_zeroed (regcache, i + st0_regnum);
        }
       else
        {
@@ -499,7 +499,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
       if ((clear_bv & I386_XSTATE_SSE))
        {
          for (i = 0; i < num_xmm_registers; i++)
-           supply_register (regcache, i + xmm0_regnum, NULL);
+           supply_register_zeroed (regcache, i + xmm0_regnum);
        }
       else
        {
@@ -516,7 +516,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
       if ((clear_bv & I386_XSTATE_AVX) != 0)
        {
          for (i = 0; i < num_xmm_registers; i++)
-           supply_register (regcache, i + ymm0h_regnum, NULL);
+           supply_register_zeroed (regcache, i + ymm0h_regnum);
        }
       else
        {
index ec0f51cc4d280033a1fbf6fd936a28bb9f91fcad..ecd974441b00cf842dd5c2d362738eb6c166ad26 100644 (file)
@@ -98,6 +98,8 @@ init_register_cache (struct regcache *regcache, unsigned char *regbuf)
         garbage.  */
       regcache->registers = xcalloc (1, register_bytes);
       regcache->registers_owned = 1;
+      regcache->register_status = xcalloc (1, num_registers);
+      gdb_assert (REG_UNAVAILABLE == 0);
     }
   else
 #else
@@ -108,6 +110,9 @@ init_register_cache (struct regcache *regcache, unsigned char *regbuf)
     {
       regcache->registers = regbuf;
       regcache->registers_owned = 0;
+#ifndef IN_PROCESS_AGENT
+      regcache->register_status = NULL;
+#endif
     }
 
   regcache->registers_valid = 0;
@@ -136,6 +141,7 @@ free_register_cache (struct regcache *regcache)
     {
       if (regcache->registers_owned)
        free (regcache->registers);
+      free (regcache->register_status);
       free (regcache);
     }
 }
@@ -146,6 +152,10 @@ void
 regcache_cpy (struct regcache *dst, struct regcache *src)
 {
   memcpy (dst->registers, src->registers, register_bytes);
+#ifndef IN_PROCESS_AGENT
+  if (dst->register_status != NULL && src->register_status != NULL)
+    memcpy (dst->register_status, src->register_status, num_registers);
+#endif
   dst->registers_valid = src->registers_valid;
 }
 
@@ -209,8 +219,23 @@ void
 registers_to_string (struct regcache *regcache, char *buf)
 {
   unsigned char *registers = regcache->registers;
+  int i;
 
-  convert_int_to_ascii (registers, buf, register_bytes);
+  for (i = 0; i < num_registers; i++)
+    {
+      if (regcache->register_status[i] == REG_VALID)
+       {
+         convert_int_to_ascii (registers, buf, register_size (i));
+         buf += register_size (i) * 2;
+       }
+      else
+       {
+         memset (buf, 'x', register_size (i) * 2);
+         buf += register_size (i) * 2;
+       }
+      registers += register_size (i);
+    }
+  *buf = '\0';
 }
 
 void
@@ -273,22 +298,74 @@ register_data (struct regcache *regcache, int n, int fetch)
   return regcache->registers + (reg_defs[n].offset / 8);
 }
 
+/* Supply register N, whose contents are stored in BUF, to REGCACHE.
+   If BUF is NULL, the register's value is recorded as
+   unavailable.  */
+
 void
 supply_register (struct regcache *regcache, int n, const void *buf)
 {
   if (buf)
-    memcpy (register_data (regcache, n, 0), buf, register_size (n));
+    {
+      memcpy (register_data (regcache, n, 0), buf, register_size (n));
+#ifndef IN_PROCESS_AGENT
+      if (regcache->register_status != NULL)
+       regcache->register_status[n] = REG_VALID;
+#endif
+    }
   else
-    memset (register_data (regcache, n, 0), 0, register_size (n));
+    {
+      memset (register_data (regcache, n, 0), 0, register_size (n));
+#ifndef IN_PROCESS_AGENT
+      if (regcache->register_status != NULL)
+       regcache->register_status[n] = REG_UNAVAILABLE;
+#endif
+    }
 }
 
+/* Supply register N with value zero to REGCACHE.  */
+
+void
+supply_register_zeroed (struct regcache *regcache, int n)
+{
+  memset (register_data (regcache, n, 0), 0, register_size (n));
+#ifndef IN_PROCESS_AGENT
+  if (regcache->register_status != NULL)
+    regcache->register_status[n] = REG_VALID;
+#endif
+}
+
+/* Supply the whole register set whose contents are stored in BUF, to
+   REGCACHE.  If BUF is NULL, all the registers' values are recorded
+   as unavailable.  */
+
 void
 supply_regblock (struct regcache *regcache, const void *buf)
 {
   if (buf)
-    memcpy (regcache->registers, buf, register_bytes);
+    {
+      memcpy (regcache->registers, buf, register_bytes);
+#ifndef IN_PROCESS_AGENT
+      {
+       int i;
+
+       for (i = 0; i < num_registers; i++)
+         regcache->register_status[i] = REG_VALID;
+      }
+#endif
+    }
   else
-    memset (regcache->registers, 0, register_bytes);
+    {
+      memset (regcache->registers, 0, register_bytes);
+#ifndef IN_PROCESS_AGENT
+      {
+       int i;
+
+       for (i = 0; i < num_registers; i++)
+         regcache->register_status[i] = REG_UNAVAILABLE;
+      }
+#endif
+    }
 }
 
 #ifndef IN_PROCESS_AGENT
index df3b2615bc5ef998b6e41019b5097d7f41b93e8d..5fe64cb1d8068d26f2e059aa0922b67f3f358606 100644 (file)
 struct inferior_list_entry;
 struct thread_info;
 
+/* The register exists, it has a value, but we don't know what it is.
+   Used when inspecting traceframes.  */
+#define REG_UNAVAILABLE 0
+
+/* We know the register's value (and we have it cached).  */
+#define REG_VALID 1
+
 /* The data for the register cache.  Note that we have one per
    inferior; this is primarily for simplicity, as the performance
    benefit is minimal.  */
 
 struct regcache
 {
+  /* Whether the REGISTERS buffer's contents are valid.  If false, we
+     haven't fetched the registers from the target yet.  Not that this
+     register cache is _not_ pass-through, unlike GDB's.  Note that
+     "valid" here is unrelated to whether the registers are available
+     in a traceframe.  For that, check REGISTER_STATUS below.  */
   int registers_valid;
   int registers_owned;
   unsigned char *registers;
+#ifndef IN_PROCESS_AGENT
+  /* One of REG_UNAVAILBLE or REG_VALID.  */
+  unsigned char *register_status;
+#endif
 };
 
 struct regcache *init_register_cache (struct regcache *regcache,
@@ -84,6 +100,8 @@ extern const char *gdbserver_xmltarget;
 
 void supply_register (struct regcache *regcache, int n, const void *buf);
 
+void supply_register_zeroed (struct regcache *regcache, int n);
+
 void supply_register_by_name (struct regcache *regcache,
                              const char *name, const void *buf);
 
index c9e9ead3271ab1498b320e55bfd5a5e57fd3869e..2da57edb9977e901970a1aeaf2c7c7ff311fc522 100644 (file)
@@ -4840,8 +4840,7 @@ fetch_traceframe_registers (int tfnum, struct regcache *regcache, int regnum)
   dataptr = traceframe_find_regblock (tframe, tfnum);
   if (dataptr == NULL)
     {
-      /* We don't like making up numbers, but GDB has all manner of
-        troubles when the target says there are no registers.  */
+      /* Mark registers unavailable.  */
       supply_regblock (regcache, NULL);
 
       /* We can generally guess at a PC, although this will be