diff options
Diffstat (limited to 'gdb/regcache-dump.c')
-rw-r--r-- | gdb/regcache-dump.c | 256 |
1 files changed, 151 insertions, 105 deletions
diff --git a/gdb/regcache-dump.c b/gdb/regcache-dump.c index bc665dc..c6ef552 100644 --- a/gdb/regcache-dump.c +++ b/gdb/regcache-dump.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1986-2024 Free Software Foundation, Inc. +/* Copyright (C) 1986-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -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 (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,19 +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"); + 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)) - gdb_printf (file, "%7d %11d", pnum, poffset); + out->field_skip ("remnum"); + out->field_skip ("goffset"); + out->field_skip ("expedited"); } } }; @@ -185,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); } }; @@ -211,20 +245,24 @@ enum regcache_dump_what regcache_dump_remote }; +/* Helper for the various maint commands that print registers. ARGS + is the arguments passed to the command. WHAT_TO_DUMP indicates + exactly which registers to display. COMMAND is the command name, + used in error messages. */ + static void -regcache_print (const char *args, enum regcache_dump_what what_to_dump) +regcache_print (const char *args, enum regcache_dump_what what_to_dump, + const char *command) { /* 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; + perror_with_name (command); + redirect.emplace (current_uiout, &file); } std::unique_ptr<register_dump> dump; @@ -236,73 +274,79 @@ 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.reset (new register_dump_none (gdbarch)); + dump = std::make_unique<register_dump_none> (gdbarch); + name = "Registers"; break; case regcache_dump_remote: - dump.reset (new register_dump_remote (gdbarch)); + dump = std::make_unique<register_dump_remote> (gdbarch); + name = "RegisterRemote"; break; case regcache_dump_groups: - dump.reset (new register_dump_groups (gdbarch)); + 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 ()) - dump.reset (new register_dump_regcache (get_thread_regcache - (inferior_thread ()), - dump_pseudo)); + dump = (std::make_unique<register_dump_regcache> + (get_thread_regcache (inferior_thread ()), dump_pseudo)); 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. */ - dump.reset (new register_dump_reg_buffer (gdbarch, dump_pseudo)); + dump = std::make_unique<register_dump_reg_buffer> (gdbarch, + dump_pseudo); } } break; } - dump->dump (out); + dump->dump (current_uiout, name); } static void maintenance_print_registers (const char *args, int from_tty) { - regcache_print (args, regcache_dump_none); + regcache_print (args, regcache_dump_none, "maintenance print registers"); } static void maintenance_print_raw_registers (const char *args, int from_tty) { - regcache_print (args, regcache_dump_raw); + regcache_print (args, regcache_dump_raw, "maintenance print raw-registers"); } static void maintenance_print_cooked_registers (const char *args, int from_tty) { - regcache_print (args, regcache_dump_cooked); + regcache_print (args, regcache_dump_cooked, + "maintenance print cooked-registers"); } static void maintenance_print_register_groups (const char *args, int from_tty) { - regcache_print (args, regcache_dump_groups); + regcache_print (args, regcache_dump_groups, + "maintenance print register-groups"); } static void maintenance_print_remote_registers (const char *args, int from_tty) { - regcache_print (args, regcache_dump_remote); + regcache_print (args, regcache_dump_remote, + "maintenance print remote-registers"); } -void _initialize_regcache_dump (); -void -_initialize_regcache_dump () +INIT_GDB_FILE (regcache_dump) { add_cmd ("registers", class_maintenance, maintenance_print_registers, _("Print the internal register configuration.\n" @@ -325,8 +369,10 @@ _initialize_regcache_dump () &maintenanceprintlist); add_cmd ("remote-registers", class_maintenance, maintenance_print_remote_registers, _("\ -Print the internal register configuration including remote register number " -"and g/G packets offset.\n\ -Takes an optional file parameter."), +Print the internal register configuration.\n\ +Usage: maintenance print remote-registers [FILE]\n\ +The remote register number and g/G packets offset are included,\n\ +as well as which registers were sent in the last stop reply packet\n\ +(i.e., expedited)."), &maintenanceprintlist); } |