* config/djgpp/fnchange.lst: Add entries for ppcobsd-nat.c and
[deliverable/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
34#ifdef HAVE_SYS_PROCFS_H
35#include <sys/procfs.h>
36#endif
37
38#ifndef HAVE_GREGSET_T
39typedef struct reg gregset_t;
40#endif
41
42#ifndef HAVE_FPREGSET_T
43typedef struct fpreg fpregset_t;
44#endif
45
b051bfa4 46#include "gregset.h"
57976e88 47#include "i386-tdep.h"
b051bfa4
MK
48\f
49
e6031aeb
MK
50/* In older BSD versions we cannot get at some of the segment
51 registers. FreeBSD for example didn't support the %fs and %gs
52 registers until the 3.0 release. We have autoconf checks for their
53 presence, and deal gracefully with their absence. */
54
55/* Registers we shouldn't try to fetch. */
3f63813d 56#undef CANNOT_FETCH_REGISTER
283accbc 57#define CANNOT_FETCH_REGISTER(regnum) cannot_fetch_register (regnum)
e6031aeb
MK
58
59/* Registers we shouldn't try to store. */
3f63813d 60#undef CANNOT_STORE_REGISTER
283accbc 61#define CANNOT_STORE_REGISTER(regnum) cannot_fetch_register (regnum)
e6031aeb
MK
62
63/* Offset to the gregset_t location where REG is stored. */
64#define REG_OFFSET(reg) offsetof (gregset_t, reg)
65
283accbc
MK
66/* At reg_offset[REGNUM] you'll find the offset to the gregset_t
67 location where the GDB register REGNUM is stored. Unsupported
e6031aeb
MK
68 registers are marked with `-1'. */
69static int reg_offset[] =
70{
71 REG_OFFSET (r_eax),
72 REG_OFFSET (r_ecx),
73 REG_OFFSET (r_edx),
2c48bda3 74 REG_OFFSET (r_ebx),
e6031aeb
MK
75 REG_OFFSET (r_esp),
76 REG_OFFSET (r_ebp),
77 REG_OFFSET (r_esi),
78 REG_OFFSET (r_edi),
79 REG_OFFSET (r_eip),
80 REG_OFFSET (r_eflags),
81 REG_OFFSET (r_cs),
82 REG_OFFSET (r_ss),
83 REG_OFFSET (r_ds),
84 REG_OFFSET (r_es),
422ea4b8 85#ifdef HAVE_STRUCT_REG_R_FS
e6031aeb
MK
86 REG_OFFSET (r_fs),
87#else
88 -1,
89#endif
422ea4b8 90#ifdef HAVE_STRUCT_REG_R_GS
e6031aeb
MK
91 REG_OFFSET (r_gs)
92#else
93 -1
94#endif
95};
96
283accbc 97#define REG_ADDR(regset, regnum) ((char *) (regset) + reg_offset[regnum])
e6031aeb 98
7e89e357 99/* Macro to determine if a register is fetched with PT_GETREGS. */
283accbc
MK
100#define GETREGS_SUPPLIES(regnum) \
101 ((0 <= (regnum) && (regnum) <= 15))
7e89e357
JT
102
103#ifdef HAVE_PT_GETXMMREGS
104/* Set to 1 if the kernel supports PT_GETXMMREGS. Initialized to -1
105 so that we try PT_GETXMMREGS the first time around. */
106static int have_ptrace_xmmregs = -1;
107#endif
108
283accbc 109/* Return nonzero if we shouldn't try to fetch register REGNUM. */
e6031aeb
MK
110
111static int
283accbc 112cannot_fetch_register (int regnum)
e6031aeb 113{
283accbc 114 return (reg_offset[regnum] == -1);
e6031aeb
MK
115}
116\f
117
118/* Transfering the registers between GDB, inferiors and core files. */
119
ad2a4d09 120/* Fill GDB's register array with the general-purpose register values
e6031aeb
MK
121 in *GREGSETP. */
122
123void
124supply_gregset (gregset_t *gregsetp)
125{
e6031aeb
MK
126 int i;
127
57976e88 128 for (i = 0; i < I386_NUM_GREGS; i++)
e6031aeb
MK
129 {
130 if (CANNOT_FETCH_REGISTER (i))
b051bfa4 131 supply_register (i, NULL);
e6031aeb
MK
132 else
133 supply_register (i, REG_ADDR (gregsetp, i));
134 }
135}
136
283accbc
MK
137/* Fill register REGNUM (if it is a general-purpose register) in
138 *GREGSETPS with the value in GDB's register array. If REGNUM is -1,
e6031aeb
MK
139 do this for all registers. */
140
141void
283accbc 142fill_gregset (gregset_t *gregsetp, int regnum)
e6031aeb
MK
143{
144 int i;
145
57976e88 146 for (i = 0; i < I386_NUM_GREGS; i++)
283accbc 147 if ((regnum == -1 || regnum == i) && ! CANNOT_STORE_REGISTER (i))
7e89e357 148 regcache_collect (i, REG_ADDR (gregsetp, i));
e6031aeb
MK
149}
150
e750d25e 151#include "i387-tdep.h"
e6031aeb
MK
152
153/* Fill GDB's register array with the floating-point register values
154 in *FPREGSETP. */
155
156void
157supply_fpregset (fpregset_t *fpregsetp)
158{
41d041d6 159 i387_supply_fsave (current_regcache, -1, fpregsetp);
e6031aeb
MK
160}
161
283accbc
MK
162/* Fill register REGNUM (if it is a floating-point register) in
163 *FPREGSETP with the value in GDB's register array. If REGNUM is
164 -1, do this for all registers. */
e6031aeb
MK
165
166void
283accbc 167fill_fpregset (fpregset_t *fpregsetp, int regnum)
e6031aeb 168{
283accbc 169 i387_collect_fsave (current_regcache, regnum, fpregsetp);
e6031aeb
MK
170}
171
283accbc 172/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
e6031aeb
MK
173 for all registers (including the floating point registers). */
174
175void
283accbc 176fetch_inferior_registers (int regnum)
e6031aeb 177{
283accbc 178 if (regnum == -1 || GETREGS_SUPPLIES (regnum))
7e89e357
JT
179 {
180 gregset_t gregs;
181
182 if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
183 (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
184 perror_with_name ("Couldn't get registers");
e6031aeb 185
7e89e357 186 supply_gregset (&gregs);
283accbc 187 if (regnum != -1)
7e89e357
JT
188 return;
189 }
e6031aeb 190
283accbc 191 if (regnum == -1 || regnum >= I386_ST0_REGNUM)
e6031aeb
MK
192 {
193 fpregset_t fpregs;
7e89e357
JT
194#ifdef HAVE_PT_GETXMMREGS
195 char xmmregs[512];
196
a144416f
MK
197 if (have_ptrace_xmmregs != 0
198 && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
199 (PTRACE_ARG3_TYPE) xmmregs, 0) == 0)
7e89e357
JT
200 {
201 have_ptrace_xmmregs = 1;
41d041d6 202 i387_supply_fxsave (current_regcache, -1, xmmregs);
7e89e357
JT
203 }
204 else
205 {
206 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
207 (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
208 perror_with_name ("Couldn't get floating point status");
e6031aeb 209
41d041d6 210 i387_supply_fsave (current_regcache, -1, &fpregs);
7e89e357
JT
211 }
212#else
39f77062 213 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
e6031aeb
MK
214 (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
215 perror_with_name ("Couldn't get floating point status");
216
41d041d6 217 i387_supply_fsave (current_regcache, -1, &fpregs);
7e89e357 218#endif
e6031aeb 219 }
b051bfa4 220}
e6031aeb 221
283accbc 222/* Store register REGNUM back into the inferior. If REGNUM is -1, do
e6031aeb
MK
223 this for all registers (including the floating point registers). */
224
225void
283accbc 226store_inferior_registers (int regnum)
e6031aeb 227{
283accbc 228 if (regnum == -1 || GETREGS_SUPPLIES (regnum))
7e89e357
JT
229 {
230 gregset_t gregs;
231
232 if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
233 (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
234 perror_with_name ("Couldn't get registers");
e6031aeb 235
283accbc 236 fill_gregset (&gregs, regnum);
e6031aeb 237
7e89e357
JT
238 if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
239 (PTRACE_ARG3_TYPE) &gregs, 0) == -1)
240 perror_with_name ("Couldn't write registers");
241
283accbc 242 if (regnum != -1)
7e89e357
JT
243 return;
244 }
e6031aeb 245
283accbc 246 if (regnum == -1 || regnum >= I386_ST0_REGNUM)
e6031aeb
MK
247 {
248 fpregset_t fpregs;
7e89e357
JT
249#ifdef HAVE_PT_GETXMMREGS
250 char xmmregs[512];
e6031aeb 251
a144416f
MK
252 if (have_ptrace_xmmregs != 0
253 && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
254 (PTRACE_ARG3_TYPE) xmmregs, 0) == 0)
7e89e357
JT
255 {
256 have_ptrace_xmmregs = 1;
257
283accbc 258 i387_collect_fxsave (current_regcache, regnum, xmmregs);
e6031aeb 259
7e89e357
JT
260 if (ptrace (PT_SETXMMREGS, PIDGET (inferior_ptid),
261 (PTRACE_ARG3_TYPE) xmmregs, 0) == -1)
262 perror_with_name ("Couldn't write XMM registers");
263 }
264 else
265 {
266 have_ptrace_xmmregs = 0;
267#endif
268 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
269 (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
270 perror_with_name ("Couldn't get floating point status");
271
283accbc 272 i387_collect_fsave (current_regcache, regnum, &fpregs);
f5b1afdf 273
7e89e357
JT
274 if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
275 (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
276 perror_with_name ("Couldn't write floating point status");
277#ifdef HAVE_PT_GETXMMREGS
278 }
279#endif
e6031aeb
MK
280 }
281}
282\f
283
0afdd437
MK
284/* Support for debug registers. */
285
286#ifdef HAVE_PT_GETDBREGS
287
288/* Not all versions of FreeBSD/i386 that support the debug registers
289 have this macro. */
290#ifndef DBREG_DRX
291#define DBREG_DRX(d, x) ((&d->dr0)[x])
292#endif
293
294static void
295i386bsd_dr_set (int regnum, unsigned int value)
296{
297 struct dbreg dbregs;
298
39f77062
KB
299 if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
300 (PTRACE_ARG3_TYPE) &dbregs, 0) == -1)
0afdd437
MK
301 perror_with_name ("Couldn't get debug registers");
302
303 /* For some mysterious reason, some of the reserved bits in the
304 debug control register get set. Mask these off, otherwise the
305 ptrace call below will fail. */
afdb036a 306 DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
0afdd437
MK
307
308 DBREG_DRX ((&dbregs), regnum) = value;
309
39f77062
KB
310 if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
311 (PTRACE_ARG3_TYPE) &dbregs, 0) == -1)
0afdd437
MK
312 perror_with_name ("Couldn't write debug registers");
313}
314
315void
316i386bsd_dr_set_control (unsigned long control)
317{
318 i386bsd_dr_set (7, control);
319}
320
321void
322i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
323{
324 gdb_assert (regnum >= 0 && regnum <= 4);
325
326 i386bsd_dr_set (regnum, addr);
327}
328
329void
330i386bsd_dr_reset_addr (int regnum)
331{
332 gdb_assert (regnum >= 0 && regnum <= 4);
333
334 i386bsd_dr_set (regnum, 0);
335}
336
337unsigned long
338i386bsd_dr_get_status (void)
339{
340 struct dbreg dbregs;
341
342 /* FIXME: kettenis/2001-03-31: Calling perror_with_name if the
343 ptrace call fails breaks debugging remote targets. The correct
344 way to fix this is to add the hardware breakpoint and watchpoint
b7247919 345 stuff to the target vector. For now, just return zero if the
0afdd437 346 ptrace call fails. */
39f77062
KB
347 if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
348 (PTRACE_ARG3_TYPE) & dbregs, 0) == -1)
0afdd437
MK
349#if 0
350 perror_with_name ("Couldn't read debug registers");
351#else
352 return 0;
353#endif
354
afdb036a 355 return DBREG_DRX ((&dbregs), 6);
0afdd437
MK
356}
357
358#endif /* PT_GETDBREGS */
359\f
360
e6031aeb
MK
361/* Support for the user struct. */
362
283accbc 363/* Return the address register REGNUM. BLOCKEND is the value of
e6031aeb
MK
364 u.u_ar0, which should point to the registers. */
365
366CORE_ADDR
283accbc 367register_u_addr (CORE_ADDR blockend, int regnum)
e6031aeb 368{
283accbc 369 return (CORE_ADDR) REG_ADDR (blockend, regnum);
e6031aeb
MK
370}
371
372#include <sys/param.h>
373#include <sys/user.h>
374
375/* Return the size of the user struct. */
376
377int
378kernel_u_size (void)
379{
380 return (sizeof (struct user));
381}
b7247919 382\f
b7247919
MK
383void
384_initialize_i386bsd_nat (void)
385{
a3386186 386 int offset;
8201327c 387
b7247919
MK
388 /* To support the recognition of signal handlers, i386bsd-tdep.c
389 hardcodes some constants. Inclusion of this file means that we
390 are compiling a native debugger, which means that we can use the
391 system header files and sysctl(3) to get at the relevant
392 information. */
393
8201327c 394#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
a3386186
MK
395#define SC_REG_OFFSET i386fbsd4_sc_reg_offset
396#elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
a3386186 397#define SC_REG_OFFSET i386fbsd_sc_reg_offset
005328e3 398#elif defined (NetBSD) || defined (__NetBSD_Version__)
a3386186 399#define SC_REG_OFFSET i386nbsd_sc_reg_offset
005328e3 400#elif defined (OpenBSD)
a3386186 401#define SC_REG_OFFSET i386obsd_sc_reg_offset
8201327c 402#else
a144416f 403#define SC_REG_OFFSET i386bsd_sc_reg_offset
8201327c
MK
404#endif
405
a3386186
MK
406 /* We only check the program counter, stack pointer and frame
407 pointer since these members of `struct sigcontext' are essential
408 for providing backtraces. More checks could be added, but would
409 involve adding configure checks for the appropriate structure
410 members, since older BSD's don't provide all of them. */
411
412#define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
413#define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
414#define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
415
b7247919
MK
416 /* Override the default value for the offset of the program counter
417 in the sigcontext structure. */
a3386186 418 offset = offsetof (struct sigcontext, sc_pc);
8201327c 419
a3386186 420 if (SC_PC_OFFSET != offset)
8201327c
MK
421 {
422 warning ("\
423offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
a3386186
MK
424Please report this to <bug-gdb@gnu.org>.",
425 offset, SC_PC_OFFSET);
8201327c
MK
426 }
427
a3386186 428 SC_PC_OFFSET = offset;
6bff26de
MK
429
430 /* Likewise for the stack pointer. */
a3386186 431 offset = offsetof (struct sigcontext, sc_sp);
6bff26de 432
a3386186 433 if (SC_SP_OFFSET != offset)
6bff26de
MK
434 {
435 warning ("\
436offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
437Please report this to <bug-gdb@gnu.org>.",
a3386186
MK
438 offset, SC_SP_OFFSET);
439 }
440
441 SC_SP_OFFSET = offset;
442
443 /* And the frame pointer. */
444 offset = offsetof (struct sigcontext, sc_fp);
445
446 if (SC_FP_OFFSET != offset)
447 {
448 warning ("\
449offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
450Please report this to <bug-gdb@gnu.org>.",
451 offset, SC_FP_OFFSET);
6bff26de
MK
452 }
453
a3386186 454 SC_FP_OFFSET = offset;
b7247919 455}
This page took 0.399764 seconds and 4 git commands to generate.