Cleanup value_fetch_lazy's comment and return value
[deliverable/binutils-gdb.git] / gdb / regcache.c
index 8b4d77ccc0c81b7444e772ed7d3d6373e5c621e2..86e648ae3d9b52496218f0cce97cee547321741a 100644 (file)
@@ -1,7 +1,6 @@
 /* Cache and manage the values of registers for GDB, the GNU debugger.
 
-   Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001,
-   2002, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1986-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "gdbcmd.h"
 #include "regcache.h"
 #include "reggroups.h"
-#include "gdb_assert.h"
-#include "gdb_string.h"
-#include "gdbcmd.h"            /* For maintenanceprintlist.  */
 #include "observer.h"
-#include "exceptions.h"
+#include "remote.h"
+#include "valprint.h"
+#include "regset.h"
 
 /*
  * DATA STRUCTURE
@@ -66,7 +64,7 @@ struct regcache_descr
   long sizeof_cooked_registers;
   long sizeof_cooked_register_status;
 
-  /* Offset and size (in 8 bit bytes), of reach register in the
+  /* Offset and size (in 8 bit bytes), of each register in the
      register cache.  All registers (including those in the range
      [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an
      offset.  */
@@ -217,22 +215,22 @@ regcache_xmalloc_1 (struct gdbarch *gdbarch, struct address_space *aspace,
 
   gdb_assert (gdbarch != NULL);
   descr = regcache_descr (gdbarch);
-  regcache = XMALLOC (struct regcache);
+  regcache = XNEW (struct regcache);
   regcache->descr = descr;
   regcache->readonly_p = readonly_p;
   if (readonly_p)
     {
       regcache->registers
-       = XCALLOC (descr->sizeof_cooked_registers, gdb_byte);
+       = XCNEWVEC (gdb_byte, descr->sizeof_cooked_registers);
       regcache->register_status
-       = XCALLOC (descr->sizeof_cooked_register_status, gdb_byte);
+       = XCNEWVEC (signed char, descr->sizeof_cooked_register_status);
     }
   else
     {
       regcache->registers
-       = XCALLOC (descr->sizeof_raw_registers, gdb_byte);
+       = XCNEWVEC (gdb_byte, descr->sizeof_raw_registers);
       regcache->register_status
-       = XCALLOC (descr->sizeof_raw_register_status, gdb_byte);
+       = XCNEWVEC (signed char, descr->sizeof_raw_register_status);
     }
   regcache->aspace = aspace;
   regcache->ptid = minus_one_ptid;
@@ -267,6 +265,32 @@ make_cleanup_regcache_xfree (struct regcache *regcache)
   return make_cleanup (do_regcache_xfree, regcache);
 }
 
+/* Cleanup routines for invalidating a register.  */
+
+struct register_to_invalidate
+{
+  struct regcache *regcache;
+  int regnum;
+};
+
+static void
+do_regcache_invalidate (void *data)
+{
+  struct register_to_invalidate *reg = data;
+
+  regcache_invalidate (reg->regcache, reg->regnum);
+}
+
+static struct cleanup *
+make_cleanup_regcache_invalidate (struct regcache *regcache, int regnum)
+{
+  struct register_to_invalidate* reg = XNEW (struct register_to_invalidate);
+
+  reg->regcache = regcache;
+  reg->regnum = regnum;
+  return make_cleanup_dtor (do_regcache_invalidate, (void *) reg, xfree);
+}
+
 /* Return REGCACHE's architecture.  */
 
 struct gdbarch *
@@ -330,7 +354,7 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read,
     }
 }
 
-void
+static void
 regcache_restore (struct regcache *dst,
                  regcache_cooked_read_ftype *cooked_read,
                  void *cooked_read_context)
@@ -350,9 +374,10 @@ regcache_restore (struct regcache *dst,
     {
       if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup))
        {
-         int valid = cooked_read (cooked_read_context, regnum, buf);
+         enum register_status status;
 
-         if (valid)
+         status = cooked_read (cooked_read_context, regnum, buf);
+         if (status == REG_VALID)
            regcache_cooked_write (dst, regnum, buf);
        }
     }
@@ -366,6 +391,9 @@ do_cooked_read (void *src, int regnum, gdb_byte *buf)
   return regcache_cooked_read (regcache, regnum, buf);
 }
 
+static void regcache_cpy_no_passthrough (struct regcache *dst,
+                                        struct regcache *src);
+
 void
 regcache_cpy (struct regcache *dst, struct regcache *src)
 {
@@ -382,7 +410,12 @@ regcache_cpy (struct regcache *dst, struct regcache *src)
     regcache_cpy_no_passthrough (dst, src);
 }
 
-void
+/* Copy/duplicate the contents of a register cache.  Unlike regcache_cpy,
+   which is pass-through, this does not go through to the target.
+   Only values values already in the cache are transferred.  The SRC and DST
+   buffers must not overlap.  */
+
+static void
 regcache_cpy_no_passthrough (struct regcache *dst, struct regcache *src)
 {
   gdb_assert (src != NULL && dst != NULL);
@@ -409,7 +442,7 @@ regcache_dup (struct regcache *src)
   return newbuf;
 }
 
-int
+enum register_status
 regcache_register_status (const struct regcache *regcache, int regnum)
 {
   gdb_assert (regcache != NULL);
@@ -449,17 +482,33 @@ struct regcache_list
 static struct regcache_list *current_regcache;
 
 struct regcache *
-get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
+get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch,
+                                struct address_space *aspace)
 {
   struct regcache_list *list;
   struct regcache *new_regcache;
-  struct address_space *aspace;
 
   for (list = current_regcache; list; list = list->next)
     if (ptid_equal (list->regcache->ptid, ptid)
        && get_regcache_arch (list->regcache) == gdbarch)
       return list->regcache;
 
+  new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0);
+  new_regcache->ptid = ptid;
+
+  list = xmalloc (sizeof (struct regcache_list));
+  list->regcache = new_regcache;
+  list->next = current_regcache;
+  current_regcache = list;
+
+  return new_regcache;
+}
+
+struct regcache *
+get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
+{
+  struct address_space *aspace;
+
   /* For the benefit of "maint print registers" & co when debugging an
      executable, allow dumping the regcache even when there is no
      thread selected (target_thread_address_space internal-errors if
@@ -470,15 +519,7 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
            ? NULL
            : target_thread_address_space (ptid));
 
-  new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0);
-  new_regcache->ptid = ptid;
-
-  list = xmalloc (sizeof (struct regcache_list));
-  list->regcache = new_regcache;
-  list->next = current_regcache;
-  current_regcache = list;
-
-  return new_regcache;
+  return get_thread_arch_aspace_regcache  (ptid, gdbarch, aspace);
 }
 
 static ptid_t current_thread_ptid;
@@ -502,6 +543,13 @@ get_current_regcache (void)
   return get_thread_regcache (inferior_ptid);
 }
 
+/* See common/common-regcache.h.  */
+
+struct regcache *
+get_thread_regcache_for_ptid (ptid_t ptid)
+{
+  return get_thread_regcache (ptid);
+}
 
 /* Observer for the target_changed event.  */
 
@@ -538,7 +586,6 @@ void
 registers_changed_ptid (ptid_t ptid)
 {
   struct regcache_list *list, **list_link;
-  int wildcard = ptid_equal (ptid, minus_one_ptid);
 
   list = current_regcache;
   list_link = &current_regcache;
@@ -559,13 +606,13 @@ registers_changed_ptid (ptid_t ptid)
       list = *list_link;
     }
 
-  if (wildcard || ptid_equal (ptid, current_thread_ptid))
+  if (ptid_match (current_thread_ptid, ptid))
     {
       current_thread_ptid = null_ptid;
       current_thread_arch = NULL;
     }
 
-  if (wildcard || ptid_equal (ptid, inferior_ptid))
+  if (ptid_match (inferior_ptid, ptid))
     {
       /* We just deleted the regcache of the current thread.  Need to
         forget about any frames we have cached, too.  */
@@ -698,8 +745,6 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
     {
       /* Read-only register cache, perhaps the cooked value was
         cached?  */
-      struct gdbarch *gdbarch = regcache->descr->gdbarch;
-
       if (regcache->register_status[regnum] == REG_VALID)
        memcpy (buf, register_buffer (regcache, regnum),
                regcache->descr->sizeof_register[regnum]);
@@ -708,11 +753,66 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf)
 
       return regcache->register_status[regnum];
     }
+  else if (gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *mark, *computed;
+      enum register_status result = REG_VALID;
+
+      mark = value_mark ();
+
+      computed = gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+                                                    regcache, regnum);
+      if (value_entirely_available (computed))
+       memcpy (buf, value_contents_raw (computed),
+               regcache->descr->sizeof_register[regnum]);
+      else
+       {
+         memset (buf, 0, regcache->descr->sizeof_register[regnum]);
+         result = REG_UNAVAILABLE;
+       }
+
+      value_free_to_mark (mark);
+
+      return result;
+    }
   else
     return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache,
                                         regnum, buf);
 }
 
+struct value *
+regcache_cooked_read_value (struct regcache *regcache, int regnum)
+{
+  gdb_assert (regnum >= 0);
+  gdb_assert (regnum < regcache->descr->nr_cooked_registers);
+
+  if (regnum < regcache->descr->nr_raw_registers
+      || (regcache->readonly_p
+         && regcache->register_status[regnum] != REG_UNKNOWN)
+      || !gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch))
+    {
+      struct value *result;
+
+      result = allocate_value (register_type (regcache->descr->gdbarch,
+                                             regnum));
+      VALUE_LVAL (result) = lval_register;
+      VALUE_REGNUM (result) = regnum;
+
+      /* It is more efficient in general to do this delegation in this
+        direction than in the other one, even though the value-based
+        API is preferred.  */
+      if (regcache_cooked_read (regcache, regnum,
+                               value_contents_raw (result)) == REG_UNAVAILABLE)
+       mark_value_bytes_unavailable (result, 0,
+                                     TYPE_LENGTH (value_type (result)));
+
+      return result;
+    }
+  else
+    return gdbarch_pseudo_register_read_value (regcache->descr->gdbarch,
+                                              regcache, regnum);
+}
+
 enum register_status
 regcache_cooked_read_signed (struct regcache *regcache, int regnum,
                             LONGEST *val)
@@ -785,7 +885,8 @@ void
 regcache_raw_write (struct regcache *regcache, int regnum,
                    const gdb_byte *buf)
 {
-  struct cleanup *old_chain;
+  struct cleanup *chain_before_save_inferior;
+  struct cleanup *chain_before_invalidate_register;
 
   gdb_assert (regcache != NULL && buf != NULL);
   gdb_assert (regnum >= 0 && regnum < regcache->descr->nr_raw_registers);
@@ -803,16 +904,26 @@ regcache_raw_write (struct regcache *regcache, int regnum,
                  regcache->descr->sizeof_register[regnum]) == 0))
     return;
 
-  old_chain = save_inferior_ptid ();
+  chain_before_save_inferior = save_inferior_ptid ();
   inferior_ptid = regcache->ptid;
 
   target_prepare_to_store (regcache);
   memcpy (register_buffer (regcache, regnum), buf,
          regcache->descr->sizeof_register[regnum]);
   regcache->register_status[regnum] = REG_VALID;
+
+  /* Register a cleanup function for invalidating the register after it is
+     written, in case of a failure.  */
+  chain_before_invalidate_register
+    = make_cleanup_regcache_invalidate (regcache, regnum);
+
   target_store_registers (regcache, regnum);
 
-  do_cleanups (old_chain);
+  /* The target did not throw an error so we can discard invalidating the
+     register and restore the cleanup chain to what it was.  */
+  discard_cleanups (chain_before_invalidate_register);
+
+  do_cleanups (chain_before_save_inferior);
 }
 
 void
@@ -970,6 +1081,92 @@ regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
   memcpy (buf, regbuf, size);
 }
 
+/* Transfer a single or all registers belonging to a certain register
+   set to or from a buffer.  This is the main worker function for
+   regcache_supply_regset and regcache_collect_regset.  */
+
+static void
+regcache_transfer_regset (const struct regset *regset,
+                         const struct regcache *regcache,
+                         struct regcache *out_regcache,
+                         int regnum, const void *in_buf,
+                         void *out_buf, size_t size)
+{
+  const struct regcache_map_entry *map;
+  int offs = 0, count;
+
+  for (map = regset->regmap; (count = map->count) != 0; map++)
+    {
+      int regno = map->regno;
+      int slot_size = map->size;
+
+      if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
+       slot_size = regcache->descr->sizeof_register[regno];
+
+      if (regno == REGCACHE_MAP_SKIP
+         || (regnum != -1
+             && (regnum < regno || regnum >= regno + count)))
+         offs += count * slot_size;
+
+      else if (regnum == -1)
+       for (; count--; regno++, offs += slot_size)
+         {
+           if (offs + slot_size > size)
+             break;
+
+           if (out_buf)
+             regcache_raw_collect (regcache, regno,
+                                   (gdb_byte *) out_buf + offs);
+           else
+             regcache_raw_supply (out_regcache, regno, in_buf
+                                  ? (const gdb_byte *) in_buf + offs
+                                  : NULL);
+         }
+      else
+       {
+         /* Transfer a single register and return.  */
+         offs += (regnum - regno) * slot_size;
+         if (offs + slot_size > size)
+           return;
+
+         if (out_buf)
+           regcache_raw_collect (regcache, regnum,
+                                 (gdb_byte *) out_buf + offs);
+         else
+           regcache_raw_supply (out_regcache, regnum, in_buf
+                                ? (const gdb_byte *) in_buf + offs
+                                : NULL);
+         return;
+       }
+    }
+}
+
+/* Supply register REGNUM from BUF to REGCACHE, using the register map
+   in REGSET.  If REGNUM is -1, do this for all registers in REGSET.
+   If BUF is NULL, set the register(s) to "unavailable" status. */
+
+void
+regcache_supply_regset (const struct regset *regset,
+                       struct regcache *regcache,
+                       int regnum, const void *buf, size_t size)
+{
+  regcache_transfer_regset (regset, regcache, regcache, regnum,
+                           buf, NULL, size);
+}
+
+/* Collect register REGNUM from REGCACHE to BUF, using the register
+   map in REGSET.  If REGNUM is -1, do this for all registers in
+   REGSET.  */
+
+void
+regcache_collect_regset (const struct regset *regset,
+                        const struct regcache *regcache,
+                        int regnum, void *buf, size_t size)
+{
+  regcache_transfer_regset (regset, regcache, NULL, regnum,
+                           NULL, buf, size);
+}
+
 
 /* Special handling for register PC.  */
 
@@ -1029,31 +1226,11 @@ reg_flush_command (char *command, int from_tty)
     printf_filtered (_("Register cache flushed.\n"));
 }
 
-static void
-dump_endian_bytes (struct ui_file *file, enum bfd_endian endian,
-                  const unsigned char *buf, long len)
-{
-  int i;
-
-  switch (endian)
-    {
-    case BFD_ENDIAN_BIG:
-      for (i = 0; i < len; i++)
-       fprintf_unfiltered (file, "%02x", buf[i]);
-      break;
-    case BFD_ENDIAN_LITTLE:
-      for (i = len - 1; i >= 0; i--)
-       fprintf_unfiltered (file, "%02x", buf[i]);
-      break;
-    default:
-      internal_error (__FILE__, __LINE__, _("Bad switch"));
-    }
-}
-
 enum regcache_dump_what
 {
   regcache_dump_none, regcache_dump_raw,
-  regcache_dump_cooked, regcache_dump_groups
+  regcache_dump_cooked, regcache_dump_groups,
+  regcache_dump_remote
 };
 
 static void
@@ -1068,7 +1245,7 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
   int footnote_register_offset = 0;
   int footnote_register_type_name_null = 0;
   long register_offset = 0;
-  unsigned char buf[MAX_REGISTER_SIZE];
+  gdb_byte buf[MAX_REGISTER_SIZE];
 
 #if 0
   fprintf_unfiltered (file, "nr_raw_registers %d\n",
@@ -1173,7 +1350,7 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
                t = n;
              }
            /* Chop a leading builtin_type.  */
-           if (strncmp (t, blt, strlen (blt)) == 0)
+           if (startswith (t, blt))
              t += strlen (blt);
          }
        fprintf_unfiltered (file, " %-15s", t);
@@ -1196,10 +1373,9 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
          else
            {
              regcache_raw_read (regcache, regnum, buf);
-             fprintf_unfiltered (file, "0x");
-             dump_endian_bytes (file,
-                                gdbarch_byte_order (gdbarch), buf,
-                                regcache->descr->sizeof_register[regnum]);
+             print_hex_chars (file, buf,
+                              regcache->descr->sizeof_register[regnum],
+                              gdbarch_byte_order (gdbarch));
            }
        }
 
@@ -1218,12 +1394,9 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
              else if (status == REG_UNAVAILABLE)
                fprintf_unfiltered (file, "<unavailable>");
              else
-               {
-                 fprintf_unfiltered (file, "0x");
-                 dump_endian_bytes (file,
-                                    gdbarch_byte_order (gdbarch), buf,
-                                    regcache->descr->sizeof_register[regnum]);
-               }
+               print_hex_chars (file, buf,
+                                regcache->descr->sizeof_register[regnum],
+                                gdbarch_byte_order (gdbarch));
            }
        }
 
@@ -1251,6 +1424,23 @@ regcache_dump (struct regcache *regcache, struct ui_file *file,
            }
        }
 
+      /* Remote packet configuration.  */
+      if (what_to_dump == regcache_dump_remote)
+       {
+         if (regnum < 0)
+           {
+             fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
+           }
+         else if (regnum < regcache->descr->nr_raw_registers)
+           {
+             int pnum, poffset;
+
+             if (remote_register_number_and_offset (get_regcache_arch (regcache), regnum,
+                                                    &pnum, &poffset))
+               fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
+           }
+       }
+
       fprintf_unfiltered (file, "\n");
     }
 
@@ -1309,6 +1499,12 @@ maintenance_print_register_groups (char *args, int from_tty)
   regcache_print (args, regcache_dump_groups);
 }
 
+static void
+maintenance_print_remote_registers (char *args, int from_tty)
+{
+  regcache_print (args, regcache_dump_remote);
+}
+
 extern initialize_file_ftype _initialize_regcache; /* -Wmissing-prototype */
 
 void
@@ -1342,5 +1538,11 @@ _initialize_regcache (void)
             "including each register's group.\n"
             "Takes an optional file parameter."),
           &maintenanceprintlist);
+  add_cmd ("remote-registers", class_maintenance,
+          maintenance_print_remote_registers, _("\
+Print the internal register configuration including each register's\n\
+remote register number and buffer offset in the g/G packets.\n\
+Takes an optional file parameter."),
+          &maintenanceprintlist);
 
 }
This page took 0.03832 seconds and 4 git commands to generate.