diff options
author | Yao Qi <yao.qi@linaro.org> | 2017-11-28 17:52:12 +0000 |
---|---|---|
committer | Yao Qi <yao.qi@linaro.org> | 2018-01-22 11:21:18 +0000 |
commit | 7e58b2bb292bf40bec07f50e52d8447e6c983654 (patch) | |
tree | 1aaffb8076f6049acf47762922b5ecad17db28ff | |
parent | fd57b1a23bbf3a8ebd8491935a4f36e1c1f2325d (diff) | |
download | gdb-7e58b2bb292bf40bec07f50e52d8447e6c983654.zip gdb-7e58b2bb292bf40bec07f50e52d8447e6c983654.tar.gz gdb-7e58b2bb292bf40bec07f50e52d8447e6c983654.tar.bz2 |
Replace regcache::dump with class register_dump
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:
2017-11-28 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.
-rw-r--r-- | gdb/regcache.c | 483 | ||||
-rw-r--r-- | gdb/regcache.h | 9 |
2 files changed, 285 insertions, 207 deletions
diff --git a/gdb/regcache.c b/gdb/regcache.c index 2857e47..918af8e 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -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 diff --git a/gdb/regcache.h b/gdb/regcache.h index d4e9243..5d923ba 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -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 @@ -372,8 +365,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; |