regcache-dump.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /* Copyright (C) 1986-2022 Free Software Foundation, Inc.
  2. This file is part of GDB.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #include "defs.h"
  14. #include "gdbcmd.h"
  15. #include "regcache.h"
  16. #include "gdbsupport/def-vector.h"
  17. #include "valprint.h"
  18. #include "remote.h"
  19. #include "reggroups.h"
  20. #include "target.h"
  21. #include "gdbarch.h"
  22. /* Dump registers from regcache, used for dumping raw registers and
  23. cooked registers. */
  24. class register_dump_regcache : public register_dump
  25. {
  26. public:
  27. register_dump_regcache (regcache *regcache, bool dump_pseudo)
  28. : register_dump (regcache->arch ()), m_regcache (regcache),
  29. m_dump_pseudo (dump_pseudo)
  30. {
  31. }
  32. protected:
  33. void dump_reg (ui_file *file, int regnum) override
  34. {
  35. if (regnum < 0)
  36. {
  37. if (m_dump_pseudo)
  38. gdb_printf (file, "Cooked value");
  39. else
  40. gdb_printf (file, "Raw value");
  41. }
  42. else
  43. {
  44. if (regnum < gdbarch_num_regs (m_gdbarch) || m_dump_pseudo)
  45. {
  46. auto size = register_size (m_gdbarch, regnum);
  47. if (size == 0)
  48. return;
  49. gdb::def_vector<gdb_byte> buf (size);
  50. auto status = m_regcache->cooked_read (regnum, buf.data ());
  51. if (status == REG_UNKNOWN)
  52. gdb_printf (file, "<invalid>");
  53. else if (status == REG_UNAVAILABLE)
  54. gdb_printf (file, "<unavailable>");
  55. else
  56. {
  57. print_hex_chars (file, buf.data (), size,
  58. gdbarch_byte_order (m_gdbarch), true);
  59. }
  60. }
  61. else
  62. {
  63. /* Just print "<cooked>" for pseudo register when
  64. regcache_dump_raw. */
  65. gdb_printf (file, "<cooked>");
  66. }
  67. }
  68. }
  69. private:
  70. regcache *m_regcache;
  71. /* Dump pseudo registers or not. */
  72. const bool m_dump_pseudo;
  73. };
  74. /* Dump from reg_buffer, used when there is no thread or
  75. registers. */
  76. class register_dump_reg_buffer : public register_dump, reg_buffer
  77. {
  78. public:
  79. register_dump_reg_buffer (gdbarch *gdbarch, bool dump_pseudo)
  80. : register_dump (gdbarch), reg_buffer (gdbarch, dump_pseudo)
  81. {
  82. }
  83. protected:
  84. void dump_reg (ui_file *file, int regnum) override
  85. {
  86. if (regnum < 0)
  87. {
  88. if (m_has_pseudo)
  89. gdb_printf (file, "Cooked value");
  90. else
  91. gdb_printf (file, "Raw value");
  92. }
  93. else
  94. {
  95. if (regnum < gdbarch_num_regs (m_gdbarch) || m_has_pseudo)
  96. {
  97. auto size = register_size (m_gdbarch, regnum);
  98. if (size == 0)
  99. return;
  100. auto status = get_register_status (regnum);
  101. gdb_assert (status != REG_VALID);
  102. if (status == REG_UNKNOWN)
  103. gdb_printf (file, "<invalid>");
  104. else
  105. gdb_printf (file, "<unavailable>");
  106. }
  107. else
  108. {
  109. /* Just print "<cooked>" for pseudo register when
  110. regcache_dump_raw. */
  111. gdb_printf (file, "<cooked>");
  112. }
  113. }
  114. }
  115. };
  116. /* For "maint print registers". */
  117. class register_dump_none : public register_dump
  118. {
  119. public:
  120. register_dump_none (gdbarch *arch)
  121. : register_dump (arch)
  122. {}
  123. protected:
  124. void dump_reg (ui_file *file, int regnum) override
  125. {}
  126. };
  127. /* For "maint print remote-registers". */
  128. class register_dump_remote : public register_dump
  129. {
  130. public:
  131. register_dump_remote (gdbarch *arch)
  132. : register_dump (arch)
  133. {}
  134. protected:
  135. void dump_reg (ui_file *file, int regnum) override
  136. {
  137. if (regnum < 0)
  138. {
  139. gdb_printf (file, "Rmt Nr g/G Offset");
  140. }
  141. else if (regnum < gdbarch_num_regs (m_gdbarch))
  142. {
  143. int pnum, poffset;
  144. if (remote_register_number_and_offset (m_gdbarch, regnum,
  145. &pnum, &poffset))
  146. gdb_printf (file, "%7d %11d", pnum, poffset);
  147. }
  148. }
  149. };
  150. /* For "maint print register-groups". */
  151. class register_dump_groups : public register_dump
  152. {
  153. public:
  154. register_dump_groups (gdbarch *arch)
  155. : register_dump (arch)
  156. {}
  157. protected:
  158. void dump_reg (ui_file *file, int regnum) override
  159. {
  160. if (regnum < 0)
  161. gdb_printf (file, "Groups");
  162. else
  163. {
  164. const char *sep = "";
  165. for (const struct reggroup *group : gdbarch_reggroups (m_gdbarch))
  166. {
  167. if (gdbarch_register_reggroup_p (m_gdbarch, regnum, group))
  168. {
  169. gdb_printf (file, "%s%s", sep, group->name ());
  170. sep = ",";
  171. }
  172. }
  173. }
  174. }
  175. };
  176. enum regcache_dump_what
  177. {
  178. regcache_dump_none, regcache_dump_raw,
  179. regcache_dump_cooked, regcache_dump_groups,
  180. regcache_dump_remote
  181. };
  182. static void
  183. regcache_print (const char *args, enum regcache_dump_what what_to_dump)
  184. {
  185. /* Where to send output. */
  186. stdio_file file;
  187. ui_file *out;
  188. if (args == NULL)
  189. out = gdb_stdout;
  190. else
  191. {
  192. if (!file.open (args, "w"))
  193. perror_with_name (_("maintenance print architecture"));
  194. out = &file;
  195. }
  196. std::unique_ptr<register_dump> dump;
  197. std::unique_ptr<regcache> regs;
  198. gdbarch *gdbarch;
  199. if (target_has_registers ())
  200. gdbarch = get_current_regcache ()->arch ();
  201. else
  202. gdbarch = target_gdbarch ();
  203. switch (what_to_dump)
  204. {
  205. case regcache_dump_none:
  206. dump.reset (new register_dump_none (gdbarch));
  207. break;
  208. case regcache_dump_remote:
  209. dump.reset (new register_dump_remote (gdbarch));
  210. break;
  211. case regcache_dump_groups:
  212. dump.reset (new register_dump_groups (gdbarch));
  213. break;
  214. case regcache_dump_raw:
  215. case regcache_dump_cooked:
  216. {
  217. auto dump_pseudo = (what_to_dump == regcache_dump_cooked);
  218. if (target_has_registers ())
  219. dump.reset (new register_dump_regcache (get_current_regcache (),
  220. dump_pseudo));
  221. else
  222. {
  223. /* For the benefit of "maint print registers" & co when
  224. debugging an executable, allow dumping a regcache even when
  225. there is no thread selected / no registers. */
  226. dump.reset (new register_dump_reg_buffer (target_gdbarch (),
  227. dump_pseudo));
  228. }
  229. }
  230. break;
  231. }
  232. dump->dump (out);
  233. }
  234. static void
  235. maintenance_print_registers (const char *args, int from_tty)
  236. {
  237. regcache_print (args, regcache_dump_none);
  238. }
  239. static void
  240. maintenance_print_raw_registers (const char *args, int from_tty)
  241. {
  242. regcache_print (args, regcache_dump_raw);
  243. }
  244. static void
  245. maintenance_print_cooked_registers (const char *args, int from_tty)
  246. {
  247. regcache_print (args, regcache_dump_cooked);
  248. }
  249. static void
  250. maintenance_print_register_groups (const char *args, int from_tty)
  251. {
  252. regcache_print (args, regcache_dump_groups);
  253. }
  254. static void
  255. maintenance_print_remote_registers (const char *args, int from_tty)
  256. {
  257. regcache_print (args, regcache_dump_remote);
  258. }
  259. void _initialize_regcache_dump ();
  260. void
  261. _initialize_regcache_dump ()
  262. {
  263. add_cmd ("registers", class_maintenance, maintenance_print_registers,
  264. _("Print the internal register configuration.\n"
  265. "Takes an optional file parameter."), &maintenanceprintlist);
  266. add_cmd ("raw-registers", class_maintenance,
  267. maintenance_print_raw_registers,
  268. _("Print the internal register configuration "
  269. "including raw values.\n"
  270. "Takes an optional file parameter."), &maintenanceprintlist);
  271. add_cmd ("cooked-registers", class_maintenance,
  272. maintenance_print_cooked_registers,
  273. _("Print the internal register configuration "
  274. "including cooked values.\n"
  275. "Takes an optional file parameter."), &maintenanceprintlist);
  276. add_cmd ("register-groups", class_maintenance,
  277. maintenance_print_register_groups,
  278. _("Print the internal register configuration "
  279. "including each register's group.\n"
  280. "Takes an optional file parameter."),
  281. &maintenanceprintlist);
  282. add_cmd ("remote-registers", class_maintenance,
  283. maintenance_print_remote_registers, _("\
  284. Print the internal register configuration including remote register number "
  285. "and g/G packets offset.\n\
  286. Takes an optional file parameter."),
  287. &maintenanceprintlist);
  288. }