Add a gdbarch 'print_auxv_entry' method for FreeBSD ABIs.
[deliverable/binutils-gdb.git] / gdb / fbsd-tdep.c
CommitLineData
a904c024
AA
1/* Target-dependent code for FreeBSD, architecture-independent.
2
618f726f 3 Copyright (C) 2002-2016 Free Software Foundation, Inc.
a904c024
AA
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
82372b2f 21#include "auxv.h"
a904c024
AA
22#include "gdbcore.h"
23#include "inferior.h"
24#include "regcache.h"
25#include "regset.h"
26#include "gdbthread.h"
27
a904c024
AA
28#include "elf-bfd.h"
29#include "fbsd-tdep.h"
30
31
79117428
JB
32/* This is how we want PTIDs from core files to be printed. */
33
34static char *
35fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
36{
37 static char buf[80];
38
39 if (ptid_get_lwp (ptid) != 0)
40 {
41 xsnprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid));
42 return buf;
43 }
44
45 return normal_pid_to_str (ptid);
46}
47
48/* Extract the name assigned to a thread from a core. Returns the
49 string in a static buffer. */
50
51static const char *
52fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr)
53{
54 static char buf[80];
55 struct bfd_section *section;
56 bfd_size_type size;
57 char sectionstr[32];
58
59 if (ptid_get_lwp (thr->ptid) != 0)
60 {
61 /* FreeBSD includes a NT_FREEBSD_THRMISC note for each thread
62 whose contents are defined by a "struct thrmisc" declared in
63 <sys/procfs.h> on FreeBSD. The per-thread name is stored as
64 a null-terminated string as the first member of the
65 structure. Rather than define the full structure here, just
66 extract the null-terminated name from the start of the
67 note. */
68 xsnprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld",
69 ptid_get_lwp (thr->ptid));
70 section = bfd_get_section_by_name (core_bfd, sectionstr);
71 if (section != NULL && bfd_section_size (core_bfd, section) > 0)
72 {
73 /* Truncate the name if it is longer than "buf". */
74 size = bfd_section_size (core_bfd, section);
75 if (size > sizeof buf - 1)
76 size = sizeof buf - 1;
77 if (bfd_get_section_contents (core_bfd, section, buf, (file_ptr) 0,
78 size)
79 && buf[0] != '\0')
80 {
81 buf[size] = '\0';
82
83 /* Note that each thread will report the process command
84 as its thread name instead of an empty name if a name
85 has not been set explicitly. Return a NULL name in
86 that case. */
87 if (strcmp (buf, elf_tdata (core_bfd)->core->program) != 0)
88 return buf;
89 }
90 }
91 }
92
93 return NULL;
94}
95
a904c024
AA
96static int
97find_signalled_thread (struct thread_info *info, void *data)
98{
99 if (info->suspend.stop_signal != GDB_SIGNAL_0
100 && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid))
101 return 1;
102
103 return 0;
104}
105
20a0aab3
JB
106/* Structure for passing information from
107 fbsd_collect_thread_registers via an iterator to
108 fbsd_collect_regset_section_cb. */
a904c024
AA
109
110struct fbsd_collect_regset_section_cb_data
111{
112 const struct regcache *regcache;
113 bfd *obfd;
114 char *note_data;
115 int *note_size;
20a0aab3
JB
116 unsigned long lwp;
117 enum gdb_signal stop_signal;
118 int abort_iteration;
a904c024
AA
119};
120
121static void
122fbsd_collect_regset_section_cb (const char *sect_name, int size,
123 const struct regset *regset,
124 const char *human_name, void *cb_data)
125{
126 char *buf;
7567e115
SM
127 struct fbsd_collect_regset_section_cb_data *data
128 = (struct fbsd_collect_regset_section_cb_data *) cb_data;
a904c024 129
20a0aab3
JB
130 if (data->abort_iteration)
131 return;
132
a904c024
AA
133 gdb_assert (regset->collect_regset);
134
224c3ddb 135 buf = (char *) xmalloc (size);
a904c024
AA
136 regset->collect_regset (regset, data->regcache, -1, buf, size);
137
138 /* PRSTATUS still needs to be treated specially. */
139 if (strcmp (sect_name, ".reg") == 0)
140 data->note_data = (char *) elfcore_write_prstatus
20a0aab3
JB
141 (data->obfd, data->note_data, data->note_size, data->lwp,
142 gdb_signal_to_host (data->stop_signal), buf);
a904c024
AA
143 else
144 data->note_data = (char *) elfcore_write_register_note
145 (data->obfd, data->note_data, data->note_size,
146 sect_name, buf, size);
147 xfree (buf);
20a0aab3
JB
148
149 if (data->note_data == NULL)
150 data->abort_iteration = 1;
151}
152
153/* Records the thread's register state for the corefile note
154 section. */
155
156static char *
157fbsd_collect_thread_registers (const struct regcache *regcache,
158 ptid_t ptid, bfd *obfd,
159 char *note_data, int *note_size,
160 enum gdb_signal stop_signal)
161{
162 struct gdbarch *gdbarch = get_regcache_arch (regcache);
163 struct fbsd_collect_regset_section_cb_data data;
164
165 data.regcache = regcache;
166 data.obfd = obfd;
167 data.note_data = note_data;
168 data.note_size = note_size;
169 data.stop_signal = stop_signal;
170 data.abort_iteration = 0;
171 data.lwp = ptid_get_lwp (ptid);
172
173 gdbarch_iterate_over_regset_sections (gdbarch,
174 fbsd_collect_regset_section_cb,
175 &data, regcache);
176 return data.note_data;
177}
178
179struct fbsd_corefile_thread_data
180{
181 struct gdbarch *gdbarch;
182 bfd *obfd;
183 char *note_data;
184 int *note_size;
185 enum gdb_signal stop_signal;
186};
187
188/* Records the thread's register state for the corefile note
189 section. */
190
191static void
192fbsd_corefile_thread (struct thread_info *info,
193 struct fbsd_corefile_thread_data *args)
194{
195 struct cleanup *old_chain;
196 struct regcache *regcache;
197
198 regcache = get_thread_arch_regcache (info->ptid, args->gdbarch);
199
200 old_chain = save_inferior_ptid ();
201 inferior_ptid = info->ptid;
202 target_fetch_registers (regcache, -1);
203 do_cleanups (old_chain);
204
205 args->note_data = fbsd_collect_thread_registers
206 (regcache, info->ptid, args->obfd, args->note_data,
207 args->note_size, args->stop_signal);
a904c024
AA
208}
209
210/* Create appropriate note sections for a corefile, returning them in
211 allocated memory. */
212
213static char *
214fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
215{
20a0aab3
JB
216 struct fbsd_corefile_thread_data thread_args;
217 char *note_data = NULL;
a904c024 218 Elf_Internal_Ehdr *i_ehdrp;
20a0aab3 219 struct thread_info *curr_thr, *signalled_thr, *thr;
a904c024
AA
220
221 /* Put a "FreeBSD" label in the ELF header. */
222 i_ehdrp = elf_elfheader (obfd);
223 i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
224
225 gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch));
226
a904c024
AA
227 if (get_exec_file (0))
228 {
229 const char *fname = lbasename (get_exec_file (0));
230 char *psargs = xstrdup (fname);
231
232 if (get_inferior_args ())
233 psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
234 (char *) NULL);
235
236 note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
237 fname, psargs);
238 }
239
20a0aab3
JB
240 /* Thread register information. */
241 TRY
242 {
243 update_thread_list ();
244 }
245 CATCH (e, RETURN_MASK_ERROR)
246 {
247 exception_print (gdb_stderr, e);
248 }
249 END_CATCH
250
251 /* Like the kernel, prefer dumping the signalled thread first.
252 "First thread" is what tools use to infer the signalled thread.
253 In case there's more than one signalled thread, prefer the
254 current thread, if it is signalled. */
255 curr_thr = inferior_thread ();
256 if (curr_thr->suspend.stop_signal != GDB_SIGNAL_0)
257 signalled_thr = curr_thr;
258 else
259 {
260 signalled_thr = iterate_over_threads (find_signalled_thread, NULL);
261 if (signalled_thr == NULL)
262 signalled_thr = curr_thr;
263 }
264
265 thread_args.gdbarch = gdbarch;
266 thread_args.obfd = obfd;
267 thread_args.note_data = note_data;
268 thread_args.note_size = note_size;
269 thread_args.stop_signal = signalled_thr->suspend.stop_signal;
270
271 fbsd_corefile_thread (signalled_thr, &thread_args);
272 ALL_NON_EXITED_THREADS (thr)
273 {
274 if (thr == signalled_thr)
275 continue;
276 if (ptid_get_pid (thr->ptid) != ptid_get_pid (inferior_ptid))
277 continue;
278
279 fbsd_corefile_thread (thr, &thread_args);
280 }
281
282 note_data = thread_args.note_data;
283
a904c024
AA
284 return note_data;
285}
286
82372b2f
JB
287/* Print descriptions of FreeBSD-specific AUXV entries to FILE. */
288
289static void
290fbsd_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file,
291 CORE_ADDR type, CORE_ADDR val)
292{
293 const char *name;
294 const char *description;
295 enum auxv_format format;
296
297 switch (type)
298 {
299#define _TAGNAME(tag) #tag
300#define TAGNAME(tag) _TAGNAME(AT_##tag)
301#define TAG(tag, text, kind) \
302 case AT_FREEBSD_##tag: name = TAGNAME(tag); description = text; format = kind; break
303 TAG (EXECPATH, _("Executable path"), AUXV_FORMAT_STR);
304 TAG (CANARY, _("Canary for SSP"), AUXV_FORMAT_HEX);
305 TAG (CANARYLEN, ("Length of the SSP canary"), AUXV_FORMAT_DEC);
306 TAG (OSRELDATE, _("OSRELDATE"), AUXV_FORMAT_DEC);
307 TAG (NCPUS, _("Number of CPUs"), AUXV_FORMAT_DEC);
308 TAG (PAGESIZES, _("Pagesizes"), AUXV_FORMAT_HEX);
309 TAG (PAGESIZESLEN, _("Number of pagesizes"), AUXV_FORMAT_DEC);
310 TAG (TIMEKEEP, _("Pointer to timehands"), AUXV_FORMAT_HEX);
311 TAG (STACKPROT, _("Initial stack protection"), AUXV_FORMAT_HEX);
312 default:
313 default_print_auxv_entry (gdbarch, file, type, val);
314 return;
315 }
316
317 fprint_auxv_entry (file, name, description, format, type, val);
318}
319
a904c024
AA
320/* To be called from GDB_OSABI_FREEBSD_ELF handlers. */
321
322void
323fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
324{
79117428
JB
325 set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str);
326 set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name);
a904c024 327 set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
82372b2f 328 set_gdbarch_print_auxv_entry (gdbarch, fbsd_print_auxv_entry);
a904c024 329}
This page took 0.17034 seconds and 4 git commands to generate.