Add a gdbarch 'print_auxv_entry' method for FreeBSD ABIs.
[deliverable/binutils-gdb.git] / gdb / fbsd-tdep.c
1 /* Target-dependent code for FreeBSD, architecture-independent.
2
3 Copyright (C) 2002-2016 Free Software Foundation, Inc.
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"
21 #include "auxv.h"
22 #include "gdbcore.h"
23 #include "inferior.h"
24 #include "regcache.h"
25 #include "regset.h"
26 #include "gdbthread.h"
27
28 #include "elf-bfd.h"
29 #include "fbsd-tdep.h"
30
31
32 /* This is how we want PTIDs from core files to be printed. */
33
34 static char *
35 fbsd_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
51 static const char *
52 fbsd_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
96 static int
97 find_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
106 /* Structure for passing information from
107 fbsd_collect_thread_registers via an iterator to
108 fbsd_collect_regset_section_cb. */
109
110 struct fbsd_collect_regset_section_cb_data
111 {
112 const struct regcache *regcache;
113 bfd *obfd;
114 char *note_data;
115 int *note_size;
116 unsigned long lwp;
117 enum gdb_signal stop_signal;
118 int abort_iteration;
119 };
120
121 static void
122 fbsd_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;
127 struct fbsd_collect_regset_section_cb_data *data
128 = (struct fbsd_collect_regset_section_cb_data *) cb_data;
129
130 if (data->abort_iteration)
131 return;
132
133 gdb_assert (regset->collect_regset);
134
135 buf = (char *) xmalloc (size);
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
141 (data->obfd, data->note_data, data->note_size, data->lwp,
142 gdb_signal_to_host (data->stop_signal), buf);
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);
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
156 static char *
157 fbsd_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
179 struct 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
191 static void
192 fbsd_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);
208 }
209
210 /* Create appropriate note sections for a corefile, returning them in
211 allocated memory. */
212
213 static char *
214 fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
215 {
216 struct fbsd_corefile_thread_data thread_args;
217 char *note_data = NULL;
218 Elf_Internal_Ehdr *i_ehdrp;
219 struct thread_info *curr_thr, *signalled_thr, *thr;
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
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
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
284 return note_data;
285 }
286
287 /* Print descriptions of FreeBSD-specific AUXV entries to FILE. */
288
289 static void
290 fbsd_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
320 /* To be called from GDB_OSABI_FREEBSD_ELF handlers. */
321
322 void
323 fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
324 {
325 set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str);
326 set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name);
327 set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
328 set_gdbarch_print_auxv_entry (gdbarch, fbsd_print_auxv_entry);
329 }
This page took 0.036241 seconds and 4 git commands to generate.