aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2024-10-09 15:25:06 -0600
committerTom Tromey <tom@tromey.com>2024-12-03 18:42:57 -0700
commit17ecffd7669d605273d1f9951118b6ab1c09ed45 (patch)
tree8f4a601f743cb01767ef5ae3d3c897f8772f4b92 /gdb
parent20e8a322b1d0732ce758a106d10beee25180f9ec (diff)
downloadgdb-17ecffd7669d605273d1f9951118b6ab1c09ed45.zip
gdb-17ecffd7669d605273d1f9951118b6ab1c09ed45.tar.gz
gdb-17ecffd7669d605273d1f9951118b6ab1c09ed45.tar.bz2
Use ui-out tables in some "maint print" commands
This changes various "maint print" register commands to use ui-out tables rather than the current printf approach. Approved-By: Andrew Burgess <aburgess@redhat.com>
Diffstat (limited to 'gdb')
-rw-r--r--gdb/regcache-dump.c210
-rw-r--r--gdb/regcache.c132
-rw-r--r--gdb/regcache.h14
-rw-r--r--gdb/testsuite/gdb.base/maint.exp4
-rw-r--r--gdb/testsuite/gdb.server/server-run.exp2
5 files changed, 192 insertions, 170 deletions
diff --git a/gdb/regcache-dump.c b/gdb/regcache-dump.c
index e25302d..9be694d 100644
--- a/gdb/regcache-dump.c
+++ b/gdb/regcache-dump.c
@@ -38,43 +38,45 @@ public:
}
protected:
- void dump_reg (ui_file *file, int regnum) override
+
+ int num_additional_headers () override
+ { return 1; }
+
+ void additional_headers (ui_out *out) override
{
- if (regnum < 0)
+ out->table_header (0, ui_left, "value",
+ m_dump_pseudo ? "Cooked value" : "Raw value");
+ }
+
+ void dump_reg (ui_out *out, int regnum) override
+ {
+ if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
{
- if (m_dump_pseudo)
- gdb_printf (file, "Cooked value");
+ auto size = register_size (m_gdbarch, regnum);
+
+ if (size == 0)
+ return;
+
+ gdb::byte_vector buf (size);
+ auto status = m_regcache->cooked_read (regnum, buf.data ());
+
+ if (status == REG_UNKNOWN)
+ out->field_string ("value", "<invalid>");
+ else if (status == REG_UNAVAILABLE)
+ out->field_string ("value", "<unavailable>");
else
- gdb_printf (file, "Raw value");
+ {
+ string_file str;
+ print_hex_chars (&str, buf.data (), size,
+ gdbarch_byte_order (m_gdbarch), true);
+ out->field_stream ("value", str);
+ }
}
else
{
- if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
- {
- auto size = register_size (m_gdbarch, regnum);
-
- if (size == 0)
- return;
-
- gdb::byte_vector buf (size);
- auto status = m_regcache->cooked_read (regnum, buf.data ());
-
- if (status == REG_UNKNOWN)
- gdb_printf (file, "<invalid>");
- else if (status == REG_UNAVAILABLE)
- gdb_printf (file, "<unavailable>");
- else
- {
- print_hex_chars (file, buf.data (), size,
- gdbarch_byte_order (m_gdbarch), true);
- }
- }
- else
- {
- /* Just print "<cooked>" for pseudo register when
- regcache_dump_raw. */
- gdb_printf (file, "<cooked>");
- }
+ /* Just print "<cooked>" for pseudo register when
+ regcache_dump_raw. */
+ out->field_string ("value", "<cooked>");
}
}
@@ -97,39 +99,39 @@ public:
}
protected:
- void dump_reg (ui_file *file, int regnum) override
+
+ int num_additional_headers () override
+ { return 1; }
+
+ void additional_headers (ui_out *out) override
{
- if (regnum < 0)
- {
- if (m_has_pseudo)
- gdb_printf (file, "Cooked value");
- else
- gdb_printf (file, "Raw value");
- }
- else
+ out->table_header (0, ui_left, "value",
+ m_has_pseudo ? "Cooked value" : "Raw value");
+ }
+
+ void dump_reg (ui_out *out, int regnum) override
+ {
+ if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
{
- if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
- {
- auto size = register_size (m_gdbarch, regnum);
+ auto size = register_size (m_gdbarch, regnum);
- if (size == 0)
- return;
+ if (size == 0)
+ return;
- auto status = get_register_status (regnum);
+ auto status = get_register_status (regnum);
- gdb_assert (status != REG_VALID);
+ gdb_assert (status != REG_VALID);
- if (status == REG_UNKNOWN)
- gdb_printf (file, "<invalid>");
- else
- gdb_printf (file, "<unavailable>");
- }
+ if (status == REG_UNKNOWN)
+ out->field_string ("value", "<invalid>");
else
- {
- /* Just print "<cooked>" for pseudo register when
- regcache_dump_raw. */
- gdb_printf (file, "<cooked>");
- }
+ out->field_string ("value", "<unavailable>");
+ }
+ else
+ {
+ /* Just print "<cooked>" for pseudo register when
+ regcache_dump_raw. */
+ out->field_string ("value", "<cooked>");
}
}
};
@@ -144,7 +146,14 @@ public:
{}
protected:
- void dump_reg (ui_file *file, int regnum) override
+
+ int num_additional_headers () override
+ { return 0; }
+
+ void additional_headers (ui_out *out) override
+ { }
+
+ void dump_reg (ui_out *out, int regnum) override
{}
};
@@ -158,24 +167,38 @@ public:
{}
protected:
- void dump_reg (ui_file *file, int regnum) override
+
+ int num_additional_headers () override
+ { return 3; }
+
+ void additional_headers (ui_out *out) override
+ {
+ out->table_header (7, ui_left, "remnum", "Rmt Nr");
+ out->table_header (11, ui_left, "goffset", "g/G Offset");
+ out->table_header (3, ui_left, "expedited", "Expedited");
+ }
+
+ void dump_reg (ui_out *out, int regnum) override
{
- if (regnum < 0)
+ int pnum, poffset;
+
+ if (regnum < gdbarch_num_regs (m_gdbarch)
+ && remote_register_number_and_offset (m_gdbarch, regnum,
+ &pnum, &poffset))
{
- gdb_printf (file, "Rmt Nr g/G Offset Expedited");
+ out->field_signed ("remnum", pnum);
+ out->field_signed ("goffset", poffset);
+
+ if (remote_register_is_expedited (regnum))
+ out->field_string ("expedited", "yes");
+ else
+ out->field_skip ("expedited");
}
- else if (regnum < gdbarch_num_regs (m_gdbarch))
+ else
{
- int pnum, poffset;
-
- if (remote_register_number_and_offset (m_gdbarch, regnum,
- &pnum, &poffset))
- {
- if (remote_register_is_expedited (regnum))
- gdb_printf (file, "%7d %11d yes", pnum, poffset);
- else
- gdb_printf (file, "%7d %11d", pnum, poffset);
- }
+ out->field_skip ("remnum");
+ out->field_skip ("goffset");
+ out->field_skip ("expedited");
}
}
};
@@ -190,22 +213,28 @@ public:
{}
protected:
- void dump_reg (ui_file *file, int regnum) override
+
+ int num_additional_headers () override
+ { return 1; }
+
+ void additional_headers (ui_out *out) override
{
- if (regnum < 0)
- gdb_printf (file, "Groups");
- else
+ out->table_header (0, ui_left, "groups", "Groups");
+ }
+
+ void dump_reg (ui_out *out, int regnum) override
+ {
+ string_file file;
+ const char *sep = "";
+ for (const struct reggroup *group : gdbarch_reggroups (m_gdbarch))
{
- const char *sep = "";
- for (const struct reggroup *group : gdbarch_reggroups (m_gdbarch))
+ if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
{
- if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
- {
- gdb_printf (file, "%s%s", sep, group->name ());
- sep = ",";
- }
+ gdb_printf (&file, "%s%s", sep, group->name ());
+ sep = ",";
}
}
+ out->field_stream ("groups", file);
}
};
@@ -221,15 +250,13 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
{
/* Where to send output. */
stdio_file file;
- ui_file *out;
+ std::optional<ui_out_redirect_pop> redirect;
- if (args == NULL)
- out = gdb_stdout;
- else
+ if (args != nullptr)
{
if (!file.open (args, "w"))
perror_with_name (_("maintenance print architecture"));
- out = &file;
+ redirect.emplace (current_uiout, &file);
}
std::unique_ptr<register_dump> dump;
@@ -241,20 +268,25 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
else
gdbarch = current_inferior ()->arch ();
+ const char *name;
switch (what_to_dump)
{
case regcache_dump_none:
dump = std::make_unique<register_dump_none> (gdbarch);
+ name = "Registers";
break;
case regcache_dump_remote:
dump = std::make_unique<register_dump_remote> (gdbarch);
+ name = "RegisterRemote";
break;
case regcache_dump_groups:
dump = std::make_unique<register_dump_groups> (gdbarch);
+ name = "RegisterGroups";
break;
case regcache_dump_raw:
case regcache_dump_cooked:
{
+ name = "RegisterDump";
auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
if (target_has_registers ())
@@ -272,7 +304,7 @@ regcache_print (const char *args, enum regcache_dump_what what_to_dump)
break;
}
- dump->dump (out);
+ dump->dump (current_uiout, name);
}
static void
diff --git a/gdb/regcache.c b/gdb/regcache.c
index ab3f616..f2c403b 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1519,7 +1519,7 @@ reg_flush_command (const char *command, int from_tty)
}
void
-register_dump::dump (ui_file *file)
+register_dump::dump (ui_out *out, const char *name)
{
auto descr = regcache_descr (m_gdbarch);
int regnum;
@@ -1531,107 +1531,91 @@ register_dump::dump (ui_file *file)
gdb_assert (descr->nr_cooked_registers
== gdbarch_num_cooked_regs (m_gdbarch));
- for (regnum = -1; regnum < descr->nr_cooked_registers; regnum++)
+ ui_out_emit_table table (out, 6 + num_additional_headers (), -1, name);
+ out->table_header (10, ui_left, "name", "Name");
+ out->table_header (4, ui_left, "num", "Nr");
+ out->table_header (4, ui_left, "relnum", "Rel");
+ out->table_header (8, ui_left, "offset", "Offset");
+ out->table_header (5, ui_left, "size", "Size");
+ out->table_header (15, ui_left, "type", "Type");
+ additional_headers (out);
+ out->table_body ();
+
+ for (regnum = 0; regnum < descr->nr_cooked_registers; regnum++)
{
- /* Name. */
- if (regnum < 0)
- gdb_printf (file, " %-10s", "Name");
- else
- {
- const char *p = gdbarch_register_name (m_gdbarch, regnum);
+ ui_out_emit_tuple tuple_emitter (out, nullptr);
- if (p[0] == '\0')
- p = "''";
- gdb_printf (file, " %-10s", p);
- }
+ /* Name. */
+ const char *p = gdbarch_register_name (m_gdbarch, regnum);
+ if (p[0] == '\0')
+ p = "''";
+ out->field_string ("name", p);
/* Number. */
- if (regnum < 0)
- gdb_printf (file, " %4s", "Nr");
- else
- gdb_printf (file, " %4d", regnum);
+ out->field_signed ("num", regnum);
/* Relative number. */
- if (regnum < 0)
- gdb_printf (file, " %4s", "Rel");
- else if (regnum < gdbarch_num_regs (m_gdbarch))
- gdb_printf (file, " %4d", regnum);
+ if (regnum < gdbarch_num_regs (m_gdbarch))
+ out->field_signed ("relnum", regnum);
else
- gdb_printf (file, " %4d",
- (regnum - gdbarch_num_regs (m_gdbarch)));
+ out->field_signed ("relnum", (regnum - gdbarch_num_regs (m_gdbarch)));
/* Offset. */
- if (regnum < 0)
- gdb_printf (file, " %6s ", "Offset");
- else
+ if (register_offset != descr->register_offset[regnum]
+ || (regnum > 0
+ && (descr->register_offset[regnum]
+ != (descr->register_offset[regnum - 1]
+ + descr->sizeof_register[regnum - 1]))))
{
- gdb_printf (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;
- gdb_printf (file, "*%d", footnote_register_offset);
- }
- else
- gdb_printf (file, " ");
- register_offset = (descr->register_offset[regnum]
- + descr->sizeof_register[regnum]);
+ if (!footnote_register_offset)
+ footnote_register_offset = ++footnote_nr;
+ std::string val = string_printf ("%ld*%d",
+ descr->register_offset[regnum],
+ footnote_register_offset);
+ out->field_string ("offset", val);
}
+ else
+ out->field_signed ("offset", descr->register_offset[regnum]);
+ register_offset = (descr->register_offset[regnum]
+ + descr->sizeof_register[regnum]);
/* Size. */
- if (regnum < 0)
- gdb_printf (file, " %5s ", "Size");
- else
- gdb_printf (file, " %5ld", descr->sizeof_register[regnum]);
+ out->field_signed ("size", descr->sizeof_register[regnum]);
/* Type. */
{
const char *t;
std::string name_holder;
- if (regnum < 0)
- t = "Type";
- else
+ static const char blt[] = "builtin_type";
+
+ t = register_type (m_gdbarch, regnum)->name ();
+ if (t == NULL)
{
- static const char blt[] = "builtin_type";
-
- t = register_type (m_gdbarch, regnum)->name ();
- 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);
+ 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 ();
}
- gdb_printf (file, " %-15s", t);
- }
+ /* Chop a leading builtin_type. */
+ if (startswith (t, blt))
+ t += strlen (blt);
- /* Leading space always present. */
- gdb_printf (file, " ");
+ out->field_string ("type", t);
+ }
- dump_reg (file, regnum);
+ dump_reg (out, regnum);
- gdb_printf (file, "\n");
+ out->text ("\n");
}
if (footnote_register_offset)
- gdb_printf (file, "*%d: Inconsistent register offsets.\n",
- footnote_register_offset);
+ out->message ("*%d: Inconsistent register offsets.\n",
+ footnote_register_offset);
if (footnote_register_type_name_null)
- gdb_printf (file,
- "*%d: Register type's name NULL.\n",
- footnote_register_type_name_null);
+ out->message ("*%d: Register type's name NULL.\n",
+ footnote_register_type_name_null);
}
#if GDB_SELF_TEST
diff --git a/gdb/regcache.h b/gdb/regcache.h
index 8d026e0..7123698 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -31,6 +31,7 @@ struct gdbarch;
class thread_info;
struct process_stratum_target;
struct inferior;
+class ui_out;
extern struct regcache *get_thread_regcache (process_stratum_target *target,
ptid_t ptid);
@@ -536,7 +537,7 @@ extern void registers_changed_thread (thread_info *thread);
class register_dump
{
public:
- void dump (ui_file *file);
+ void dump (ui_out *out, const char *name);
virtual ~register_dump () = default;
protected:
@@ -544,9 +545,14 @@ protected:
: 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;
+ /* Number of additional table headers. */
+ virtual int num_additional_headers () = 0;
+
+ /* Add the additional headers to OUT. */
+ virtual void additional_headers (ui_out *out) = 0;
+
+ /* Dump the register REGNUM contents. */
+ virtual void dump_reg (ui_out *out, int regnum) = 0;
gdbarch *m_gdbarch;
};
diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp
index f1e1b87..2c58ffa 100644
--- a/gdb/testsuite/gdb.base/maint.exp
+++ b/gdb/testsuite/gdb.base/maint.exp
@@ -70,11 +70,11 @@ set saw_registers 0
set saw_headers 0
set test "maint print registers"
gdb_test_multiple $test $test {
- -re "\[^\r\n\]+Name\[^\r\n\]+Nr\[^\r\n\]+Rel\[^\r\n\]+Offset\[^\r\n\]+Size\[^\r\n\]+Type\[^\r\n\]+\r\n" {
+ -re "Name\[^\r\n\]+Nr\[^\r\n\]+Rel\[^\r\n\]+Offset\[^\r\n\]+Size\[^\r\n\]+Type\[^\r\n\]+\r\n" {
set saw_headers 1
exp_continue
}
- -re "^\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\r\n" {
+ -re "\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\[0-9\]+\[^\r\n\]+\r\n" {
set saw_registers 1
exp_continue
}
diff --git a/gdb/testsuite/gdb.server/server-run.exp b/gdb/testsuite/gdb.server/server-run.exp
index af5a5f5..e81384f 100644
--- a/gdb/testsuite/gdb.server/server-run.exp
+++ b/gdb/testsuite/gdb.server/server-run.exp
@@ -74,7 +74,7 @@ if { [info exists pc_regname] } {
set seen_line false
gdb_test_multiple "maintenance print remote-registers" \
$expedited_pc_test_name -lbl {
- -re " ${pc_regname}\[\[:space:\]\]+${decimal}.*${decimal} yes" {
+ -re "${pc_regname}\[\[:space:\]\]+${decimal}.*${decimal}\[\[:space:\]\]+yes" {
set seen_line true
exp_continue
}