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