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" | |
21 | #include "gdbcore.h" | |
22 | #include "inferior.h" | |
23 | #include "regcache.h" | |
24 | #include "regset.h" | |
25 | #include "gdbthread.h" | |
26 | ||
a904c024 AA |
27 | #include "elf-bfd.h" |
28 | #include "fbsd-tdep.h" | |
29 | ||
30 | ||
79117428 JB |
31 | /* This is how we want PTIDs from core files to be printed. */ |
32 | ||
33 | static char * | |
34 | fbsd_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid) | |
35 | { | |
36 | static char buf[80]; | |
37 | ||
38 | if (ptid_get_lwp (ptid) != 0) | |
39 | { | |
40 | xsnprintf (buf, sizeof buf, "LWP %ld", ptid_get_lwp (ptid)); | |
41 | return buf; | |
42 | } | |
43 | ||
44 | return normal_pid_to_str (ptid); | |
45 | } | |
46 | ||
47 | /* Extract the name assigned to a thread from a core. Returns the | |
48 | string in a static buffer. */ | |
49 | ||
50 | static const char * | |
51 | fbsd_core_thread_name (struct gdbarch *gdbarch, struct thread_info *thr) | |
52 | { | |
53 | static char buf[80]; | |
54 | struct bfd_section *section; | |
55 | bfd_size_type size; | |
56 | char sectionstr[32]; | |
57 | ||
58 | if (ptid_get_lwp (thr->ptid) != 0) | |
59 | { | |
60 | /* FreeBSD includes a NT_FREEBSD_THRMISC note for each thread | |
61 | whose contents are defined by a "struct thrmisc" declared in | |
62 | <sys/procfs.h> on FreeBSD. The per-thread name is stored as | |
63 | a null-terminated string as the first member of the | |
64 | structure. Rather than define the full structure here, just | |
65 | extract the null-terminated name from the start of the | |
66 | note. */ | |
67 | xsnprintf (sectionstr, sizeof sectionstr, ".thrmisc/%ld", | |
68 | ptid_get_lwp (thr->ptid)); | |
69 | section = bfd_get_section_by_name (core_bfd, sectionstr); | |
70 | if (section != NULL && bfd_section_size (core_bfd, section) > 0) | |
71 | { | |
72 | /* Truncate the name if it is longer than "buf". */ | |
73 | size = bfd_section_size (core_bfd, section); | |
74 | if (size > sizeof buf - 1) | |
75 | size = sizeof buf - 1; | |
76 | if (bfd_get_section_contents (core_bfd, section, buf, (file_ptr) 0, | |
77 | size) | |
78 | && buf[0] != '\0') | |
79 | { | |
80 | buf[size] = '\0'; | |
81 | ||
82 | /* Note that each thread will report the process command | |
83 | as its thread name instead of an empty name if a name | |
84 | has not been set explicitly. Return a NULL name in | |
85 | that case. */ | |
86 | if (strcmp (buf, elf_tdata (core_bfd)->core->program) != 0) | |
87 | return buf; | |
88 | } | |
89 | } | |
90 | } | |
91 | ||
92 | return NULL; | |
93 | } | |
94 | ||
a904c024 AA |
95 | static int |
96 | find_signalled_thread (struct thread_info *info, void *data) | |
97 | { | |
98 | if (info->suspend.stop_signal != GDB_SIGNAL_0 | |
99 | && ptid_get_pid (info->ptid) == ptid_get_pid (inferior_ptid)) | |
100 | return 1; | |
101 | ||
102 | return 0; | |
103 | } | |
104 | ||
20a0aab3 JB |
105 | /* Structure for passing information from |
106 | fbsd_collect_thread_registers via an iterator to | |
107 | fbsd_collect_regset_section_cb. */ | |
a904c024 AA |
108 | |
109 | struct fbsd_collect_regset_section_cb_data | |
110 | { | |
111 | const struct regcache *regcache; | |
112 | bfd *obfd; | |
113 | char *note_data; | |
114 | int *note_size; | |
20a0aab3 JB |
115 | unsigned long lwp; |
116 | enum gdb_signal stop_signal; | |
117 | int abort_iteration; | |
a904c024 AA |
118 | }; |
119 | ||
120 | static void | |
121 | fbsd_collect_regset_section_cb (const char *sect_name, int size, | |
122 | const struct regset *regset, | |
123 | const char *human_name, void *cb_data) | |
124 | { | |
125 | char *buf; | |
7567e115 SM |
126 | struct fbsd_collect_regset_section_cb_data *data |
127 | = (struct fbsd_collect_regset_section_cb_data *) cb_data; | |
a904c024 | 128 | |
20a0aab3 JB |
129 | if (data->abort_iteration) |
130 | return; | |
131 | ||
a904c024 AA |
132 | gdb_assert (regset->collect_regset); |
133 | ||
224c3ddb | 134 | buf = (char *) xmalloc (size); |
a904c024 AA |
135 | regset->collect_regset (regset, data->regcache, -1, buf, size); |
136 | ||
137 | /* PRSTATUS still needs to be treated specially. */ | |
138 | if (strcmp (sect_name, ".reg") == 0) | |
139 | data->note_data = (char *) elfcore_write_prstatus | |
20a0aab3 JB |
140 | (data->obfd, data->note_data, data->note_size, data->lwp, |
141 | gdb_signal_to_host (data->stop_signal), buf); | |
a904c024 AA |
142 | else |
143 | data->note_data = (char *) elfcore_write_register_note | |
144 | (data->obfd, data->note_data, data->note_size, | |
145 | sect_name, buf, size); | |
146 | xfree (buf); | |
20a0aab3 JB |
147 | |
148 | if (data->note_data == NULL) | |
149 | data->abort_iteration = 1; | |
150 | } | |
151 | ||
152 | /* Records the thread's register state for the corefile note | |
153 | section. */ | |
154 | ||
155 | static char * | |
156 | fbsd_collect_thread_registers (const struct regcache *regcache, | |
157 | ptid_t ptid, bfd *obfd, | |
158 | char *note_data, int *note_size, | |
159 | enum gdb_signal stop_signal) | |
160 | { | |
161 | struct gdbarch *gdbarch = get_regcache_arch (regcache); | |
162 | struct fbsd_collect_regset_section_cb_data data; | |
163 | ||
164 | data.regcache = regcache; | |
165 | data.obfd = obfd; | |
166 | data.note_data = note_data; | |
167 | data.note_size = note_size; | |
168 | data.stop_signal = stop_signal; | |
169 | data.abort_iteration = 0; | |
170 | data.lwp = ptid_get_lwp (ptid); | |
171 | ||
172 | gdbarch_iterate_over_regset_sections (gdbarch, | |
173 | fbsd_collect_regset_section_cb, | |
174 | &data, regcache); | |
175 | return data.note_data; | |
176 | } | |
177 | ||
178 | struct fbsd_corefile_thread_data | |
179 | { | |
180 | struct gdbarch *gdbarch; | |
181 | bfd *obfd; | |
182 | char *note_data; | |
183 | int *note_size; | |
184 | enum gdb_signal stop_signal; | |
185 | }; | |
186 | ||
187 | /* Records the thread's register state for the corefile note | |
188 | section. */ | |
189 | ||
190 | static void | |
191 | fbsd_corefile_thread (struct thread_info *info, | |
192 | struct fbsd_corefile_thread_data *args) | |
193 | { | |
194 | struct cleanup *old_chain; | |
195 | struct regcache *regcache; | |
196 | ||
197 | regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); | |
198 | ||
199 | old_chain = save_inferior_ptid (); | |
200 | inferior_ptid = info->ptid; | |
201 | target_fetch_registers (regcache, -1); | |
202 | do_cleanups (old_chain); | |
203 | ||
204 | args->note_data = fbsd_collect_thread_registers | |
205 | (regcache, info->ptid, args->obfd, args->note_data, | |
206 | args->note_size, args->stop_signal); | |
a904c024 AA |
207 | } |
208 | ||
209 | /* Create appropriate note sections for a corefile, returning them in | |
210 | allocated memory. */ | |
211 | ||
212 | static char * | |
213 | fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) | |
214 | { | |
20a0aab3 JB |
215 | struct fbsd_corefile_thread_data thread_args; |
216 | char *note_data = NULL; | |
a904c024 | 217 | Elf_Internal_Ehdr *i_ehdrp; |
20a0aab3 | 218 | struct thread_info *curr_thr, *signalled_thr, *thr; |
a904c024 AA |
219 | |
220 | /* Put a "FreeBSD" label in the ELF header. */ | |
221 | i_ehdrp = elf_elfheader (obfd); | |
222 | i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; | |
223 | ||
224 | gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); | |
225 | ||
a904c024 AA |
226 | if (get_exec_file (0)) |
227 | { | |
228 | const char *fname = lbasename (get_exec_file (0)); | |
229 | char *psargs = xstrdup (fname); | |
230 | ||
231 | if (get_inferior_args ()) | |
232 | psargs = reconcat (psargs, psargs, " ", get_inferior_args (), | |
233 | (char *) NULL); | |
234 | ||
235 | note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, | |
236 | fname, psargs); | |
237 | } | |
238 | ||
20a0aab3 JB |
239 | /* Thread register information. */ |
240 | TRY | |
241 | { | |
242 | update_thread_list (); | |
243 | } | |
244 | CATCH (e, RETURN_MASK_ERROR) | |
245 | { | |
246 | exception_print (gdb_stderr, e); | |
247 | } | |
248 | END_CATCH | |
249 | ||
250 | /* Like the kernel, prefer dumping the signalled thread first. | |
251 | "First thread" is what tools use to infer the signalled thread. | |
252 | In case there's more than one signalled thread, prefer the | |
253 | current thread, if it is signalled. */ | |
254 | curr_thr = inferior_thread (); | |
255 | if (curr_thr->suspend.stop_signal != GDB_SIGNAL_0) | |
256 | signalled_thr = curr_thr; | |
257 | else | |
258 | { | |
259 | signalled_thr = iterate_over_threads (find_signalled_thread, NULL); | |
260 | if (signalled_thr == NULL) | |
261 | signalled_thr = curr_thr; | |
262 | } | |
263 | ||
264 | thread_args.gdbarch = gdbarch; | |
265 | thread_args.obfd = obfd; | |
266 | thread_args.note_data = note_data; | |
267 | thread_args.note_size = note_size; | |
268 | thread_args.stop_signal = signalled_thr->suspend.stop_signal; | |
269 | ||
270 | fbsd_corefile_thread (signalled_thr, &thread_args); | |
271 | ALL_NON_EXITED_THREADS (thr) | |
272 | { | |
273 | if (thr == signalled_thr) | |
274 | continue; | |
275 | if (ptid_get_pid (thr->ptid) != ptid_get_pid (inferior_ptid)) | |
276 | continue; | |
277 | ||
278 | fbsd_corefile_thread (thr, &thread_args); | |
279 | } | |
280 | ||
281 | note_data = thread_args.note_data; | |
282 | ||
a904c024 AA |
283 | return note_data; |
284 | } | |
285 | ||
286 | /* To be called from GDB_OSABI_FREEBSD_ELF handlers. */ | |
287 | ||
288 | void | |
289 | fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | |
290 | { | |
79117428 JB |
291 | set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str); |
292 | set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name); | |
a904c024 AA |
293 | set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes); |
294 | } |