xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/regcache-dump.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
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