]> Git Repo - binutils.git/blob - gdb/gcore-elf.c
Automatic date update in version.in
[binutils.git] / gdb / gcore-elf.c
1 /* Copyright (C) 2021-2022 Free Software Foundation, Inc.
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
18 #include "defs.h"
19 #include "gcore-elf.h"
20 #include "elf-bfd.h"
21 #include "target.h"
22 #include "regcache.h"
23 #include "gdbarch.h"
24 #include "gdbthread.h"
25 #include "inferior.h"
26 #include "regset.h"
27 #include "gdbsupport/tdesc.h"
28
29 /* Structure for passing information from GCORE_COLLECT_THREAD_REGISTERS
30    via an iterator to GCORE_COLLECT_REGSET_SECTION_CB. */
31
32 struct gcore_elf_collect_regset_section_cb_data
33 {
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)
41   {
42     /* The LWP is often not available for bare metal target, in which case
43        use the tid instead.  */
44     if (ptid.lwp_p ())
45       lwp = ptid.lwp ();
46     else
47       lwp = ptid.tid ();
48   }
49
50   struct gdbarch *gdbarch;
51   const struct regcache *regcache;
52   bfd *obfd;
53   gdb::unique_xmalloc_ptr<char> *note_data;
54   int *note_size;
55   unsigned long lwp;
56   enum gdb_signal stop_signal;
57   bool abort_iteration = false;
58 };
59
60 /* Callback for ITERATE_OVER_REGSET_SECTIONS that records a single
61    regset in the core file note section.  */
62
63 static void
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)
68 {
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);
73
74   gdb_assert (variable_size_section || supply_size == collect_size);
75
76   if (data->abort_iteration)
77     return;
78
79   gdb_assert (regset != nullptr && regset->collect_regset != nullptr);
80
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);
84
85   regset->collect_regset (regset, data->regcache, -1, buf.data (),
86                           collect_size);
87
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),
94                              buf.data ()));
95   else
96     data->note_data->reset (elfcore_write_register_note
97                             (data->obfd, data->note_data->release (),
98                              data->note_size, sect_name, buf.data (),
99                              collect_size));
100
101   if (*data->note_data == nullptr)
102     data->abort_iteration = true;
103 }
104
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.  */
109
110 static void
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)
115 {
116   struct gdbarch *gdbarch = regcache->arch ();
117   gcore_elf_collect_regset_section_cb_data data (gdbarch, regcache, obfd,
118                                                  ptid, stop_signal,
119                                                  note_data, note_size);
120   gdbarch_iterate_over_regset_sections
121     (gdbarch, gcore_elf_collect_regset_section_cb, &data, regcache);
122 }
123
124 /* See gcore-elf.h.  */
125
126 void
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)
130 {
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);
137 }
138
139 /* See gcore-elf.h.  */
140
141 void
142 gcore_elf_make_tdesc_note (bfd *obfd,
143                            gdb::unique_xmalloc_ptr<char> *note_data,
144                            int *note_size)
145 {
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')
151     {
152       /* Skip the leading '@'.  */
153       if (*tdesc_xml == '@')
154         ++tdesc_xml;
155
156       /* Include the null terminator in the length.  */
157       size_t tdesc_len = strlen (tdesc_xml) + 1;
158
159       /* Now add the target description into the core file.  */
160       note_data->reset (elfcore_write_register_note (obfd,
161                                                      note_data->release (),
162                                                      note_size,
163                                                      ".gdb-tdesc", tdesc_xml,
164                                                      tdesc_len));
165     }
166 }
This page took 0.031542 seconds and 4 git commands to generate.