gcore-elf.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /* Copyright (C) 2021-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 "gcore-elf.h"
  15. #include "elf-bfd.h"
  16. #include "target.h"
  17. #include "regcache.h"
  18. #include "gdbarch.h"
  19. #include "gdbthread.h"
  20. #include "inferior.h"
  21. #include "regset.h"
  22. #include "gdbsupport/tdesc.h"
  23. /* Structure for passing information from GCORE_COLLECT_THREAD_REGISTERS
  24. via an iterator to GCORE_COLLECT_REGSET_SECTION_CB. */
  25. struct gcore_elf_collect_regset_section_cb_data
  26. {
  27. gcore_elf_collect_regset_section_cb_data
  28. (struct gdbarch *gdbarch, const struct regcache *regcache,
  29. bfd *obfd, ptid_t ptid, gdb_signal stop_signal,
  30. gdb::unique_xmalloc_ptr<char> *note_data, int *note_size)
  31. : gdbarch (gdbarch), regcache (regcache), obfd (obfd),
  32. note_data (note_data), note_size (note_size),
  33. stop_signal (stop_signal)
  34. {
  35. /* The LWP is often not available for bare metal target, in which case
  36. use the tid instead. */
  37. if (ptid.lwp_p ())
  38. lwp = ptid.lwp ();
  39. else
  40. lwp = ptid.tid ();
  41. }
  42. struct gdbarch *gdbarch;
  43. const struct regcache *regcache;
  44. bfd *obfd;
  45. gdb::unique_xmalloc_ptr<char> *note_data;
  46. int *note_size;
  47. unsigned long lwp;
  48. enum gdb_signal stop_signal;
  49. bool abort_iteration = false;
  50. };
  51. /* Callback for ITERATE_OVER_REGSET_SECTIONS that records a single
  52. regset in the core file note section. */
  53. static void
  54. gcore_elf_collect_regset_section_cb (const char *sect_name,
  55. int supply_size, int collect_size,
  56. const struct regset *regset,
  57. const char *human_name, void *cb_data)
  58. {
  59. struct gcore_elf_collect_regset_section_cb_data *data
  60. = (struct gcore_elf_collect_regset_section_cb_data *) cb_data;
  61. bool variable_size_section = (regset != nullptr
  62. && regset->flags & REGSET_VARIABLE_SIZE);
  63. gdb_assert (variable_size_section || supply_size == collect_size);
  64. if (data->abort_iteration)
  65. return;
  66. gdb_assert (regset != nullptr && regset->collect_regset != nullptr);
  67. /* This is intentionally zero-initialized by using std::vector, so
  68. that any padding bytes in the core file will show as 0. */
  69. std::vector<gdb_byte> buf (collect_size);
  70. regset->collect_regset (regset, data->regcache, -1, buf.data (),
  71. collect_size);
  72. /* PRSTATUS still needs to be treated specially. */
  73. if (strcmp (sect_name, ".reg") == 0)
  74. data->note_data->reset (elfcore_write_prstatus
  75. (data->obfd, data->note_data->release (),
  76. data->note_size, data->lwp,
  77. gdb_signal_to_host (data->stop_signal),
  78. buf.data ()));
  79. else
  80. data->note_data->reset (elfcore_write_register_note
  81. (data->obfd, data->note_data->release (),
  82. data->note_size, sect_name, buf.data (),
  83. collect_size));
  84. if (*data->note_data == nullptr)
  85. data->abort_iteration = true;
  86. }
  87. /* Records the register state of thread PTID out of REGCACHE into the note
  88. buffer represented by *NOTE_DATA and NOTE_SIZE. OBFD is the bfd into
  89. which the core file is being created, and STOP_SIGNAL is the signal that
  90. cause thread PTID to stop. */
  91. static void
  92. gcore_elf_collect_thread_registers
  93. (const struct regcache *regcache, ptid_t ptid, bfd *obfd,
  94. gdb::unique_xmalloc_ptr<char> *note_data, int *note_size,
  95. enum gdb_signal stop_signal)
  96. {
  97. struct gdbarch *gdbarch = regcache->arch ();
  98. gcore_elf_collect_regset_section_cb_data data (gdbarch, regcache, obfd,
  99. ptid, stop_signal,
  100. note_data, note_size);
  101. gdbarch_iterate_over_regset_sections
  102. (gdbarch, gcore_elf_collect_regset_section_cb, &data, regcache);
  103. }
  104. /* See gcore-elf.h. */
  105. void
  106. gcore_elf_build_thread_register_notes
  107. (struct gdbarch *gdbarch, struct thread_info *info, gdb_signal stop_signal,
  108. bfd *obfd, gdb::unique_xmalloc_ptr<char> *note_data, int *note_size)
  109. {
  110. struct regcache *regcache
  111. = get_thread_arch_regcache (info->inf->process_target (),
  112. info->ptid, gdbarch);
  113. target_fetch_registers (regcache, -1);
  114. gcore_elf_collect_thread_registers (regcache, info->ptid, obfd,
  115. note_data, note_size, stop_signal);
  116. }
  117. /* See gcore-elf.h. */
  118. void
  119. gcore_elf_make_tdesc_note (bfd *obfd,
  120. gdb::unique_xmalloc_ptr<char> *note_data,
  121. int *note_size)
  122. {
  123. /* Append the target description to the core file. */
  124. const struct target_desc *tdesc = gdbarch_target_desc (target_gdbarch ());
  125. const char *tdesc_xml
  126. = tdesc == nullptr ? nullptr : tdesc_get_features_xml (tdesc);
  127. if (tdesc_xml != nullptr && *tdesc_xml != '\0')
  128. {
  129. /* Skip the leading '@'. */
  130. if (*tdesc_xml == '@')
  131. ++tdesc_xml;
  132. /* Include the null terminator in the length. */
  133. size_t tdesc_len = strlen (tdesc_xml) + 1;
  134. /* Now add the target description into the core file. */
  135. note_data->reset (elfcore_write_register_note (obfd,
  136. note_data->release (),
  137. note_size,
  138. ".gdb-tdesc", tdesc_xml,
  139. tdesc_len));
  140. }
  141. }