1*6881a400Schristos /* Copyright (C) 1986-2023 Free Software Foundation, Inc. 27f2ac410Schristos 37f2ac410Schristos This file is part of GDB. 47f2ac410Schristos 57f2ac410Schristos This program is free software; you can redistribute it and/or modify 67f2ac410Schristos it under the terms of the GNU General Public License as published by 77f2ac410Schristos the Free Software Foundation; either version 3 of the License, or 87f2ac410Schristos (at your option) any later version. 97f2ac410Schristos 107f2ac410Schristos This program is distributed in the hope that it will be useful, 117f2ac410Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 127f2ac410Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 137f2ac410Schristos GNU General Public License for more details. 147f2ac410Schristos 157f2ac410Schristos You should have received a copy of the GNU General Public License 167f2ac410Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 177f2ac410Schristos 187f2ac410Schristos #include "defs.h" 197f2ac410Schristos #include "gdbcmd.h" 207f2ac410Schristos #include "regcache.h" 217d62b00eSchristos #include "gdbsupport/def-vector.h" 227f2ac410Schristos #include "valprint.h" 237f2ac410Schristos #include "remote.h" 247f2ac410Schristos #include "reggroups.h" 257f2ac410Schristos #include "target.h" 267d62b00eSchristos #include "gdbarch.h" 277f2ac410Schristos 287f2ac410Schristos /* Dump registers from regcache, used for dumping raw registers and 297f2ac410Schristos cooked registers. */ 307f2ac410Schristos 317f2ac410Schristos class register_dump_regcache : public register_dump 327f2ac410Schristos { 337f2ac410Schristos public: 347f2ac410Schristos register_dump_regcache (regcache *regcache, bool dump_pseudo) 357f2ac410Schristos : register_dump (regcache->arch ()), m_regcache (regcache), 367f2ac410Schristos m_dump_pseudo (dump_pseudo) 377f2ac410Schristos { 387f2ac410Schristos } 397f2ac410Schristos 407f2ac410Schristos protected: 417f2ac410Schristos void dump_reg (ui_file *file, int regnum) override 427f2ac410Schristos { 437f2ac410Schristos if (regnum < 0) 447f2ac410Schristos { 457f2ac410Schristos if (m_dump_pseudo) 46*6881a400Schristos gdb_printf (file, "Cooked value"); 477f2ac410Schristos else 48*6881a400Schristos gdb_printf (file, "Raw value"); 497f2ac410Schristos } 507f2ac410Schristos else 517f2ac410Schristos { 527f2ac410Schristos if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo) 537f2ac410Schristos { 547f2ac410Schristos auto size = register_size (m_gdbarch, regnum); 557f2ac410Schristos 567f2ac410Schristos if (size == 0) 577f2ac410Schristos return; 587f2ac410Schristos 597f2ac410Schristos gdb::def_vector<gdb_byte> buf (size); 607f2ac410Schristos auto status = m_regcache->cooked_read (regnum, buf.data ()); 617f2ac410Schristos 627f2ac410Schristos if (status == REG_UNKNOWN) 63*6881a400Schristos gdb_printf (file, "<invalid>"); 647f2ac410Schristos else if (status == REG_UNAVAILABLE) 65*6881a400Schristos gdb_printf (file, "<unavailable>"); 667f2ac410Schristos else 677f2ac410Schristos { 687f2ac410Schristos print_hex_chars (file, buf.data (), size, 697f2ac410Schristos gdbarch_byte_order (m_gdbarch), true); 707f2ac410Schristos } 717f2ac410Schristos } 727f2ac410Schristos else 737f2ac410Schristos { 747f2ac410Schristos /* Just print "<cooked>" for pseudo register when 757f2ac410Schristos regcache_dump_raw. */ 76*6881a400Schristos gdb_printf (file, "<cooked>"); 777f2ac410Schristos } 787f2ac410Schristos } 797f2ac410Schristos } 807f2ac410Schristos 817f2ac410Schristos private: 827f2ac410Schristos regcache *m_regcache; 837f2ac410Schristos 847f2ac410Schristos /* Dump pseudo registers or not. */ 857f2ac410Schristos const bool m_dump_pseudo; 867f2ac410Schristos }; 877f2ac410Schristos 887f2ac410Schristos /* Dump from reg_buffer, used when there is no thread or 897f2ac410Schristos registers. */ 907f2ac410Schristos 917f2ac410Schristos class register_dump_reg_buffer : public register_dump, reg_buffer 927f2ac410Schristos { 937f2ac410Schristos public: 947f2ac410Schristos register_dump_reg_buffer (gdbarch *gdbarch, bool dump_pseudo) 957f2ac410Schristos : register_dump (gdbarch), reg_buffer (gdbarch, dump_pseudo) 967f2ac410Schristos { 977f2ac410Schristos } 987f2ac410Schristos 997f2ac410Schristos protected: 1007f2ac410Schristos void dump_reg (ui_file *file, int regnum) override 1017f2ac410Schristos { 1027f2ac410Schristos if (regnum < 0) 1037f2ac410Schristos { 1047f2ac410Schristos if (m_has_pseudo) 105*6881a400Schristos gdb_printf (file, "Cooked value"); 1067f2ac410Schristos else 107*6881a400Schristos gdb_printf (file, "Raw value"); 1087f2ac410Schristos } 1097f2ac410Schristos else 1107f2ac410Schristos { 1117f2ac410Schristos if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo) 1127f2ac410Schristos { 1137f2ac410Schristos auto size = register_size (m_gdbarch, regnum); 1147f2ac410Schristos 1157f2ac410Schristos if (size == 0) 1167f2ac410Schristos return; 1177f2ac410Schristos 1187f2ac410Schristos auto status = get_register_status (regnum); 1197f2ac410Schristos 1207f2ac410Schristos gdb_assert (status != REG_VALID); 1217f2ac410Schristos 1227f2ac410Schristos if (status == REG_UNKNOWN) 123*6881a400Schristos gdb_printf (file, "<invalid>"); 1247f2ac410Schristos else 125*6881a400Schristos gdb_printf (file, "<unavailable>"); 1267f2ac410Schristos } 1277f2ac410Schristos else 1287f2ac410Schristos { 1297f2ac410Schristos /* Just print "<cooked>" for pseudo register when 1307f2ac410Schristos regcache_dump_raw. */ 131*6881a400Schristos gdb_printf (file, "<cooked>"); 1327f2ac410Schristos } 1337f2ac410Schristos } 1347f2ac410Schristos } 1357f2ac410Schristos }; 1367f2ac410Schristos 1377f2ac410Schristos /* For "maint print registers". */ 1387f2ac410Schristos 1397f2ac410Schristos class register_dump_none : public register_dump 1407f2ac410Schristos { 1417f2ac410Schristos public: 1427f2ac410Schristos register_dump_none (gdbarch *arch) 1437f2ac410Schristos : register_dump (arch) 1447f2ac410Schristos {} 1457f2ac410Schristos 1467f2ac410Schristos protected: 1477f2ac410Schristos void dump_reg (ui_file *file, int regnum) override 1487f2ac410Schristos {} 1497f2ac410Schristos }; 1507f2ac410Schristos 1517f2ac410Schristos /* For "maint print remote-registers". */ 1527f2ac410Schristos 1537f2ac410Schristos class register_dump_remote : public register_dump 1547f2ac410Schristos { 1557f2ac410Schristos public: 1567f2ac410Schristos register_dump_remote (gdbarch *arch) 1577f2ac410Schristos : register_dump (arch) 1587f2ac410Schristos {} 1597f2ac410Schristos 1607f2ac410Schristos protected: 1617f2ac410Schristos void dump_reg (ui_file *file, int regnum) override 1627f2ac410Schristos { 1637f2ac410Schristos if (regnum < 0) 1647f2ac410Schristos { 165*6881a400Schristos gdb_printf (file, "Rmt Nr g/G Offset"); 1667f2ac410Schristos } 1677f2ac410Schristos else if (regnum < gdbarch_num_regs (m_gdbarch)) 1687f2ac410Schristos { 1697f2ac410Schristos int pnum, poffset; 1707f2ac410Schristos 1717f2ac410Schristos if (remote_register_number_and_offset (m_gdbarch, regnum, 1727f2ac410Schristos &pnum, &poffset)) 173*6881a400Schristos gdb_printf (file, "%7d %11d", pnum, poffset); 1747f2ac410Schristos } 1757f2ac410Schristos } 1767f2ac410Schristos }; 1777f2ac410Schristos 1787f2ac410Schristos /* For "maint print register-groups". */ 1797f2ac410Schristos 1807f2ac410Schristos class register_dump_groups : public register_dump 1817f2ac410Schristos { 1827f2ac410Schristos public: 1837f2ac410Schristos register_dump_groups (gdbarch *arch) 1847f2ac410Schristos : register_dump (arch) 1857f2ac410Schristos {} 1867f2ac410Schristos 1877f2ac410Schristos protected: 1887f2ac410Schristos void dump_reg (ui_file *file, int regnum) override 1897f2ac410Schristos { 1907f2ac410Schristos if (regnum < 0) 191*6881a400Schristos gdb_printf (file, "Groups"); 1927f2ac410Schristos else 1937f2ac410Schristos { 1947f2ac410Schristos const char *sep = ""; 195*6881a400Schristos for (const struct reggroup *group : gdbarch_reggroups (m_gdbarch)) 1967f2ac410Schristos { 1977f2ac410Schristos if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group)) 1987f2ac410Schristos { 199*6881a400Schristos gdb_printf (file, "%s%s", sep, group->name ()); 2007f2ac410Schristos sep = ","; 2017f2ac410Schristos } 2027f2ac410Schristos } 2037f2ac410Schristos } 2047f2ac410Schristos } 2057f2ac410Schristos }; 2067f2ac410Schristos 2077f2ac410Schristos enum regcache_dump_what 2087f2ac410Schristos { 2097f2ac410Schristos regcache_dump_none, regcache_dump_raw, 2107f2ac410Schristos regcache_dump_cooked, regcache_dump_groups, 2117f2ac410Schristos regcache_dump_remote 2127f2ac410Schristos }; 2137f2ac410Schristos 2147f2ac410Schristos static void 2157f2ac410Schristos regcache_print (const char *args, enum regcache_dump_what what_to_dump) 2167f2ac410Schristos { 2177f2ac410Schristos /* Where to send output. */ 2187f2ac410Schristos stdio_file file; 2197f2ac410Schristos ui_file *out; 2207f2ac410Schristos 2217f2ac410Schristos if (args == NULL) 2227f2ac410Schristos out = gdb_stdout; 2237f2ac410Schristos else 2247f2ac410Schristos { 2257f2ac410Schristos if (!file.open (args, "w")) 2267f2ac410Schristos perror_with_name (_("maintenance print architecture")); 2277f2ac410Schristos out = &file; 2287f2ac410Schristos } 2297f2ac410Schristos 2307f2ac410Schristos std::unique_ptr<register_dump> dump; 2317f2ac410Schristos std::unique_ptr<regcache> regs; 2327f2ac410Schristos gdbarch *gdbarch; 2337f2ac410Schristos 234*6881a400Schristos if (target_has_registers ()) 2357f2ac410Schristos gdbarch = get_current_regcache ()->arch (); 2367f2ac410Schristos else 2377f2ac410Schristos gdbarch = target_gdbarch (); 2387f2ac410Schristos 2397f2ac410Schristos switch (what_to_dump) 2407f2ac410Schristos { 2417f2ac410Schristos case regcache_dump_none: 2427f2ac410Schristos dump.reset (new register_dump_none (gdbarch)); 2437f2ac410Schristos break; 2447f2ac410Schristos case regcache_dump_remote: 2457f2ac410Schristos dump.reset (new register_dump_remote (gdbarch)); 2467f2ac410Schristos break; 2477f2ac410Schristos case regcache_dump_groups: 2487f2ac410Schristos dump.reset (new register_dump_groups (gdbarch)); 2497f2ac410Schristos break; 2507f2ac410Schristos case regcache_dump_raw: 2517f2ac410Schristos case regcache_dump_cooked: 2527f2ac410Schristos { 2537f2ac410Schristos auto dump_pseudo = (what_to_dump == regcache_dump_cooked); 2547f2ac410Schristos 255*6881a400Schristos if (target_has_registers ()) 2567f2ac410Schristos dump.reset (new register_dump_regcache (get_current_regcache (), 2577f2ac410Schristos dump_pseudo)); 2587f2ac410Schristos else 2597f2ac410Schristos { 2607f2ac410Schristos /* For the benefit of "maint print registers" & co when 2617f2ac410Schristos debugging an executable, allow dumping a regcache even when 2627f2ac410Schristos there is no thread selected / no registers. */ 2637f2ac410Schristos dump.reset (new register_dump_reg_buffer (target_gdbarch (), 2647f2ac410Schristos dump_pseudo)); 2657f2ac410Schristos } 2667f2ac410Schristos } 2677f2ac410Schristos break; 2687f2ac410Schristos } 2697f2ac410Schristos 2707f2ac410Schristos dump->dump (out); 2717f2ac410Schristos } 2727f2ac410Schristos 2737f2ac410Schristos static void 2747f2ac410Schristos maintenance_print_registers (const char *args, int from_tty) 2757f2ac410Schristos { 2767f2ac410Schristos regcache_print (args, regcache_dump_none); 2777f2ac410Schristos } 2787f2ac410Schristos 2797f2ac410Schristos static void 2807f2ac410Schristos maintenance_print_raw_registers (const char *args, int from_tty) 2817f2ac410Schristos { 2827f2ac410Schristos regcache_print (args, regcache_dump_raw); 2837f2ac410Schristos } 2847f2ac410Schristos 2857f2ac410Schristos static void 2867f2ac410Schristos maintenance_print_cooked_registers (const char *args, int from_tty) 2877f2ac410Schristos { 2887f2ac410Schristos regcache_print (args, regcache_dump_cooked); 2897f2ac410Schristos } 2907f2ac410Schristos 2917f2ac410Schristos static void 2927f2ac410Schristos maintenance_print_register_groups (const char *args, int from_tty) 2937f2ac410Schristos { 2947f2ac410Schristos regcache_print (args, regcache_dump_groups); 2957f2ac410Schristos } 2967f2ac410Schristos 2977f2ac410Schristos static void 2987f2ac410Schristos maintenance_print_remote_registers (const char *args, int from_tty) 2997f2ac410Schristos { 3007f2ac410Schristos regcache_print (args, regcache_dump_remote); 3017f2ac410Schristos } 3027f2ac410Schristos 3037d62b00eSchristos void _initialize_regcache_dump (); 3047f2ac410Schristos void 3057d62b00eSchristos _initialize_regcache_dump () 3067f2ac410Schristos { 3077f2ac410Schristos add_cmd ("registers", class_maintenance, maintenance_print_registers, 3087f2ac410Schristos _("Print the internal register configuration.\n" 3097f2ac410Schristos "Takes an optional file parameter."), &maintenanceprintlist); 3107f2ac410Schristos add_cmd ("raw-registers", class_maintenance, 3117f2ac410Schristos maintenance_print_raw_registers, 3127f2ac410Schristos _("Print the internal register configuration " 3137f2ac410Schristos "including raw values.\n" 3147f2ac410Schristos "Takes an optional file parameter."), &maintenanceprintlist); 3157f2ac410Schristos add_cmd ("cooked-registers", class_maintenance, 3167f2ac410Schristos maintenance_print_cooked_registers, 3177f2ac410Schristos _("Print the internal register configuration " 3187f2ac410Schristos "including cooked values.\n" 3197f2ac410Schristos "Takes an optional file parameter."), &maintenanceprintlist); 3207f2ac410Schristos add_cmd ("register-groups", class_maintenance, 3217f2ac410Schristos maintenance_print_register_groups, 3227f2ac410Schristos _("Print the internal register configuration " 3237f2ac410Schristos "including each register's group.\n" 3247f2ac410Schristos "Takes an optional file parameter."), 3257f2ac410Schristos &maintenanceprintlist); 3267f2ac410Schristos add_cmd ("remote-registers", class_maintenance, 3277f2ac410Schristos maintenance_print_remote_registers, _("\ 3287d62b00eSchristos Print the internal register configuration including remote register number " 3297d62b00eSchristos "and g/G packets offset.\n\ 3307f2ac410Schristos Takes an optional file parameter."), 3317f2ac410Schristos &maintenanceprintlist); 3327f2ac410Schristos } 333