xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/fbsd-tdep.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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 #include "xml-syscall.h"
28 
29 #include "elf-bfd.h"
30 #include "fbsd-tdep.h"
31 
32 
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 
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 
107 /* Structure for passing information from
108    fbsd_collect_thread_registers via an iterator to
109    fbsd_collect_regset_section_cb. */
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;
117   unsigned long lwp;
118   enum gdb_signal stop_signal;
119   int abort_iteration;
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;
128   struct fbsd_collect_regset_section_cb_data *data
129     = (struct fbsd_collect_regset_section_cb_data *) cb_data;
130 
131   if (data->abort_iteration)
132     return;
133 
134   gdb_assert (regset->collect_regset);
135 
136   buf = (char *) xmalloc (size);
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
142       (data->obfd, data->note_data, data->note_size, data->lwp,
143        gdb_signal_to_host (data->stop_signal), buf);
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);
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);
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 {
217   struct fbsd_corefile_thread_data thread_args;
218   char *note_data = NULL;
219   Elf_Internal_Ehdr *i_ehdrp;
220   struct thread_info *curr_thr, *signalled_thr, *thr;
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 
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 
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 
285   return note_data;
286 }
287 
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 
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 
337 /* To be called from GDB_OSABI_FREEBSD_ELF handlers. */
338 
339 void
340 fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
341 {
342   set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str);
343   set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name);
344   set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
345   set_gdbarch_print_auxv_entry (gdbarch, fbsd_print_auxv_entry);
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);
350 }
351