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