]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/i386bsd-nat.c
* sparc64nbsd-tdep.c: Include "objfiles.h".
[thirdparty/binutils-gdb.git] / gdb / i386bsd-nat.c
CommitLineData
e6031aeb 1/* Native-dependent code for modern i386 BSD's.
3f63813d
MK
2
3 Copyright 2000, 2001, 2002, 2003, 2004 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
9 the Free Software Foundation; either version 2 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, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22#include "defs.h"
23#include "inferior.h"
4e052eda 24#include "regcache.h"
e6031aeb 25
0afdd437 26#include "gdb_assert.h"
b7247919
MK
27#include <signal.h>
28#include <stddef.h>
e6031aeb
MK
29#include <sys/types.h>
30#include <sys/ptrace.h>
31#include <machine/reg.h>
32#include <machine/frame.h>
33
57976e88 34#include "i386-tdep.h"
1fc7d519 35#include "i387-tdep.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
131void
283accbc 132fetch_inferior_registers (int regnum)
e6031aeb 133{
283accbc 134 if (regnum == -1 || GETREGS_SUPPLIES (regnum))
7e89e357 135 {
6cfb2041 136 struct reg regs;
7e89e357
JT
137
138 if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 139 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
7e89e357 140 perror_with_name ("Couldn't get registers");
e6031aeb 141
6cfb2041 142 i386bsd_supply_gregset (current_regcache, &regs);
283accbc 143 if (regnum != -1)
7e89e357
JT
144 return;
145 }
e6031aeb 146
283accbc 147 if (regnum == -1 || regnum >= I386_ST0_REGNUM)
e6031aeb 148 {
6cfb2041 149 struct fpreg fpregs;
7e89e357
JT
150#ifdef HAVE_PT_GETXMMREGS
151 char xmmregs[512];
152
a144416f
MK
153 if (have_ptrace_xmmregs != 0
154 && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
9f8e0089 155 (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
7e89e357
JT
156 {
157 have_ptrace_xmmregs = 1;
41d041d6 158 i387_supply_fxsave (current_regcache, -1, xmmregs);
7e89e357
JT
159 }
160 else
161 {
162 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 163 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
7e89e357 164 perror_with_name ("Couldn't get floating point status");
e6031aeb 165
41d041d6 166 i387_supply_fsave (current_regcache, -1, &fpregs);
7e89e357
JT
167 }
168#else
39f77062 169 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 170 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e6031aeb
MK
171 perror_with_name ("Couldn't get floating point status");
172
41d041d6 173 i387_supply_fsave (current_regcache, -1, &fpregs);
7e89e357 174#endif
e6031aeb 175 }
b051bfa4 176}
e6031aeb 177
283accbc 178/* Store register REGNUM back into the inferior. If REGNUM is -1, do
e6031aeb
MK
179 this for all registers (including the floating point registers). */
180
181void
283accbc 182store_inferior_registers (int regnum)
e6031aeb 183{
283accbc 184 if (regnum == -1 || GETREGS_SUPPLIES (regnum))
7e89e357 185 {
6cfb2041 186 struct reg regs;
7e89e357
JT
187
188 if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 189 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
7e89e357 190 perror_with_name ("Couldn't get registers");
e6031aeb 191
6cfb2041 192 i386bsd_collect_gregset (current_regcache, &regs, regnum);
e6031aeb 193
7e89e357 194 if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 195 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
7e89e357
JT
196 perror_with_name ("Couldn't write registers");
197
283accbc 198 if (regnum != -1)
7e89e357
JT
199 return;
200 }
e6031aeb 201
283accbc 202 if (regnum == -1 || regnum >= I386_ST0_REGNUM)
e6031aeb 203 {
6cfb2041 204 struct fpreg fpregs;
7e89e357
JT
205#ifdef HAVE_PT_GETXMMREGS
206 char xmmregs[512];
e6031aeb 207
a144416f
MK
208 if (have_ptrace_xmmregs != 0
209 && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
9f8e0089 210 (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
7e89e357
JT
211 {
212 have_ptrace_xmmregs = 1;
213
283accbc 214 i387_collect_fxsave (current_regcache, regnum, xmmregs);
e6031aeb 215
7e89e357 216 if (ptrace (PT_SETXMMREGS, PIDGET (inferior_ptid),
9f8e0089 217 (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
7e89e357
JT
218 perror_with_name ("Couldn't write XMM registers");
219 }
220 else
221 {
222 have_ptrace_xmmregs = 0;
223#endif
224 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 225 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
7e89e357
JT
226 perror_with_name ("Couldn't get floating point status");
227
283accbc 228 i387_collect_fsave (current_regcache, regnum, &fpregs);
f5b1afdf 229
7e89e357 230 if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 231 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
7e89e357
JT
232 perror_with_name ("Couldn't write floating point status");
233#ifdef HAVE_PT_GETXMMREGS
234 }
235#endif
e6031aeb
MK
236 }
237}
238\f
239
0afdd437
MK
240/* Support for debug registers. */
241
242#ifdef HAVE_PT_GETDBREGS
243
244/* Not all versions of FreeBSD/i386 that support the debug registers
245 have this macro. */
246#ifndef DBREG_DRX
247#define DBREG_DRX(d, x) ((&d->dr0)[x])
248#endif
249
250static void
251i386bsd_dr_set (int regnum, unsigned int value)
252{
253 struct dbreg dbregs;
254
39f77062 255 if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
9f8e0089 256 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
0afdd437
MK
257 perror_with_name ("Couldn't get debug registers");
258
259 /* For some mysterious reason, some of the reserved bits in the
260 debug control register get set. Mask these off, otherwise the
261 ptrace call below will fail. */
afdb036a 262 DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
0afdd437
MK
263
264 DBREG_DRX ((&dbregs), regnum) = value;
265
39f77062 266 if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
9f8e0089 267 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
0afdd437
MK
268 perror_with_name ("Couldn't write debug registers");
269}
270
271void
272i386bsd_dr_set_control (unsigned long control)
273{
274 i386bsd_dr_set (7, control);
275}
276
277void
278i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
279{
280 gdb_assert (regnum >= 0 && regnum <= 4);
281
282 i386bsd_dr_set (regnum, addr);
283}
284
285void
286i386bsd_dr_reset_addr (int regnum)
287{
288 gdb_assert (regnum >= 0 && regnum <= 4);
289
290 i386bsd_dr_set (regnum, 0);
291}
292
293unsigned long
294i386bsd_dr_get_status (void)
295{
296 struct dbreg dbregs;
297
298 /* FIXME: kettenis/2001-03-31: Calling perror_with_name if the
299 ptrace call fails breaks debugging remote targets. The correct
300 way to fix this is to add the hardware breakpoint and watchpoint
b7247919 301 stuff to the target vector. For now, just return zero if the
0afdd437 302 ptrace call fails. */
39f77062 303 if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
9f8e0089 304 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
0afdd437
MK
305#if 0
306 perror_with_name ("Couldn't read debug registers");
307#else
308 return 0;
309#endif
310
afdb036a 311 return DBREG_DRX ((&dbregs), 6);
0afdd437
MK
312}
313
314#endif /* PT_GETDBREGS */
315\f
316
e6031aeb
MK
317/* Support for the user struct. */
318
283accbc 319/* Return the address register REGNUM. BLOCKEND is the value of
e6031aeb
MK
320 u.u_ar0, which should point to the registers. */
321
322CORE_ADDR
283accbc 323register_u_addr (CORE_ADDR blockend, int regnum)
e6031aeb 324{
6cfb2041
MK
325 gdb_assert (regnum >= 0 && regnum < ARRAY_SIZE (i386bsd_r_reg_offset));
326
327 return blockend + i386bsd_r_reg_offset[regnum];
e6031aeb
MK
328}
329
330#include <sys/param.h>
331#include <sys/user.h>
332
333/* Return the size of the user struct. */
334
335int
336kernel_u_size (void)
337{
338 return (sizeof (struct user));
339}
b7247919 340\f
b7247919
MK
341void
342_initialize_i386bsd_nat (void)
343{
a3386186 344 int offset;
8201327c 345
b7247919
MK
346 /* To support the recognition of signal handlers, i386bsd-tdep.c
347 hardcodes some constants. Inclusion of this file means that we
348 are compiling a native debugger, which means that we can use the
349 system header files and sysctl(3) to get at the relevant
350 information. */
351
8201327c 352#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
a3386186
MK
353#define SC_REG_OFFSET i386fbsd4_sc_reg_offset
354#elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
a3386186 355#define SC_REG_OFFSET i386fbsd_sc_reg_offset
005328e3 356#elif defined (NetBSD) || defined (__NetBSD_Version__)
a3386186 357#define SC_REG_OFFSET i386nbsd_sc_reg_offset
005328e3 358#elif defined (OpenBSD)
a3386186 359#define SC_REG_OFFSET i386obsd_sc_reg_offset
8201327c
MK
360#endif
361
bbe06c74
MK
362#ifdef SC_REG_OFFSET
363
a3386186
MK
364 /* We only check the program counter, stack pointer and frame
365 pointer since these members of `struct sigcontext' are essential
366 for providing backtraces. More checks could be added, but would
367 involve adding configure checks for the appropriate structure
368 members, since older BSD's don't provide all of them. */
369
370#define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
371#define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
372#define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
373
b7247919
MK
374 /* Override the default value for the offset of the program counter
375 in the sigcontext structure. */
a3386186 376 offset = offsetof (struct sigcontext, sc_pc);
8201327c 377
a3386186 378 if (SC_PC_OFFSET != offset)
8201327c
MK
379 {
380 warning ("\
381offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
a3386186
MK
382Please report this to <bug-gdb@gnu.org>.",
383 offset, SC_PC_OFFSET);
8201327c
MK
384 }
385
a3386186 386 SC_PC_OFFSET = offset;
6bff26de
MK
387
388 /* Likewise for the stack pointer. */
a3386186 389 offset = offsetof (struct sigcontext, sc_sp);
6bff26de 390
a3386186 391 if (SC_SP_OFFSET != offset)
6bff26de
MK
392 {
393 warning ("\
394offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
395Please report this to <bug-gdb@gnu.org>.",
a3386186
MK
396 offset, SC_SP_OFFSET);
397 }
398
399 SC_SP_OFFSET = offset;
400
401 /* And the frame pointer. */
402 offset = offsetof (struct sigcontext, sc_fp);
403
404 if (SC_FP_OFFSET != offset)
405 {
406 warning ("\
407offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
408Please report this to <bug-gdb@gnu.org>.",
409 offset, SC_FP_OFFSET);
6bff26de
MK
410 }
411
a3386186 412 SC_FP_OFFSET = offset;
bbe06c74
MK
413
414#endif /* SC_REG_OFFSET */
b7247919 415}