1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
3 This file is part of GDB.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include "gcore-elf.h"
24 #include "gdbthread.h"
27 #include "gdbsupport/tdesc.h"
29 /* Structure for passing information from GCORE_COLLECT_THREAD_REGISTERS
30 via an iterator to GCORE_COLLECT_REGSET_SECTION_CB. */
32 struct gcore_elf_collect_regset_section_cb_data
34 gcore_elf_collect_regset_section_cb_data
35 (struct gdbarch
*gdbarch
, const struct regcache
*regcache
,
36 bfd
*obfd
, ptid_t ptid
, gdb_signal stop_signal
,
37 gdb::unique_xmalloc_ptr
<char> *note_data
, int *note_size
)
38 : gdbarch (gdbarch
), regcache (regcache
), obfd (obfd
),
39 note_data (note_data
), note_size (note_size
),
40 stop_signal (stop_signal
)
42 /* The LWP is often not available for bare metal target, in which case
43 use the tid instead. */
50 struct gdbarch
*gdbarch
;
51 const struct regcache
*regcache
;
53 gdb::unique_xmalloc_ptr
<char> *note_data
;
56 enum gdb_signal stop_signal
;
57 bool abort_iteration
= false;
60 /* Callback for ITERATE_OVER_REGSET_SECTIONS that records a single
61 regset in the core file note section. */
64 gcore_elf_collect_regset_section_cb (const char *sect_name
,
65 int supply_size
, int collect_size
,
66 const struct regset
*regset
,
67 const char *human_name
, void *cb_data
)
69 struct gcore_elf_collect_regset_section_cb_data
*data
70 = (struct gcore_elf_collect_regset_section_cb_data
*) cb_data
;
71 bool variable_size_section
= (regset
!= nullptr
72 && regset
->flags
& REGSET_VARIABLE_SIZE
);
74 gdb_assert (variable_size_section
|| supply_size
== collect_size
);
76 if (data
->abort_iteration
)
79 gdb_assert (regset
!= nullptr && regset
->collect_regset
!= nullptr);
81 /* This is intentionally zero-initialized by using std::vector, so
82 that any padding bytes in the core file will show as 0. */
83 std::vector
<gdb_byte
> buf (collect_size
);
85 regset
->collect_regset (regset
, data
->regcache
, -1, buf
.data (),
88 /* PRSTATUS still needs to be treated specially. */
89 if (strcmp (sect_name
, ".reg") == 0)
90 data
->note_data
->reset (elfcore_write_prstatus
91 (data
->obfd
, data
->note_data
->release (),
92 data
->note_size
, data
->lwp
,
93 gdb_signal_to_host (data
->stop_signal
),
96 data
->note_data
->reset (elfcore_write_register_note
97 (data
->obfd
, data
->note_data
->release (),
98 data
->note_size
, sect_name
, buf
.data (),
101 if (*data
->note_data
== nullptr)
102 data
->abort_iteration
= true;
105 /* Records the register state of thread PTID out of REGCACHE into the note
106 buffer represented by *NOTE_DATA and NOTE_SIZE. OBFD is the bfd into
107 which the core file is being created, and STOP_SIGNAL is the signal that
108 cause thread PTID to stop. */
111 gcore_elf_collect_thread_registers
112 (const struct regcache
*regcache
, ptid_t ptid
, bfd
*obfd
,
113 gdb::unique_xmalloc_ptr
<char> *note_data
, int *note_size
,
114 enum gdb_signal stop_signal
)
116 struct gdbarch
*gdbarch
= regcache
->arch ();
117 gcore_elf_collect_regset_section_cb_data
data (gdbarch
, regcache
, obfd
,
119 note_data
, note_size
);
120 gdbarch_iterate_over_regset_sections
121 (gdbarch
, gcore_elf_collect_regset_section_cb
, &data
, regcache
);
124 /* See gcore-elf.h. */
127 gcore_elf_build_thread_register_notes
128 (struct gdbarch
*gdbarch
, struct thread_info
*info
, gdb_signal stop_signal
,
129 bfd
*obfd
, gdb::unique_xmalloc_ptr
<char> *note_data
, int *note_size
)
131 struct regcache
*regcache
132 = get_thread_arch_regcache (info
->inf
->process_target (),
133 info
->ptid
, gdbarch
);
134 target_fetch_registers (regcache
, -1);
135 gcore_elf_collect_thread_registers (regcache
, info
->ptid
, obfd
,
136 note_data
, note_size
, stop_signal
);
139 /* See gcore-elf.h. */
142 gcore_elf_make_tdesc_note (bfd
*obfd
,
143 gdb::unique_xmalloc_ptr
<char> *note_data
,
146 /* Append the target description to the core file. */
147 const struct target_desc
*tdesc
= gdbarch_target_desc (target_gdbarch ());
148 const char *tdesc_xml
149 = tdesc
== nullptr ? nullptr : tdesc_get_features_xml (tdesc
);
150 if (tdesc_xml
!= nullptr && *tdesc_xml
!= '\0')
152 /* Skip the leading '@'. */
153 if (*tdesc_xml
== '@')
156 /* Include the null terminator in the length. */
157 size_t tdesc_len
= strlen (tdesc_xml
) + 1;
159 /* Now add the target description into the core file. */
160 note_data
->reset (elfcore_write_register_note (obfd
,
161 note_data
->release (),
163 ".gdb-tdesc", tdesc_xml
,