diff options
Diffstat (limited to 'gdb/regcache.c')
-rw-r--r-- | gdb/regcache.c | 196 |
1 files changed, 84 insertions, 112 deletions
diff --git a/gdb/regcache.c b/gdb/regcache.c index f04354d..9892c54 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -1,6 +1,6 @@ /* Cache and manage the values of registers for GDB, the GNU debugger. - Copyright (C) 1986-2024 Free Software Foundation, Inc. + Copyright (C) 1986-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -28,6 +28,7 @@ #include "reggroups.h" #include "observable.h" #include "regset.h" +#include "gdbsupport/unordered_map.h" #include <unordered_map> #include "cli/cli-cmds.h" @@ -179,10 +180,9 @@ register_size (struct gdbarch *gdbarch, int regnum) /* See gdbsupport/common-regcache.h. */ int -regcache_register_size (const reg_buffer_common *regcache, int n) +reg_buffer::register_size (int regnum) const { - return register_size - (gdb::checked_static_cast<const struct regcache *> (regcache)->arch (), n); + return ::register_size (this->arch (), regnum); } reg_buffer::reg_buffer (gdbarch *gdbarch, bool has_pseudo) @@ -350,12 +350,12 @@ using ptid_regcache_map /* Type holding regcaches for a given pid. */ -using pid_ptid_regcache_map = std::unordered_map<int, ptid_regcache_map>; +using pid_ptid_regcache_map = gdb::unordered_map<int, ptid_regcache_map>; /* Type holding regcaches for a given target. */ using target_pid_ptid_regcache_map - = std::unordered_map<process_stratum_target *, pid_ptid_regcache_map>; + = gdb::unordered_map<process_stratum_target *, pid_ptid_regcache_map>; /* Global structure containing the existing regcaches. */ @@ -939,7 +939,7 @@ register_status readable_regcache::read_part (int regnum, int offset, gdb::array_view<gdb_byte> dst, bool is_raw) { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + dst.size () <= reg_size); @@ -983,7 +983,7 @@ void reg_buffer::raw_collect_part (int regnum, int offset, gdb::array_view<gdb_byte> dst) const { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + dst.size () <= reg_size); @@ -1013,7 +1013,7 @@ register_status regcache::write_part (int regnum, int offset, gdb::array_view<const gdb_byte> src, bool is_raw) { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + src.size () <= reg_size); @@ -1065,7 +1065,7 @@ void reg_buffer::raw_supply_part (int regnum, int offset, gdb::array_view<const gdb_byte> src) { - int reg_size = register_size (arch (), regnum); + int reg_size = register_size (regnum); gdb_assert (offset >= 0); gdb_assert (offset + src.size () <= reg_size); @@ -1190,6 +1190,16 @@ reg_buffer::raw_supply_zeroed (int regnum) /* See gdbsupport/common-regcache.h. */ void +reg_buffer::raw_supply_part_zeroed (int regnum, int offset, size_t size) +{ + gdb::array_view<gdb_byte> dst = register_buffer (regnum).slice (offset, size); + memset (dst.data (), 0, dst.size ()); + m_register_status[regnum] = REG_VALID; +} + +/* See gdbsupport/common-regcache.h. */ + +void reg_buffer::raw_collect (int regnum, gdb::array_view<gdb_byte> dst) const { gdb::array_view<const gdb_byte> src = register_buffer (regnum); @@ -1226,8 +1236,7 @@ regcache::transfer_regset_register (struct regcache *out_regcache, int regnum, const gdb_byte *in_buf, gdb_byte *out_buf, int slot_size, int offs) const { - struct gdbarch *gdbarch = arch (); - int reg_size = std::min (register_size (gdbarch, regnum), slot_size); + int reg_size = std::min (register_size (regnum), slot_size); /* Use part versions and reg_size to prevent possible buffer overflows when accessing the regcache. */ @@ -1244,7 +1253,7 @@ regcache::transfer_regset_register (struct regcache *out_regcache, int regnum, else if (in_buf != nullptr) { /* Zero-extend the register value if the slot is smaller than the register. */ - if (slot_size < register_size (gdbarch, regnum)) + if (slot_size < register_size (regnum)) out_regcache->raw_supply_zeroed (regnum); out_regcache->raw_supply_part (regnum, 0, gdb::make_array_view (in_buf + offs, @@ -1509,7 +1518,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; @@ -1521,107 +1530,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 @@ -1918,32 +1911,13 @@ public: {} }; -/* Return true if regcache::cooked_{read,write}_test should be skipped for - GDBARCH. */ - -static bool -selftest_skiparch (struct gdbarch *gdbarch) -{ - const char *name = gdbarch_bfd_arch_info (gdbarch)->printable_name; - - /* Avoid warning: - Running selftest regcache::cooked_{read,write}_test::m68hc11. - warning: No frame soft register found in the symbol table. - Stack backtrace will not work. - We could instead capture the output and then filter out the warning, but - that seems more trouble than it's worth. */ - return (strcmp (name, "m68hc11") == 0 - || strcmp (name, "m68hc12") == 0 - || strcmp (name, "m68hc12:HCS12") == 0); -} - /* Test regcache::cooked_read gets registers from raw registers and memory instead of target to_{fetch,store}_registers. */ static void cooked_read_test (struct gdbarch *gdbarch) { - if (selftest_skiparch (gdbarch)) + if (selftest_skip_warning_arch (gdbarch)) return; scoped_mock_context<target_ops_no_register> mockctx (gdbarch); @@ -2081,7 +2055,7 @@ cooked_read_test (struct gdbarch *gdbarch) static void cooked_write_test (struct gdbarch *gdbarch) { - if (selftest_skiparch (gdbarch)) + if (selftest_skip_warning_arch (gdbarch)) return; /* Create a mock environment. A process_stratum target pushed. */ @@ -2236,12 +2210,10 @@ regcache_thread_ptid_changed () gdb_assert (regcaches.empty ()); } -} // namespace selftests +} /* namespace selftests */ #endif /* GDB_SELF_TEST */ -void _initialize_regcache (); -void -_initialize_regcache () +INIT_GDB_FILE (regcache) { struct cmd_list_element *c; |