Set dynamic tag VMA and size from dynamic section when possible
[external/binutils.git] / gdb / fbsd-tdep.c
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 "gdbcore.h"
22 #include "inferior.h"
23 #include "regcache.h"
24 #include "regset.h"
25 #include "gdbthread.h"
26
27 #include "elf-bfd.h"
28 #include "fbsd-tdep.h"
29
30
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
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
105 /* Structure for passing information from
106    fbsd_collect_thread_registers via an iterator to
107    fbsd_collect_regset_section_cb. */
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;
115   unsigned long lwp;
116   enum gdb_signal stop_signal;
117   int abort_iteration;
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;
126   struct fbsd_collect_regset_section_cb_data *data
127     = (struct fbsd_collect_regset_section_cb_data *) cb_data;
128
129   if (data->abort_iteration)
130     return;
131
132   gdb_assert (regset->collect_regset);
133
134   buf = (char *) xmalloc (size);
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
140       (data->obfd, data->note_data, data->note_size, data->lwp,
141        gdb_signal_to_host (data->stop_signal), buf);
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);
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);
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 {
215   struct fbsd_corefile_thread_data thread_args;
216   char *note_data = NULL;
217   Elf_Internal_Ehdr *i_ehdrp;
218   struct thread_info *curr_thr, *signalled_thr, *thr;
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
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
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
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 {
291   set_gdbarch_core_pid_to_str (gdbarch, fbsd_core_pid_to_str);
292   set_gdbarch_core_thread_name (gdbarch, fbsd_core_thread_name);
293   set_gdbarch_make_corefile_notes (gdbarch, fbsd_make_corefile_notes);
294 }