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