GDB (xrefs)
/tmp/gdb-7.10/gdb/i386bsd-nat.c
Go to the documentation of this file.
1 /* Native-dependent code for modern i386 BSD's.
2 
3  Copyright (C) 2000-2015 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 
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 
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 = 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
113  void *gregs, int regnum)
114 {
115  char *regs = 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
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, ptid_get_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  char *xstateregs;
161 
162  xstateregs = alloca (i386bsd_xsave_len);
163  if (ptrace (PT_GETXSTATE, ptid_get_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, ptid_get_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, ptid_get_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
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, ptid_get_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, ptid_get_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  char *xstateregs;
231 
232  xstateregs = alloca (i386bsd_xsave_len);
233  if (ptrace (PT_GETXSTATE, ptid_get_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, ptid_get_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, ptid_get_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, ptid_get_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, ptid_get_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, ptid_get_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 *
283 {
284  struct target_ops *t;
285 
286  t = inf_ptrace_target ();
289  return t;
290 }
291 
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, ptid_get_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, ptid_get_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, ptid_get_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
358 {
359  return i386bsd_dr_get (inferior_ptid, 6);
360 }
361 
362 unsigned long
364 {
365  return i386bsd_dr_get (inferior_ptid, 7);
366 }
367 
368 #endif /* PT_GETDBREGS */
369 
370 
371 /* Provide a prototype to silence -Wmissing-prototypes. */
372 void _initialize_i386bsd_nat (void);
373 
374 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 }
struct target_ops * i386bsd_target(void)
Definition: i386bsd-nat.c:282
void i387_collect_fsave(const struct regcache *regcache, int regnum, void *fsave)
Definition: i387-tdep.c:502
#define GETREGS_SUPPLIES(regnum)
Definition: i386bsd-nat.c:76
static void i386bsd_collect_gregset(const struct regcache *regcache, void *gregs, int regnum)
Definition: i386bsd-nat.c:112
bfd_vma CORE_ADDR
Definition: common-types.h:41
void warning(const char *fmt,...)
Definition: errors.c:26
void i387_supply_fxsave(struct regcache *regcache, int regnum, const void *fxsave)
Definition: i387-tdep.c:595
void _initialize_i386bsd_nat(void)
Definition: i386bsd-nat.c:375
static void i386bsd_store_inferior_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
Definition: i386bsd-nat.c:199
void i387_supply_fsave(struct regcache *regcache, int regnum, const void *fsave)
Definition: i387-tdep.c:447
#define _(String)
Definition: gdb_locale.h:40
struct target_ops * inf_ptrace_target(void)
Definition: inf-ptrace.c:668
PTRACE_TYPE_RET ptrace()
Definition: ptid.h:35
static void i386bsd_fetch_inferior_registers(struct target_ops *ops, struct regcache *regcache, int regnum)
Definition: i386bsd-nat.c:134
void i387_collect_fxsave(const struct regcache *regcache, int regnum, void *fxsave)
Definition: i387-tdep.c:678
#define REG_OFFSET(member)
Definition: i386bsd-nat.c:42
#define gdb_assert(expr)
Definition: gdb_assert.h:33
CORE_ADDR i386bsd_dr_get_addr(int regnum)
int regnum
Definition: aarch64-tdep.c:69
static int i386bsd_r_reg_offset[]
Definition: i386bsd-nat.c:47
Definition: regdef.h:22
void i387_collect_xsave(const struct regcache *regcache, int regnum, void *xsave, int gcore)
Definition: i387-tdep.c:1267
int ptid_get_pid(ptid_t ptid)
Definition: ptid.c:52
void i386bsd_dr_set_control(unsigned long control)
void i386bsd_dr_set_addr(int regnum, CORE_ADDR addr)
void(* to_fetch_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_IGNORE()
Definition: target.h:472
void void void void void void void void void perror_with_name(const char *string) ATTRIBUTE_NORETURN
Definition: utils.c:979
unsigned long i386bsd_dr_get_status(void)
ptid_t inferior_ptid
Definition: infcmd.c:124
int offset
Definition: agent.c:65
size_t i386bsd_xsave_len
void regcache_raw_supply(struct regcache *regcache, int regnum, const void *buf)
Definition: regcache.c:1041
void regcache_raw_collect(const struct regcache *regcache, int regnum, void *buf)
Definition: regcache.c:1071
#define PTRACE_TYPE_ARG3
Definition: config.h:658
void i387_supply_xsave(struct regcache *regcache, int regnum, const void *xsave)
Definition: i387-tdep.c:894
unsigned long i386bsd_dr_get_control(void)
void(* to_store_registers)(struct target_ops *, struct regcache *, int) TARGET_DEFAULT_NORETURN(noprocess())
Definition: target.h:474
static void i386bsd_supply_gregset(struct regcache *regcache, const void *gregs)
Definition: i386bsd-nat.c:93