Commit | Line | Data |
---|---|---|
a904c024 AA |
1 | /* Target-dependent code for FreeBSD, architecture-independent. |
2 | ||
61baf725 | 3 | Copyright (C) 2002-2017 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" | |
e6cdd38e | 27 | #include "xml-syscall.h" |
a904c024 | 28 | |
a904c024 AA |
29 | #include "elf-bfd.h" |
30 | #include "fbsd-tdep.h" | |
31 | ||
32 | ||
762c974a JB |
33 | static struct gdbarch_data *fbsd_gdbarch_data_handle; |
34 | ||
35 | struct fbsd_gdbarch_data | |
36 | { | |
37 | struct type *siginfo_type; | |
38 | }; | |
39 | ||
40 | static void * | |
41 | init_fbsd_gdbarch_data (struct gdbarch *gdbarch) | |
42 | { | |
43 | return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct fbsd_gdbarch_data); | |
44 | } | |
45 | ||
46 | static struct fbsd_gdbarch_data * | |
47 | get_fbsd_gdbarch_data (struct gdbarch *gdbarch) | |
48 | { | |
49 | return ((struct fbsd_gdbarch_data *) | |
50 | gdbarch_data (gdbarch, fbsd_gdbarch_data_handle)); | |
51 | } | |
52 | ||
79117428 JB |
53 | /* This is how we want PTIDs from core files to be printed. */ |
54 | ||
7a114964 | 55 | static const char * |
79117428 JB |
56 | fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid) |
57 | { | |
58 | static char buf[80]; | |
59 | ||
60 | if (ptid_get_lwp (ptid) != 0) | |
61 | { | |
62 | xsnprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid)); | |
63 | return buf; | |
64 | } | |
65 | ||
66 | return normal_pid_to_str (ptid); | |
67 | } | |
68 | ||
69 | /* Extract the name assigned to a thread from a core. Returns the | |
70 | string in a static buffer. */ | |
71 | ||
72 | static const char * | |
73 | fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr) | |
74 | { | |
75 | static char buf[80]; | |
76 | struct bfd_section *section; | |
77 | bfd_size_type size; | |
78 | char sectionstr[32]; | |
79 | ||
80 | if (ptid_get_lwp (thr->ptid) != 0) | |
81 | { | |
82 | /* FreeBSD includes a NT_FREEBSD_THRMISC note for each thread | |
83 | whose contents are defined by a "struct thrmisc" declared in | |
84 | <sys/procfs.h> on FreeBSD. The per-thread name is stored as | |
85 | a null-terminated string as the first member of the | |
86 | structure. Rather than define the full structure here, just | |
87 | extract the null-terminated name from the start of the | |
88 | note. */ | |
89 | xsnprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld", | |
90 | ptid_get_lwp (thr->ptid)); | |
91 | section = bfd_get_section_by_name (core_bfd, sectionstr); | |
92 | if (section != NULL && bfd_section_size (core_bfd, section) > 0) | |
93 | { | |
94 | /* Truncate the name if it is longer than "buf". */ | |
95 | size = bfd_section_size (core_bfd, section); | |
96 | if (size > sizeof buf - 1) | |
97 | size = sizeof buf - 1; | |
98 | if (bfd_get_section_contents (core_bfd, section, buf, (file_ptr) 0, | |
99 | size) | |
100 | && buf[0] != '\0') | |
101 | { | |
102 | buf[size] = '\0'; | |
103 | ||
104 | /* Note that each thread will report the process command | |
105 | as its thread name instead of an empty name if a name | |
106 | has not been set explicitly. Return a NULL name in | |
107 | that case. */ | |
108 | if (strcmp (buf, elf_tdata (core_bfd)->core->program) != 0) | |
109 | return buf; | |
110 | } | |
111 | } | |
112 | } | |
113 | ||
114 | return NULL; | |
115 | } | |
116 | ||
a904c024 AA |
117 | static int |
118 | find_signalled_thread (struct thread_info *info, void *data) | |
119 | { | |
120 | if (info->suspend.stop_signal != GDB_SIGNAL_0 | |
121 | && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) | |
122 | return 1; | |
123 | ||
124 | return 0; | |
125 | } | |
126 | ||
20a0aab3 JB |
127 | /* Structure for passing information from |
128 | fbsd_collect_thread_registers via an iterator to | |
129 | fbsd_collect_regset_section_cb. */ | |
a904c024 AA |
130 | |
131 | struct fbsd_collect_regset_section_cb_data | |
132 | { | |
133 | const struct regcache *regcache; | |
134 | bfd *obfd; | |
135 | char *note_data; | |
136 | int *note_size; | |
20a0aab3 JB |
137 | unsigned long lwp; |
138 | enum gdb_signal stop_signal; | |
139 | int abort_iteration; | |
a904c024 AA |
140 | }; |
141 | ||
142 | static void | |
143 | fbsd_collect_regset_section_cb (const char *sect_name, int size, | |
144 | const struct regset *regset, | |
145 | const char *human_name, void *cb_data) | |
146 | { | |
147 | char *buf; | |
7567e115 SM |
148 | struct fbsd_collect_regset_section_cb_data *data |
149 | = (struct fbsd_collect_regset_section_cb_data *) cb_data; | |
a904c024 | 150 | |
20a0aab3 JB |
151 | if (data->abort_iteration) |
152 | return; | |
153 | ||
a904c024 AA |
154 | gdb_assert (regset->collect_regset); |
155 | ||
224c3ddb | 156 | buf = (char *) xmalloc (size); |
a904c024 AA |
157 | regset->collect_regset (regset, data->regcache, -1, buf, size); |
158 | ||
159 | /* PRSTATUS still needs to be treated specially. */ | |
160 | if (strcmp (sect_name, ".reg") == 0) | |
161 | data->note_data = (char *) elfcore_write_prstatus | |
20a0aab3 JB |
162 | (data->obfd, data->note_data, data->note_size, data->lwp, |
163 | gdb_signal_to_host (data->stop_signal), buf); | |
a904c024 AA |
164 | else |
165 | data->note_data = (char *) elfcore_write_register_note | |
166 | (data->obfd, data->note_data, data->note_size, | |
167 | sect_name, buf, size); | |
168 | xfree (buf); | |
20a0aab3 JB |
169 | |
170 | if (data->note_data == NULL) | |
171 | data->abort_iteration = 1; | |
172 | } | |
173 | ||
174 | /* Records the thread's register state for the corefile note | |
175 | section. */ | |
176 | ||
177 | static char * | |
178 | fbsd_collect_thread_registers (const struct regcache *regcache, | |
179 | ptid_t ptid, bfd *obfd, | |
180 | char *note_data, int *note_size, | |
181 | enum gdb_signal stop_signal) | |
182 | { | |
183 | struct gdbarch *gdbarch = get_regcache_arch (regcache); | |
184 | struct fbsd_collect_regset_section_cb_data data; | |
185 | ||
186 | data.regcache = regcache; | |
187 | data.obfd = obfd; | |
188 | data.note_data = note_data; | |
189 | data.note_size = note_size; | |
190 | data.stop_signal = stop_signal; | |
191 | data.abort_iteration = 0; | |
192 | data.lwp = ptid_get_lwp (ptid); | |
193 | ||
194 | gdbarch_iterate_over_regset_sections (gdbarch, | |
195 | fbsd_collect_regset_section_cb, | |
196 | &data, regcache); | |
197 | return data.note_data; | |
198 | } | |
199 | ||
200 | struct fbsd_corefile_thread_data | |
201 | { | |
202 | struct gdbarch *gdbarch; | |
203 | bfd *obfd; | |
204 | char *note_data; | |
205 | int *note_size; | |
206 | enum gdb_signal stop_signal; | |
207 | }; | |
208 | ||
209 | /* Records the thread's register state for the corefile note | |
210 | section. */ | |
211 | ||
212 | static void | |
213 | fbsd_corefile_thread (struct thread_info *info, | |
214 | struct fbsd_corefile_thread_data *args) | |
215 | { | |
20a0aab3 JB |
216 | struct regcache *regcache; |
217 | ||
218 | regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); | |
219 | ||
20a0aab3 | 220 | target_fetch_registers (regcache, -1); |
20a0aab3 JB |
221 | |
222 | args->note_data = fbsd_collect_thread_registers | |
223 | (regcache, info->ptid, args->obfd, args->note_data, | |
224 | args->note_size, args->stop_signal); | |
a904c024 AA |
225 | } |
226 | ||
227 | /* Create appropriate note sections for a corefile, returning them in | |
228 | allocated memory. */ | |
229 | ||
230 | static char * | |
231 | fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) | |
232 | { | |
20a0aab3 JB |
233 | struct fbsd_corefile_thread_data thread_args; |
234 | char *note_data = NULL; | |
a904c024 | 235 | Elf_Internal_Ehdr *i_ehdrp; |
20a0aab3 | 236 | struct thread_info *curr_thr, *signalled_thr, *thr; |
a904c024 AA |
237 | |
238 | /* Put a "FreeBSD" label in the ELF header. */ | |
239 | i_ehdrp = elf_elfheader (obfd); | |
240 | i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; | |
241 | ||
242 | gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); | |
243 | ||
a904c024 AA |
244 | if (get_exec_file (0)) |
245 | { | |
246 | const char *fname = lbasename (get_exec_file (0)); | |
247 | char *psargs = xstrdup (fname); | |
248 | ||
249 | if (get_inferior_args ()) | |
250 | psargs = reconcat (psargs, psargs, " ", get_inferior_args (), | |
251 | (char *) NULL); | |
252 | ||
253 | note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, | |
254 | fname, psargs); | |
255 | } | |
256 | ||
20a0aab3 JB |
257 | /* Thread register information. */ |
258 | TRY | |
259 | { | |
260 | update_thread_list (); | |
261 | } | |
262 | CATCH (e, RETURN_MASK_ERROR) | |
263 | { | |
264 | exception_print (gdb_stderr, e); | |
265 | } | |
266 | END_CATCH | |
267 | ||
268 | /* Like the kernel, prefer dumping the signalled thread first. | |
269 | "First thread" is what tools use to infer the signalled thread. | |
270 | In case there's more than one signalled thread, prefer the | |
271 | current thread, if it is signalled. */ | |
272 | curr_thr = inferior_thread (); | |
273 | if (curr_thr->suspend.stop_signal != GDB_SIGNAL_0) | |
274 | signalled_thr = curr_thr; | |
275 | else | |
276 | { | |
277 | signalled_thr = iterate_over_threads (find_signalled_thread, NULL); | |
278 | if (signalled_thr == NULL) | |
279 | signalled_thr = curr_thr; | |
280 | } | |
281 | ||
282 | thread_args.gdbarch = gdbarch; | |
283 | thread_args.obfd = obfd; | |
284 | thread_args.note_data = note_data; | |
285 | thread_args.note_size = note_size; | |
286 | thread_args.stop_signal = signalled_thr->suspend.stop_signal; | |
287 | ||
288 | fbsd_corefile_thread (signalled_thr, &thread_args); | |
289 | ALL_NON_EXITED_THREADS (thr) | |
290 | { | |
291 | if (thr == signalled_thr) | |
292 | continue; | |
293 | if (ptid_get_pid (thr->ptid) != ptid_get_pid (inferior_ptid)) | |
294 | continue; | |
295 | ||
296 | fbsd_corefile_thread (thr, &thread_args); | |
297 | } | |
298 | ||
299 | note_data = thread_args.note_data; | |
300 | ||
a904c024 AA |
301 | return note_data; |
302 | } | |
303 | ||
82372b2f JB |
304 | /* Print descriptions of FreeBSD-specific AUXV entries to FILE. */ |
305 | ||
306 | static void | |
307 | fbsd_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file, | |
308 | CORE_ADDR type, CORE_ADDR val) | |
309 | { | |
310 | const char *name; | |
311 | const char *description; | |
312 | enum auxv_format format; | |
313 | ||
314 | switch (type) | |
315 | { | |
316 | #define _TAGNAME(tag) #tag | |
317 | #define TAGNAME(tag) _TAGNAME(AT_##tag) | |
318 | #define TAG(tag, text, kind) \ | |
319 | case AT_FREEBSD_##tag: name = TAGNAME(tag); description = text; format = kind; break | |
320 | TAG (EXECPATH, _("Executable path"), AUXV_FORMAT_STR); | |
321 | TAG (CANARY, _("Canary for SSP"), AUXV_FORMAT_HEX); | |
322 | TAG (CANARYLEN, ("Length of the SSP canary"), AUXV_FORMAT_DEC); | |
323 | TAG (OSRELDATE, _("OSRELDATE"), AUXV_FORMAT_DEC); | |
324 | TAG (NCPUS, _("Number of CPUs"), AUXV_FORMAT_DEC); | |
325 | TAG (PAGESIZES, _("Pagesizes"), AUXV_FORMAT_HEX); | |
326 | TAG (PAGESIZESLEN, _("Number of pagesizes"), AUXV_FORMAT_DEC); | |
327 | TAG (TIMEKEEP, _("Pointer to timehands"), AUXV_FORMAT_HEX); | |
328 | TAG (STACKPROT, _("Initial stack protection"), AUXV_FORMAT_HEX); | |
329 | default: | |
330 | default_print_auxv_entry (gdbarch, file, type, val); | |
331 | return; | |
332 | } | |
333 | ||
334 | fprint_auxv_entry (file, name, description, format, type, val); | |
335 | } | |
336 | ||
762c974a JB |
337 | /* Implement the "get_siginfo_type" gdbarch method. */ |
338 | ||
339 | static struct type * | |
340 | fbsd_get_siginfo_type (struct gdbarch *gdbarch) | |
341 | { | |
342 | struct fbsd_gdbarch_data *fbsd_gdbarch_data; | |
343 | struct type *int_type, *int32_type, *uint32_type, *long_type, *void_ptr_type; | |
344 | struct type *uid_type, *pid_type; | |
345 | struct type *sigval_type, *reason_type; | |
346 | struct type *siginfo_type; | |
347 | struct type *type; | |
348 | ||
349 | fbsd_gdbarch_data = get_fbsd_gdbarch_data (gdbarch); | |
350 | if (fbsd_gdbarch_data->siginfo_type != NULL) | |
351 | return fbsd_gdbarch_data->siginfo_type; | |
352 | ||
353 | int_type = arch_integer_type (gdbarch, gdbarch_int_bit (gdbarch), | |
354 | 0, "int"); | |
355 | int32_type = arch_integer_type (gdbarch, 32, 0, "int32_t"); | |
356 | uint32_type = arch_integer_type (gdbarch, 32, 1, "uint32_t"); | |
357 | long_type = arch_integer_type (gdbarch, gdbarch_long_bit (gdbarch), | |
358 | 0, "long"); | |
359 | void_ptr_type = lookup_pointer_type (builtin_type (gdbarch)->builtin_void); | |
360 | ||
361 | /* union sigval */ | |
362 | sigval_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); | |
363 | TYPE_NAME (sigval_type) = xstrdup ("sigval"); | |
364 | append_composite_type_field (sigval_type, "sival_int", int_type); | |
365 | append_composite_type_field (sigval_type, "sival_ptr", void_ptr_type); | |
366 | ||
367 | /* __pid_t */ | |
368 | pid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, | |
369 | TYPE_LENGTH (int32_type), "__pid_t"); | |
370 | TYPE_TARGET_TYPE (pid_type) = int32_type; | |
371 | TYPE_TARGET_STUB (pid_type) = 1; | |
372 | ||
373 | /* __uid_t */ | |
374 | uid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, | |
375 | TYPE_LENGTH (uint32_type), "__uid_t"); | |
376 | TYPE_TARGET_TYPE (uid_type) = uint32_type; | |
377 | TYPE_TARGET_STUB (uid_type) = 1; | |
378 | ||
379 | /* _reason */ | |
380 | reason_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); | |
381 | ||
382 | /* _fault */ | |
383 | type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); | |
384 | append_composite_type_field (type, "si_trapno", int_type); | |
385 | append_composite_type_field (reason_type, "_fault", type); | |
386 | ||
387 | /* _timer */ | |
388 | type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); | |
389 | append_composite_type_field (type, "si_timerid", int_type); | |
390 | append_composite_type_field (type, "si_overrun", int_type); | |
391 | append_composite_type_field (reason_type, "_timer", type); | |
392 | ||
393 | /* _mesgq */ | |
394 | type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); | |
395 | append_composite_type_field (type, "si_mqd", int_type); | |
396 | append_composite_type_field (reason_type, "_mesgq", type); | |
397 | ||
398 | /* _poll */ | |
399 | type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); | |
400 | append_composite_type_field (type, "si_band", long_type); | |
401 | append_composite_type_field (reason_type, "_poll", type); | |
402 | ||
403 | /* __spare__ */ | |
404 | type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); | |
405 | append_composite_type_field (type, "__spare1__", long_type); | |
406 | append_composite_type_field (type, "__spare2__", | |
407 | init_vector_type (int_type, 7)); | |
408 | append_composite_type_field (reason_type, "__spare__", type); | |
409 | ||
410 | /* struct siginfo */ | |
411 | siginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); | |
412 | TYPE_NAME (siginfo_type) = xstrdup ("siginfo"); | |
413 | append_composite_type_field (siginfo_type, "si_signo", int_type); | |
414 | append_composite_type_field (siginfo_type, "si_errno", int_type); | |
415 | append_composite_type_field (siginfo_type, "si_code", int_type); | |
416 | append_composite_type_field (siginfo_type, "si_pid", pid_type); | |
417 | append_composite_type_field (siginfo_type, "si_uid", uid_type); | |
418 | append_composite_type_field (siginfo_type, "si_status", int_type); | |
419 | append_composite_type_field (siginfo_type, "si_addr", void_ptr_type); | |
420 | append_composite_type_field (siginfo_type, "si_value", sigval_type); | |
421 | append_composite_type_field (siginfo_type, "_reason", reason_type); | |
422 | ||
423 | fbsd_gdbarch_data->siginfo_type = siginfo_type; | |
424 | ||
425 | return siginfo_type; | |
426 | } | |
427 | ||
e6cdd38e JB |
428 | /* Implement the "get_syscall_number" gdbarch method. */ |
429 | ||
430 | static LONGEST | |
431 | fbsd_get_syscall_number (struct gdbarch *gdbarch, | |
432 | ptid_t ptid) | |
433 | { | |
434 | ||
435 | /* FreeBSD doesn't use gdbarch_get_syscall_number since FreeBSD | |
436 | native targets fetch the system call number from the | |
437 | 'pl_syscall_code' member of struct ptrace_lwpinfo in fbsd_wait. | |
438 | However, system call catching requires this function to be | |
439 | set. */ | |
440 | ||
441 | internal_error (__FILE__, __LINE__, _("fbsd_get_sycall_number called")); | |
442 | } | |
443 | ||
1736a7bd | 444 | /* To be called from GDB_OSABI_FREEBSD handlers. */ |
a904c024 AA |
445 | |
446 | void | |
447 | fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
448 | { | |
79117428 JB |
449 | set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str); |
450 | set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name); | |
a904c024 | 451 | set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes); |
82372b2f | 452 | set_gdbarch_print_auxv_entry (gdbarch, fbsd_print_auxv_entry); |
762c974a | 453 | set_gdbarch_get_siginfo_type (gdbarch, fbsd_get_siginfo_type); |
e6cdd38e JB |
454 | |
455 | /* `catch syscall' */ | |
456 | set_xml_syscall_file_name (gdbarch, "syscalls/freebsd.xml"); | |
457 | set_gdbarch_get_syscall_number (gdbarch, fbsd_get_syscall_number); | |
a904c024 | 458 | } |
762c974a JB |
459 | |
460 | /* Provide a prototype to silence -Wmissing-prototypes. */ | |
461 | extern initialize_file_ftype _initialize_fbsd_tdep; | |
462 | ||
463 | void | |
464 | _initialize_fbsd_tdep (void) | |
465 | { | |
466 | fbsd_gdbarch_data_handle = | |
467 | gdbarch_data_register_post_init (init_fbsd_gdbarch_data); | |
468 | } |