Set dynamic tag VMA and size from dynamic section when possible
[external/binutils.git] / gdb / i386bsd-nat.c
1 /* Native-dependent code for modern i386 BSD's.
2
3    Copyright (C) 2000-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 "inferior.h"
22 #include "regcache.h"
23
24 #include <signal.h>
25 #include <sys/types.h>
26 #include <sys/ptrace.h>
27 #include <machine/reg.h>
28 #include <machine/frame.h>
29
30 #include "i386-tdep.h"
31 #include "i387-tdep.h"
32 #include "i386bsd-nat.h"
33 #include "inf-ptrace.h"
34 \f
35
36 /* In older BSD versions we cannot get at some of the segment
37    registers.  FreeBSD for example didn't support the %fs and %gs
38    registers until the 3.0 release.  We have autoconf checks for their
39    presence, and deal gracefully with their absence.  */
40
41 /* Offset in `struct reg' where MEMBER is stored.  */
42 #define REG_OFFSET(member) offsetof (struct reg, member)
43
44 /* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct
45    reg' where the GDB register REGNUM is stored.  Unsupported
46    registers are marked with `-1'.  */
47 static int i386bsd_r_reg_offset[] =
48 {
49   REG_OFFSET (r_eax),
50   REG_OFFSET (r_ecx),
51   REG_OFFSET (r_edx),
52   REG_OFFSET (r_ebx),
53   REG_OFFSET (r_esp),
54   REG_OFFSET (r_ebp),
55   REG_OFFSET (r_esi),
56   REG_OFFSET (r_edi),
57   REG_OFFSET (r_eip),
58   REG_OFFSET (r_eflags),
59   REG_OFFSET (r_cs),
60   REG_OFFSET (r_ss),
61   REG_OFFSET (r_ds),
62   REG_OFFSET (r_es),
63 #ifdef HAVE_STRUCT_REG_R_FS
64   REG_OFFSET (r_fs),
65 #else
66   -1,
67 #endif
68 #ifdef HAVE_STRUCT_REG_R_GS
69   REG_OFFSET (r_gs)
70 #else
71   -1
72 #endif
73 };
74
75 /* Macro to determine if a register is fetched with PT_GETREGS.  */
76 #define GETREGS_SUPPLIES(regnum) \
77   ((0 <= (regnum) && (regnum) <= 15))
78
79 #ifdef HAVE_PT_GETXMMREGS
80 /* Set to 1 if the kernel supports PT_GETXMMREGS.  Initialized to -1
81    so that we try PT_GETXMMREGS the first time around.  */
82 static int have_ptrace_xmmregs = -1;
83 #endif
84
85 #ifdef PT_GETXSTATE_INFO
86 size_t i386bsd_xsave_len;
87 #endif
88 \f
89
90 /* Supply the general-purpose registers in GREGS, to REGCACHE.  */
91
92 static void
93 i386bsd_supply_gregset (struct regcache *regcache, const void *gregs)
94 {
95   const char *regs = (const char *) gregs;
96   int regnum;
97
98   for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++)
99     {
100       int offset = i386bsd_r_reg_offset[regnum];
101
102       if (offset != -1)
103         regcache_raw_supply (regcache, regnum, regs + offset);
104     }
105 }
106
107 /* Collect register REGNUM from REGCACHE and store its contents in
108    GREGS.  If REGNUM is -1, collect and store all appropriate
109    registers.  */
110
111 static void
112 i386bsd_collect_gregset (const struct regcache *regcache,
113                          void *gregs, int regnum)
114 {
115   char *regs = (char *) gregs;
116   int i;
117
118   for (i = 0; i < ARRAY_SIZE (i386bsd_r_reg_offset); i++)
119     {
120       if (regnum == -1 || regnum == i)
121         {
122           int offset = i386bsd_r_reg_offset[i];
123
124           if (offset != -1)
125             regcache_raw_collect (regcache, i, regs + offset);
126         }
127     }
128 }
129
130 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
131    for all registers (including the floating point registers).  */
132
133 static void
134 i386bsd_fetch_inferior_registers (struct target_ops *ops,
135                                   struct regcache *regcache, int regnum)
136 {
137   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
138     {
139       struct reg regs;
140
141       if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid),
142                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
143         perror_with_name (_("Couldn't get registers"));
144
145       i386bsd_supply_gregset (regcache, &regs);
146       if (regnum != -1)
147         return;
148     }
149
150   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
151     {
152       struct fpreg fpregs;
153 #ifdef HAVE_PT_GETXMMREGS
154       char xmmregs[512];
155 #endif
156
157 #ifdef PT_GETXSTATE_INFO
158       if (i386bsd_xsave_len != 0)
159         {
160           void *xstateregs;
161
162           xstateregs = alloca (i386bsd_xsave_len);
163           if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid),
164                       (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
165             perror_with_name (_("Couldn't get extended state status"));
166
167           i387_supply_xsave (regcache, -1, xstateregs);
168           return;
169         }
170 #endif
171       
172 #ifdef HAVE_PT_GETXMMREGS
173       if (have_ptrace_xmmregs != 0
174           && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid),
175                     (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
176         {
177           have_ptrace_xmmregs = 1;
178           i387_supply_fxsave (regcache, -1, xmmregs);
179         }
180       else
181         {
182           have_ptrace_xmmregs = 0;
183 #endif
184           if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid),
185                       (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
186             perror_with_name (_("Couldn't get floating point status"));
187
188           i387_supply_fsave (regcache, -1, &fpregs);
189 #ifdef HAVE_PT_GETXMMREGS
190         }
191 #endif
192     }
193 }
194
195 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
196    this for all registers (including the floating point registers).  */
197
198 static void
199 i386bsd_store_inferior_registers (struct target_ops *ops,
200                                   struct regcache *regcache, int regnum)
201 {
202   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
203     {
204       struct reg regs;
205
206       if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid),
207                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
208         perror_with_name (_("Couldn't get registers"));
209
210       i386bsd_collect_gregset (regcache, &regs, regnum);
211
212       if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid),
213                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
214         perror_with_name (_("Couldn't write registers"));
215
216       if (regnum != -1)
217         return;
218     }
219
220   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
221     {
222       struct fpreg fpregs;
223 #ifdef HAVE_PT_GETXMMREGS
224       char xmmregs[512];
225 #endif
226
227 #ifdef PT_GETXSTATE_INFO
228       if (i386bsd_xsave_len != 0)
229         {
230           void *xstateregs;
231
232           xstateregs = alloca (i386bsd_xsave_len);
233           if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid),
234                       (PTRACE_TYPE_ARG3) xstateregs, 0) == -1)
235             perror_with_name (_("Couldn't get extended state status"));
236
237           i387_collect_xsave (regcache, -1, xstateregs, 0);
238
239           if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid),
240                       (PTRACE_TYPE_ARG3) xstateregs, i386bsd_xsave_len) == -1)
241             perror_with_name (_("Couldn't write extended state status"));
242           return;
243         }
244 #endif
245
246 #ifdef HAVE_PT_GETXMMREGS
247       if (have_ptrace_xmmregs != 0
248           && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid),
249                     (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
250         {
251           have_ptrace_xmmregs = 1;
252
253           i387_collect_fxsave (regcache, regnum, xmmregs);
254
255           if (ptrace (PT_SETXMMREGS, get_ptrace_pid (inferior_ptid),
256                       (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
257             perror_with_name (_("Couldn't write XMM registers"));
258         }
259       else
260         {
261           have_ptrace_xmmregs = 0;
262 #endif
263           if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid),
264                       (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
265             perror_with_name (_("Couldn't get floating point status"));
266
267           i387_collect_fsave (regcache, regnum, &fpregs);
268
269           if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid),
270                       (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
271             perror_with_name (_("Couldn't write floating point status"));
272 #ifdef HAVE_PT_GETXMMREGS
273         }
274 #endif
275     }
276 }
277
278 /* Create a prototype *BSD/i386 target.  The client can override it
279    with local methods.  */
280
281 struct target_ops *
282 i386bsd_target (void)
283 {
284   struct target_ops *t;
285
286   t = inf_ptrace_target ();
287   t->to_fetch_registers = i386bsd_fetch_inferior_registers;
288   t->to_store_registers = i386bsd_store_inferior_registers;
289   return t;
290 }
291 \f
292
293 /* Support for debug registers.  */
294
295 #ifdef HAVE_PT_GETDBREGS
296
297 /* Not all versions of FreeBSD/i386 that support the debug registers
298    have this macro.  */
299 #ifndef DBREG_DRX
300 #define DBREG_DRX(d, x) ((&d->dr0)[x])
301 #endif
302
303 static unsigned long
304 i386bsd_dr_get (ptid_t ptid, int regnum)
305 {
306   struct dbreg dbregs;
307
308   if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid),
309               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
310     perror_with_name (_("Couldn't read debug registers"));
311
312   return DBREG_DRX ((&dbregs), regnum);
313 }
314
315 static void
316 i386bsd_dr_set (int regnum, unsigned int value)
317 {
318   struct dbreg dbregs;
319
320   if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid),
321               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
322     perror_with_name (_("Couldn't get debug registers"));
323
324   /* For some mysterious reason, some of the reserved bits in the
325      debug control register get set.  Mask these off, otherwise the
326      ptrace call below will fail.  */
327   DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
328
329   DBREG_DRX ((&dbregs), regnum) = value;
330
331   if (ptrace (PT_SETDBREGS, get_ptrace_pid (inferior_ptid),
332               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
333     perror_with_name (_("Couldn't write debug registers"));
334 }
335
336 void
337 i386bsd_dr_set_control (unsigned long control)
338 {
339   i386bsd_dr_set (7, control);
340 }
341
342 void
343 i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
344 {
345   gdb_assert (regnum >= 0 && regnum <= 4);
346
347   i386bsd_dr_set (regnum, addr);
348 }
349
350 CORE_ADDR
351 i386bsd_dr_get_addr (int regnum)
352 {
353   return i386bsd_dr_get (inferior_ptid, regnum);
354 }
355
356 unsigned long
357 i386bsd_dr_get_status (void)
358 {
359   return i386bsd_dr_get (inferior_ptid, 6);
360 }
361
362 unsigned long
363 i386bsd_dr_get_control (void)
364 {
365   return i386bsd_dr_get (inferior_ptid, 7);
366 }
367
368 #endif /* PT_GETDBREGS */
369 \f
370
371 /* Provide a prototype to silence -Wmissing-prototypes.  */
372 void _initialize_i386bsd_nat (void);
373
374 void
375 _initialize_i386bsd_nat (void)
376 {
377   int offset;
378
379   /* To support the recognition of signal handlers, i386bsd-tdep.c
380      hardcodes some constants.  Inclusion of this file means that we
381      are compiling a native debugger, which means that we can use the
382      system header files and sysctl(3) to get at the relevant
383      information.  */
384
385 #if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
386 #define SC_REG_OFFSET i386fbsd4_sc_reg_offset
387 #elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
388 #define SC_REG_OFFSET i386fbsd_sc_reg_offset
389 #elif defined (NetBSD) || defined (__NetBSD_Version__)
390 #define SC_REG_OFFSET i386nbsd_sc_reg_offset
391 #elif defined (OpenBSD)
392 #define SC_REG_OFFSET i386obsd_sc_reg_offset
393 #endif
394
395 #ifdef SC_REG_OFFSET
396
397   /* We only check the program counter, stack pointer and frame
398      pointer since these members of `struct sigcontext' are essential
399      for providing backtraces.  More checks could be added, but would
400      involve adding configure checks for the appropriate structure
401      members, since older BSD's don't provide all of them.  */
402
403 #define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
404 #define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
405 #define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
406
407   /* Override the default value for the offset of the program counter
408      in the sigcontext structure.  */
409   offset = offsetof (struct sigcontext, sc_pc);
410
411   if (SC_PC_OFFSET != offset)
412     {
413       warning (_("\
414 offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
415 Please report this to <bug-gdb@gnu.org>."), 
416                offset, SC_PC_OFFSET);
417     }
418
419   SC_PC_OFFSET = offset;
420
421   /* Likewise for the stack pointer.  */
422   offset = offsetof (struct sigcontext, sc_sp);
423
424   if (SC_SP_OFFSET != offset)
425     {
426       warning (_("\
427 offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
428 Please report this to <bug-gdb@gnu.org>."),
429                offset, SC_SP_OFFSET);
430     }
431
432   SC_SP_OFFSET = offset;
433
434   /* And the frame pointer.  */
435   offset = offsetof (struct sigcontext, sc_fp);
436
437   if (SC_FP_OFFSET != offset)
438     {
439       warning (_("\
440 offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
441 Please report this to <bug-gdb@gnu.org>."),
442                offset, SC_FP_OFFSET);
443     }
444
445   SC_FP_OFFSET = offset;
446
447 #endif /* SC_REG_OFFSET */
448 }