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