Commit | Line | Data |
---|---|---|
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" | |
e6cdd38e | 27 | #include "xml-syscall.h" |
a904c024 | 28 | |
a904c024 AA |
29 | #include "elf-bfd.h" |
30 | #include "fbsd-tdep.h" | |
31 | ||
32 | ||
79117428 JB |
33 | /* This is how we want PTIDs from core files to be printed. */ |
34 | ||
35 | static char * | |
36 | fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid) | |
37 | { | |
38 | static char buf[80]; | |
39 | ||
40 | if (ptid_get_lwp (ptid) != 0) | |
41 | { | |
42 | xsnprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid)); | |
43 | return buf; | |
44 | } | |
45 | ||
46 | return normal_pid_to_str (ptid); | |
47 | } | |
48 | ||
49 | /* Extract the name assigned to a thread from a core. Returns the | |
50 | string in a static buffer. */ | |
51 | ||
52 | static const char * | |
53 | fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr) | |
54 | { | |
55 | static char buf[80]; | |
56 | struct bfd_section *section; | |
57 | bfd_size_type size; | |
58 | char sectionstr[32]; | |
59 | ||
60 | if (ptid_get_lwp (thr->ptid) != 0) | |
61 | { | |
62 | /* FreeBSD includes a NT_FREEBSD_THRMISC note for each thread | |
63 | whose contents are defined by a "struct thrmisc" declared in | |
64 | <sys/procfs.h> on FreeBSD. The per-thread name is stored as | |
65 | a null-terminated string as the first member of the | |
66 | structure. Rather than define the full structure here, just | |
67 | extract the null-terminated name from the start of the | |
68 | note. */ | |
69 | xsnprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld", | |
70 | ptid_get_lwp (thr->ptid)); | |
71 | section = bfd_get_section_by_name (core_bfd, sectionstr); | |
72 | if (section != NULL && bfd_section_size (core_bfd, section) > 0) | |
73 | { | |
74 | /* Truncate the name if it is longer than "buf". */ | |
75 | size = bfd_section_size (core_bfd, section); | |
76 | if (size > sizeof buf - 1) | |
77 | size = sizeof buf - 1; | |
78 | if (bfd_get_section_contents (core_bfd, section, buf, (file_ptr) 0, | |
79 | size) | |
80 | && buf[0] != '\0') | |
81 | { | |
82 | buf[size] = '\0'; | |
83 | ||
84 | /* Note that each thread will report the process command | |
85 | as its thread name instead of an empty name if a name | |
86 | has not been set explicitly. Return a NULL name in | |
87 | that case. */ | |
88 | if (strcmp (buf, elf_tdata (core_bfd)->core->program) != 0) | |
89 | return buf; | |
90 | } | |
91 | } | |
92 | } | |
93 | ||
94 | return NULL; | |
95 | } | |
96 | ||
a904c024 AA |
97 | static int |
98 | find_signalled_thread (struct thread_info *info, void *data) | |
99 | { | |
100 | if (info->suspend.stop_signal != GDB_SIGNAL_0 | |
101 | && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) | |
102 | return 1; | |
103 | ||
104 | return 0; | |
105 | } | |
106 | ||
20a0aab3 JB |
107 | /* Structure for passing information from |
108 | fbsd_collect_thread_registers via an iterator to | |
109 | fbsd_collect_regset_section_cb. */ | |
a904c024 AA |
110 | |
111 | struct fbsd_collect_regset_section_cb_data | |
112 | { | |
113 | const struct regcache *regcache; | |
114 | bfd *obfd; | |
115 | char *note_data; | |
116 | int *note_size; | |
20a0aab3 JB |
117 | unsigned long lwp; |
118 | enum gdb_signal stop_signal; | |
119 | int abort_iteration; | |
a904c024 AA |
120 | }; |
121 | ||
122 | static void | |
123 | fbsd_collect_regset_section_cb (const char *sect_name, int size, | |
124 | const struct regset *regset, | |
125 | const char *human_name, void *cb_data) | |
126 | { | |
127 | char *buf; | |
7567e115 SM |
128 | struct fbsd_collect_regset_section_cb_data *data |
129 | = (struct fbsd_collect_regset_section_cb_data *) cb_data; | |
a904c024 | 130 | |
20a0aab3 JB |
131 | if (data->abort_iteration) |
132 | return; | |
133 | ||
a904c024 AA |
134 | gdb_assert (regset->collect_regset); |
135 | ||
224c3ddb | 136 | buf = (char *) xmalloc (size); |
a904c024 AA |
137 | regset->collect_regset (regset, data->regcache, -1, buf, size); |
138 | ||
139 | /* PRSTATUS still needs to be treated specially. */ | |
140 | if (strcmp (sect_name, ".reg") == 0) | |
141 | data->note_data = (char *) elfcore_write_prstatus | |
20a0aab3 JB |
142 | (data->obfd, data->note_data, data->note_size, data->lwp, |
143 | gdb_signal_to_host (data->stop_signal), buf); | |
a904c024 AA |
144 | else |
145 | data->note_data = (char *) elfcore_write_register_note | |
146 | (data->obfd, data->note_data, data->note_size, | |
147 | sect_name, buf, size); | |
148 | xfree (buf); | |
20a0aab3 JB |
149 | |
150 | if (data->note_data == NULL) | |
151 | data->abort_iteration = 1; | |
152 | } | |
153 | ||
154 | /* Records the thread's register state for the corefile note | |
155 | section. */ | |
156 | ||
157 | static char * | |
158 | fbsd_collect_thread_registers (const struct regcache *regcache, | |
159 | ptid_t ptid, bfd *obfd, | |
160 | char *note_data, int *note_size, | |
161 | enum gdb_signal stop_signal) | |
162 | { | |
163 | struct gdbarch *gdbarch = get_regcache_arch (regcache); | |
164 | struct fbsd_collect_regset_section_cb_data data; | |
165 | ||
166 | data.regcache = regcache; | |
167 | data.obfd = obfd; | |
168 | data.note_data = note_data; | |
169 | data.note_size = note_size; | |
170 | data.stop_signal = stop_signal; | |
171 | data.abort_iteration = 0; | |
172 | data.lwp = ptid_get_lwp (ptid); | |
173 | ||
174 | gdbarch_iterate_over_regset_sections (gdbarch, | |
175 | fbsd_collect_regset_section_cb, | |
176 | &data, regcache); | |
177 | return data.note_data; | |
178 | } | |
179 | ||
180 | struct fbsd_corefile_thread_data | |
181 | { | |
182 | struct gdbarch *gdbarch; | |
183 | bfd *obfd; | |
184 | char *note_data; | |
185 | int *note_size; | |
186 | enum gdb_signal stop_signal; | |
187 | }; | |
188 | ||
189 | /* Records the thread's register state for the corefile note | |
190 | section. */ | |
191 | ||
192 | static void | |
193 | fbsd_corefile_thread (struct thread_info *info, | |
194 | struct fbsd_corefile_thread_data *args) | |
195 | { | |
196 | struct cleanup *old_chain; | |
197 | struct regcache *regcache; | |
198 | ||
199 | regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); | |
200 | ||
201 | old_chain = save_inferior_ptid (); | |
202 | inferior_ptid = info->ptid; | |
203 | target_fetch_registers (regcache, -1); | |
204 | do_cleanups (old_chain); | |
205 | ||
206 | args->note_data = fbsd_collect_thread_registers | |
207 | (regcache, info->ptid, args->obfd, args->note_data, | |
208 | args->note_size, args->stop_signal); | |
a904c024 AA |
209 | } |
210 | ||
211 | /* Create appropriate note sections for a corefile, returning them in | |
212 | allocated memory. */ | |
213 | ||
214 | static char * | |
215 | fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) | |
216 | { | |
20a0aab3 JB |
217 | struct fbsd_corefile_thread_data thread_args; |
218 | char *note_data = NULL; | |
a904c024 | 219 | Elf_Internal_Ehdr *i_ehdrp; |
20a0aab3 | 220 | struct thread_info *curr_thr, *signalled_thr, *thr; |
a904c024 AA |
221 | |
222 | /* Put a "FreeBSD" label in the ELF header. */ | |
223 | i_ehdrp = elf_elfheader (obfd); | |
224 | i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; | |
225 | ||
226 | gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); | |
227 | ||
a904c024 AA |
228 | if (get_exec_file (0)) |
229 | { | |
230 | const char *fname = lbasename (get_exec_file (0)); | |
231 | char *psargs = xstrdup (fname); | |
232 | ||
233 | if (get_inferior_args ()) | |
234 | psargs = reconcat (psargs, psargs, " ", get_inferior_args (), | |
235 | (char *) NULL); | |
236 | ||
237 | note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, | |
238 | fname, psargs); | |
239 | } | |
240 | ||
20a0aab3 JB |
241 | /* Thread register information. */ |
242 | TRY | |
243 | { | |
244 | update_thread_list (); | |
245 | } | |
246 | CATCH (e, RETURN_MASK_ERROR) | |
247 | { | |
248 | exception_print (gdb_stderr, e); | |
249 | } | |
250 | END_CATCH | |
251 | ||
252 | /* Like the kernel, prefer dumping the signalled thread first. | |
253 | "First thread" is what tools use to infer the signalled thread. | |
254 | In case there's more than one signalled thread, prefer the | |
255 | current thread, if it is signalled. */ | |
256 | curr_thr = inferior_thread (); | |
257 | if (curr_thr->suspend.stop_signal != GDB_SIGNAL_0) | |
258 | signalled_thr = curr_thr; | |
259 | else | |
260 | { | |
261 | signalled_thr = iterate_over_threads (find_signalled_thread, NULL); | |
262 | if (signalled_thr == NULL) | |
263 | signalled_thr = curr_thr; | |
264 | } | |
265 | ||
266 | thread_args.gdbarch = gdbarch; | |
267 | thread_args.obfd = obfd; | |
268 | thread_args.note_data = note_data; | |
269 | thread_args.note_size = note_size; | |
270 | thread_args.stop_signal = signalled_thr->suspend.stop_signal; | |
271 | ||
272 | fbsd_corefile_thread (signalled_thr, &thread_args); | |
273 | ALL_NON_EXITED_THREADS (thr) | |
274 | { | |
275 | if (thr == signalled_thr) | |
276 | continue; | |
277 | if (ptid_get_pid (thr->ptid) != ptid_get_pid (inferior_ptid)) | |
278 | continue; | |
279 | ||
280 | fbsd_corefile_thread (thr, &thread_args); | |
281 | } | |
282 | ||
283 | note_data = thread_args.note_data; | |
284 | ||
a904c024 AA |
285 | return note_data; |
286 | } | |
287 | ||
82372b2f JB |
288 | /* Print descriptions of FreeBSD-specific AUXV entries to FILE. */ |
289 | ||
290 | static void | |
291 | fbsd_print_auxv_entry (struct gdbarch *gdbarch, struct ui_file *file, | |
292 | CORE_ADDR type, CORE_ADDR val) | |
293 | { | |
294 | const char *name; | |
295 | const char *description; | |
296 | enum auxv_format format; | |
297 | ||
298 | switch (type) | |
299 | { | |
300 | #define _TAGNAME(tag) #tag | |
301 | #define TAGNAME(tag) _TAGNAME(AT_##tag) | |
302 | #define TAG(tag, text, kind) \ | |
303 | case AT_FREEBSD_##tag: name = TAGNAME(tag); description = text; format = kind; break | |
304 | TAG (EXECPATH, _("Executable path"), AUXV_FORMAT_STR); | |
305 | TAG (CANARY, _("Canary for SSP"), AUXV_FORMAT_HEX); | |
306 | TAG (CANARYLEN, ("Length of the SSP canary"), AUXV_FORMAT_DEC); | |
307 | TAG (OSRELDATE, _("OSRELDATE"), AUXV_FORMAT_DEC); | |
308 | TAG (NCPUS, _("Number of CPUs"), AUXV_FORMAT_DEC); | |
309 | TAG (PAGESIZES, _("Pagesizes"), AUXV_FORMAT_HEX); | |
310 | TAG (PAGESIZESLEN, _("Number of pagesizes"), AUXV_FORMAT_DEC); | |
311 | TAG (TIMEKEEP, _("Pointer to timehands"), AUXV_FORMAT_HEX); | |
312 | TAG (STACKPROT, _("Initial stack protection"), AUXV_FORMAT_HEX); | |
313 | default: | |
314 | default_print_auxv_entry (gdbarch, file, type, val); | |
315 | return; | |
316 | } | |
317 | ||
318 | fprint_auxv_entry (file, name, description, format, type, val); | |
319 | } | |
320 | ||
e6cdd38e JB |
321 | /* Implement the "get_syscall_number" gdbarch method. */ |
322 | ||
323 | static LONGEST | |
324 | fbsd_get_syscall_number (struct gdbarch *gdbarch, | |
325 | ptid_t ptid) | |
326 | { | |
327 | ||
328 | /* FreeBSD doesn't use gdbarch_get_syscall_number since FreeBSD | |
329 | native targets fetch the system call number from the | |
330 | 'pl_syscall_code' member of struct ptrace_lwpinfo in fbsd_wait. | |
331 | However, system call catching requires this function to be | |
332 | set. */ | |
333 | ||
334 | internal_error (__FILE__, __LINE__, _("fbsd_get_sycall_number called")); | |
335 | } | |
336 | ||
1736a7bd | 337 | /* To be called from GDB_OSABI_FREEBSD handlers. */ |
a904c024 AA |
338 | |
339 | void | |
340 | fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
341 | { | |
79117428 JB |
342 | set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str); |
343 | set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name); | |
a904c024 | 344 | set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes); |
82372b2f | 345 | set_gdbarch_print_auxv_entry (gdbarch, fbsd_print_auxv_entry); |
e6cdd38e JB |
346 | |
347 | /* `catch syscall' */ | |
348 | set_xml_syscall_file_name (gdbarch, "syscalls/freebsd.xml"); | |
349 | set_gdbarch_get_syscall_number (gdbarch, fbsd_get_syscall_number); | |
a904c024 | 350 | } |