mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-12-19 01:19:41 +08:00
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>
This commit is contained in:
@@ -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)
|
||||
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 (m_has_pseudo)
|
||||
gdb_printf (file, "Cooked value");
|
||||
auto size = register_size (m_gdbarch, regnum);
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
auto status = get_register_status (regnum);
|
||||
|
||||
gdb_assert (status != REG_VALID);
|
||||
|
||||
if (status == REG_UNKNOWN)
|
||||
out->field_string ("value", "<invalid>");
|
||||
else
|
||||
gdb_printf (file, "Raw value");
|
||||
out->field_string ("value", "<unavailable>");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
|
||||
{
|
||||
auto size = register_size (m_gdbarch, regnum);
|
||||
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
auto status = get_register_status (regnum);
|
||||
|
||||
gdb_assert (status != REG_VALID);
|
||||
|
||||
if (status == REG_UNKNOWN)
|
||||
gdb_printf (file, "<invalid>");
|
||||
else
|
||||
gdb_printf (file, "<unavailable>");
|
||||
}
|
||||
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>");
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
if (regnum < 0)
|
||||
{
|
||||
gdb_printf (file, "Rmt Nr g/G Offset Expedited");
|
||||
}
|
||||
else if (regnum < gdbarch_num_regs (m_gdbarch))
|
||||
{
|
||||
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);
|
||||
}
|
||||
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
|
||||
{
|
||||
int pnum, poffset;
|
||||
|
||||
if (regnum < gdbarch_num_regs (m_gdbarch)
|
||||
&& remote_register_number_and_offset (m_gdbarch, regnum,
|
||||
&pnum, &poffset))
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
134
gdb/regcache.c
134
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++)
|
||||
{
|
||||
/* Name. */
|
||||
if (regnum < 0)
|
||||
gdb_printf (file, " %-10s", "Name");
|
||||
else
|
||||
{
|
||||
const char *p = gdbarch_register_name (m_gdbarch, 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 ();
|
||||
|
||||
if (p[0] == '\0')
|
||||
p = "''";
|
||||
gdb_printf (file, " %-10s", p);
|
||||
}
|
||||
for (regnum = 0; regnum < descr->nr_cooked_registers; regnum++)
|
||||
{
|
||||
ui_out_emit_tuple tuple_emitter (out, nullptr);
|
||||
|
||||
/* 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";
|
||||
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);
|
||||
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 ();
|
||||
}
|
||||
gdb_printf (file, " %-15s", t);
|
||||
/* Chop a leading builtin_type. */
|
||||
if (startswith (t, blt))
|
||||
t += strlen (blt);
|
||||
|
||||
out->field_string ("type", t);
|
||||
}
|
||||
|
||||
/* Leading space always present. */
|
||||
gdb_printf (file, " ");
|
||||
dump_reg (out, regnum);
|
||||
|
||||
dump_reg (file, 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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user