Replace regcache::dump with class register_dump
authorYao Qi <yao.qi@linaro.org>
Wed, 21 Feb 2018 11:20:03 +0000 (11:20 +0000)
committerYao Qi <yao.qi@linaro.org>
Wed, 21 Feb 2018 11:20:03 +0000 (11:20 +0000)
Nowadays, we need to dump registers contents from "readwrite" regcache and
"readonly" regcache,

  if (target_has_registers)
    get_current_regcache ()->dump (out, what_to_dump);
  else
    {
      /* For the benefit of "maint print registers" & co when
         debugging an executable, allow dumping a regcache even when
         there is no thread selected / no registers.  */
      regcache dummy_regs (target_gdbarch ());
      dummy_regs.dump (out, what_to_dump);
    }

since we'll have two different types/classes for "readwrite" regcache and
"readonly" regcache, we have to move dump method to their parent class,
reg_buffer.  However, the functionality of "dump" looks unnecessary to
reg_buffer (because some dump modes like regcache_dump_none,
regcache_dump_remote and regcache_dump_groups don't need reg_buffer at
all, they need gdbarch to do the dump), so I decide to move "dump" into a
separate classes, and each sub-class is about each mode of dump.

gdb:

2018-02-21  Yao Qi  <yao.qi@linaro.org>

* regcache.c (class register_dump): New class.
(register_dump_regcache, register_dump_none): New class.
(register_dump_remote, register_dump_groups): New class.
(regcache_print): Update.
* regcache.h (regcache_dump_what): Move it to regcache.c.
(regcache) <dump>: Remove.

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

index eb8521ee647ed23b91f2653c3397b43d3a803f2e..64b4cd2479deb22195ad39e1bdb00c11b9289f41 100644 (file)
@@ -1,3 +1,12 @@
+2018-02-21  Yao Qi  <yao.qi@linaro.org>
+
+       * regcache.c (class register_dump): New class.
+       (register_dump_regcache, register_dump_none): New class.
+       (register_dump_remote, register_dump_groups): New class.
+       (regcache_print): Update.
+       * regcache.h (regcache_dump_what): Move it to regcache.c.
+       (regcache) <dump>: Remove.
+
 2018-02-21  Yao Qi  <yao.qi@linaro.org>
 
        * jit.c (struct jit_unwind_private) <regcache>: Change its type to
index c75723118449ab0db41b10f19f134391b283d7cc..389c016972f8bd910520e0991e75cae7d1aa3d8a 100644 (file)
@@ -1315,231 +1315,284 @@ reg_flush_command (const char *command, int from_tty)
     printf_filtered (_("Register cache flushed.\n"));
 }
 
-void
-regcache::dump (ui_file *file, enum regcache_dump_what what_to_dump)
+/* An abstract base class for register dump.  */
+
+class register_dump
 {
-  struct gdbarch *gdbarch = m_descr->gdbarch;
-  int regnum;
-  int footnote_nr = 0;
-  int footnote_register_offset = 0;
-  int footnote_register_type_name_null = 0;
-  long register_offset = 0;
+public:
+  void dump (ui_file *file)
+  {
+    auto descr = regcache_descr (m_gdbarch);
+    int regnum;
+    int footnote_nr = 0;
+    int footnote_register_offset = 0;
+    int footnote_register_type_name_null = 0;
+    long register_offset = 0;
+
+    gdb_assert (descr->nr_cooked_registers
+               == (gdbarch_num_regs (m_gdbarch)
+                   + gdbarch_num_pseudo_regs (m_gdbarch)));
+
+    for (regnum = -1; regnum < descr->nr_cooked_registers; regnum++)
+      {
+       /* Name.  */
+       if (regnum < 0)
+         fprintf_unfiltered (file, " %-10s", "Name");
+       else
+         {
+           const char *p = gdbarch_register_name (m_gdbarch, regnum);
 
-  gdb_assert (m_descr->nr_cooked_registers
-             == (gdbarch_num_regs (gdbarch)
-                 + gdbarch_num_pseudo_regs (gdbarch)));
+           if (p == NULL)
+             p = "";
+           else if (p[0] == '\0')
+             p = "''";
+           fprintf_unfiltered (file, " %-10s", p);
+         }
 
-  for (regnum = -1; regnum < m_descr->nr_cooked_registers; regnum++)
-    {
-      /* Name.  */
-      if (regnum < 0)
-       fprintf_unfiltered (file, " %-10s", "Name");
-      else
-       {
-         const char *p = gdbarch_register_name (gdbarch, regnum);
+       /* Number.  */
+       if (regnum < 0)
+         fprintf_unfiltered (file, " %4s", "Nr");
+       else
+         fprintf_unfiltered (file, " %4d", regnum);
 
-         if (p == NULL)
-           p = "";
-         else if (p[0] == '\0')
-           p = "''";
-         fprintf_unfiltered (file, " %-10s", p);
-       }
+       /* Relative number.  */
+       if (regnum < 0)
+         fprintf_unfiltered (file, " %4s", "Rel");
+       else if (regnum < gdbarch_num_regs (m_gdbarch))
+         fprintf_unfiltered (file, " %4d", regnum);
+       else
+         fprintf_unfiltered (file, " %4d",
+                             (regnum - gdbarch_num_regs (m_gdbarch)));
 
-      /* Number.  */
-      if (regnum < 0)
-       fprintf_unfiltered (file, " %4s", "Nr");
-      else
-       fprintf_unfiltered (file, " %4d", regnum);
+       /* Offset.  */
+       if (regnum < 0)
+         fprintf_unfiltered (file, " %6s  ", "Offset");
+       else
+         {
+           fprintf_unfiltered (file, " %6ld",
+                               descr->register_offset[regnum]);
+           if (register_offset != descr->register_offset[regnum]
+               || (regnum > 0
+                   && (descr->register_offset[regnum]
+                       != (descr->register_offset[regnum - 1]
+                           + descr->sizeof_register[regnum - 1])))
+               )
+             {
+               if (!footnote_register_offset)
+                 footnote_register_offset = ++footnote_nr;
+               fprintf_unfiltered (file, "*%d", footnote_register_offset);
+             }
+           else
+             fprintf_unfiltered (file, "  ");
+           register_offset = (descr->register_offset[regnum]
+                              + descr->sizeof_register[regnum]);
+         }
 
-      /* Relative number.  */
-      if (regnum < 0)
-       fprintf_unfiltered (file, " %4s", "Rel");
-      else if (regnum < gdbarch_num_regs (gdbarch))
-       fprintf_unfiltered (file, " %4d", regnum);
-      else
-       fprintf_unfiltered (file, " %4d",
-                           (regnum - gdbarch_num_regs (gdbarch)));
+       /* Size.  */
+       if (regnum < 0)
+         fprintf_unfiltered (file, " %5s ", "Size");
+       else
+         fprintf_unfiltered (file, " %5ld", descr->sizeof_register[regnum]);
 
-      /* Offset.  */
-      if (regnum < 0)
-       fprintf_unfiltered (file, " %6s  ", "Offset");
-      else
+       /* Type.  */
        {
-         fprintf_unfiltered (file, " %6ld",
-                             m_descr->register_offset[regnum]);
-         if (register_offset != m_descr->register_offset[regnum]
-             || (regnum > 0
-                 && (m_descr->register_offset[regnum]
-                     != (m_descr->register_offset[regnum - 1]
-                         + m_descr->sizeof_register[regnum - 1])))
-             )
+         const char *t;
+         std::string name_holder;
+
+         if (regnum < 0)
+           t = "Type";
+         else
            {
-             if (!footnote_register_offset)
-               footnote_register_offset = ++footnote_nr;
-             fprintf_unfiltered (file, "*%d", footnote_register_offset);
+             static const char blt[] = "builtin_type";
+
+             t = TYPE_NAME (register_type (m_gdbarch, regnum));
+             if (t == NULL)
+               {
+                 if (!footnote_register_type_name_null)
+                   footnote_register_type_name_null = ++footnote_nr;
+                 name_holder = string_printf ("*%d",
+                                              footnote_register_type_name_null);
+                 t = name_holder.c_str ();
+               }
+             /* Chop a leading builtin_type.  */
+             if (startswith (t, blt))
+               t += strlen (blt);
            }
-         else
-           fprintf_unfiltered (file, "  ");
-         register_offset = (m_descr->register_offset[regnum]
-                            + m_descr->sizeof_register[regnum]);
+         fprintf_unfiltered (file, " %-15s", t);
        }
 
-      /* Size.  */
-      if (regnum < 0)
-       fprintf_unfiltered (file, " %5s ", "Size");
-      else
-       fprintf_unfiltered (file, " %5ld", m_descr->sizeof_register[regnum]);
+       /* Leading space always present.  */
+       fprintf_unfiltered (file, " ");
 
-      /* Type.  */
-      {
-       const char *t;
-       std::string name_holder;
+       dump_reg (file, regnum);
 
-       if (regnum < 0)
-         t = "Type";
+       fprintf_unfiltered (file, "\n");
+      }
+
+    if (footnote_register_offset)
+      fprintf_unfiltered (file, "*%d: Inconsistent register offsets.\n",
+                         footnote_register_offset);
+    if (footnote_register_type_name_null)
+      fprintf_unfiltered (file,
+                         "*%d: Register type's name NULL.\n",
+                         footnote_register_type_name_null);
+  }
+
+  virtual ~register_dump () {};
+
+protected:
+  register_dump (gdbarch *arch)
+    : m_gdbarch (arch)
+  {}
+
+  /* Dump the register REGNUM contents.  If REGNUM is -1, print the
+     header.  */
+  virtual void dump_reg (ui_file *file, int regnum) = 0;
+
+  gdbarch *m_gdbarch;
+};
+
+/* Dump registers from regcache, used for dump raw registers and
+   cooked registers.  */
+
+class register_dump_regcache : public register_dump
+{
+public:
+  register_dump_regcache (regcache *regcache, bool dump_pseudo)
+    : register_dump (regcache->arch ()), m_regcache (regcache),
+      m_dump_pseudo (dump_pseudo)
+  {
+  }
+
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+       if (m_dump_pseudo)
+         fprintf_unfiltered (file, "Cooked value");
        else
+         fprintf_unfiltered (file, "Raw value");
+      }
+    else
+      {
+       if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
          {
-           static const char blt[] = "builtin_type";
+           auto size = register_size (m_gdbarch, regnum);
+
+           if (size == 0)
+             return;
 
-           t = TYPE_NAME (register_type (arch (), regnum));
-           if (t == NULL)
+           gdb::def_vector<gdb_byte> buf (size);
+           auto status = m_regcache->cooked_read (regnum, buf.data ());
+
+           if (status == REG_UNKNOWN)
+             fprintf_unfiltered (file, "<invalid>");
+           else if (status == REG_UNAVAILABLE)
+             fprintf_unfiltered (file, "<unavailable>");
+           else
              {
-               if (!footnote_register_type_name_null)
-                 footnote_register_type_name_null = ++footnote_nr;
-               name_holder = string_printf ("*%d",
-                                            footnote_register_type_name_null);
-               t = name_holder.c_str ();
+               print_hex_chars (file, buf.data (), size,
+                                gdbarch_byte_order (m_gdbarch), true);
              }
-           /* Chop a leading builtin_type.  */
-           if (startswith (t, blt))
-             t += strlen (blt);
          }
-       fprintf_unfiltered (file, " %-15s", t);
+       else
+         {
+           /* Just print "<cooked>" for pseudo register when
+              regcache_dump_raw.  */
+           fprintf_unfiltered (file, "<cooked>");
+         }
       }
+  }
 
-      /* Leading space always present.  */
-      fprintf_unfiltered (file, " ");
+private:
+  regcache *m_regcache;
 
-      /* Value, raw.  */
-      if (what_to_dump == regcache_dump_raw)
-       {
-         if (regnum < 0)
-           fprintf_unfiltered (file, "Raw value");
-         else if (regnum >= num_raw_registers ())
-           fprintf_unfiltered (file, "<cooked>");
-         else if (get_register_status (regnum) == REG_UNKNOWN)
-           fprintf_unfiltered (file, "<invalid>");
-         else if (get_register_status (regnum) == REG_UNAVAILABLE)
-           fprintf_unfiltered (file, "<unavailable>");
-         else
-           {
-             raw_update (regnum);
-             print_hex_chars (file, register_buffer (regnum),
-                              m_descr->sizeof_register[regnum],
-                              gdbarch_byte_order (gdbarch), true);
-           }
-       }
+  /* Dump pseudo registers or not.  */
+  const bool m_dump_pseudo;
+};
 
-      /* Value, cooked.  */
-      if (what_to_dump == regcache_dump_cooked)
-       {
-         if (regnum < 0)
-           fprintf_unfiltered (file, "Cooked value");
-         else
-           {
-             const gdb_byte *buf = NULL;
-             enum register_status status;
-             struct value *value = NULL;
+/* For "maint print registers".  */
 
-             if (regnum < num_raw_registers ())
-               {
-                 raw_update (regnum);
-                 status = get_register_status (regnum);
-                 buf = register_buffer (regnum);
-               }
-             else
-               {
-                 value = cooked_read_value (regnum);
-
-                 if (!value_optimized_out (value)
-                     && value_entirely_available (value))
-                   {
-                     status = REG_VALID;
-                     buf = value_contents_all (value);
-                   }
-                 else
-                   status = REG_UNAVAILABLE;
-               }
+class register_dump_none : public register_dump
+{
+public:
+  register_dump_none (gdbarch *arch)
+    : register_dump (arch)
+  {}
 
-             if (status == REG_UNKNOWN)
-               fprintf_unfiltered (file, "<invalid>");
-             else if (status == REG_UNAVAILABLE)
-               fprintf_unfiltered (file, "<unavailable>");
-             else
-               print_hex_chars (file, buf,
-                                m_descr->sizeof_register[regnum],
-                                gdbarch_byte_order (gdbarch), true);
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {}
+};
 
-             if (value != NULL)
-               {
-                 release_value (value);
-                 value_free (value);
-               }
-           }
-       }
+/* For "maint print remote-registers".  */
 
-      /* Group members.  */
-      if (what_to_dump == regcache_dump_groups)
-       {
-         if (regnum < 0)
-           fprintf_unfiltered (file, "Groups");
-         else
-           {
-             const char *sep = "";
-             struct reggroup *group;
+class register_dump_remote : public register_dump
+{
+public:
+  register_dump_remote (gdbarch *arch)
+    : register_dump (arch)
+  {}
 
-             for (group = reggroup_next (gdbarch, NULL);
-                  group != NULL;
-                  group = reggroup_next (gdbarch, group))
-               {
-                 if (gdbarch_register_reggroup_p (gdbarch, regnum, group))
-                   {
-                     fprintf_unfiltered (file,
-                                         "%s%s", sep, reggroup_name (group));
-                     sep = ",";
-                   }
-               }
-           }
-       }
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      {
+       fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
+      }
+    else if (regnum < gdbarch_num_regs (m_gdbarch))
+      {
+       int pnum, poffset;
 
-      /* Remote packet configuration.  */
-      if (what_to_dump == regcache_dump_remote)
-       {
-         if (regnum < 0)
-           {
-             fprintf_unfiltered (file, "Rmt Nr  g/G Offset");
-           }
-         else if (regnum < num_raw_registers ())
-           {
-             int pnum, poffset;
+       if (remote_register_number_and_offset (m_gdbarch, regnum,
+                                              &pnum, &poffset))
+         fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
+      }
+  }
+};
 
-             if (remote_register_number_and_offset (arch (), regnum,
-                                                    &pnum, &poffset))
-               fprintf_unfiltered (file, "%7d %11d", pnum, poffset);
-           }
-       }
+/* For "maint print register-groups".  */
 
-      fprintf_unfiltered (file, "\n");
-    }
+class register_dump_groups : public register_dump
+{
+public:
+  register_dump_groups (gdbarch *arch)
+    : register_dump (arch)
+  {}
 
-  if (footnote_register_offset)
-    fprintf_unfiltered (file, "*%d: Inconsistent register offsets.\n",
-                       footnote_register_offset);
-  if (footnote_register_type_name_null)
-    fprintf_unfiltered (file, 
-                       "*%d: Register type's name NULL.\n",
-                       footnote_register_type_name_null);
-}
+protected:
+  void dump_reg (ui_file *file, int regnum) override
+  {
+    if (regnum < 0)
+      fprintf_unfiltered (file, "Groups");
+    else
+      {
+       const char *sep = "";
+       struct reggroup *group;
+
+       for (group = reggroup_next (m_gdbarch, NULL);
+            group != NULL;
+            group = reggroup_next (m_gdbarch, group))
+         {
+           if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
+             {
+               fprintf_unfiltered (file,
+                                   "%s%s", sep, reggroup_name (group));
+               sep = ",";
+             }
+         }
+      }
+  }
+};
+
+enum regcache_dump_what
+{
+  regcache_dump_none, regcache_dump_raw,
+  regcache_dump_cooked, regcache_dump_groups,
+  regcache_dump_remote
+};
 
 static void
 regcache_print (const char *args, enum regcache_dump_what what_to_dump)
@@ -1557,16 +1610,50 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
       out = &file;
     }
 
+  std::unique_ptr<register_dump> dump;
+  std::unique_ptr<regcache> regs;
+  gdbarch *gdbarch;
+
   if (target_has_registers)
-    get_current_regcache ()->dump (out, what_to_dump);
+    gdbarch = get_current_regcache ()->arch ();
   else
+    gdbarch = target_gdbarch ();
+
+  switch (what_to_dump)
     {
-      /* For the benefit of "maint print registers" & co when
-        debugging an executable, allow dumping a regcache even when
-        there is no thread selected / no registers.  */
-      regcache dummy_regs (target_gdbarch ());
-      dummy_regs.dump (out, what_to_dump);
+    case regcache_dump_none:
+      dump.reset (new register_dump_none (gdbarch));
+      break;
+    case regcache_dump_remote:
+      dump.reset (new register_dump_remote (gdbarch));
+      break;
+    case regcache_dump_groups:
+      dump.reset (new register_dump_groups (gdbarch));
+      break;
+    case regcache_dump_raw:
+    case regcache_dump_cooked:
+      {
+       regcache *reg;
+
+       if (target_has_registers)
+         reg = get_current_regcache ();
+       else
+         {
+           /* For the benefit of "maint print registers" & co when
+              debugging an executable, allow dumping a regcache even when
+              there is no thread selected / no registers.  */
+           reg = new regcache (target_gdbarch ());
+           regs.reset (reg);
+         }
+
+       auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
+
+       dump.reset (new register_dump_regcache (reg, dump_pseudo));
+      }
+      break;
     }
+
+  dump->dump (out);
 }
 
 static void
index beebf99c05ed3b923822ac04abc76e705bb7333e..a377d2d4defd34d86a169775b14885b204281770 100644 (file)
@@ -194,13 +194,6 @@ typedef enum register_status (regcache_cooked_read_ftype) (void *src,
                                                           int regnum,
                                                           gdb_byte *buf);
 
-enum regcache_dump_what
-{
-  regcache_dump_none, regcache_dump_raw,
-  regcache_dump_cooked, regcache_dump_groups,
-  regcache_dump_remote
-};
-
 /* A (register_number, register_value) pair.  */
 
 typedef struct cached_reg
@@ -374,8 +367,6 @@ public:
   void collect_regset (const struct regset *regset, int regnum,
                       void *buf, size_t size) const;
 
-  void dump (ui_file *file, enum regcache_dump_what what_to_dump);
-
   ptid_t ptid () const
   {
     return m_ptid;