2005-01-12 H.J. Lu <hongjiu.lu@intel.com>
[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
57976e88 34#include "i386-tdep.h"
1fc7d519 35#include "i387-tdep.h"
9692934b
MK
36#include "i386bsd-nat.h"
37#include "inf-ptrace.h"
b051bfa4
MK
38\f
39
e6031aeb
MK
40/* In older BSD versions we cannot get at some of the segment
41 registers. FreeBSD for example didn't support the %fs and %gs
42 registers until the 3.0 release. We have autoconf checks for their
43 presence, and deal gracefully with their absence. */
44
6cfb2041
MK
45/* Offset in `struct reg' where MEMBER is stored. */
46#define REG_OFFSET(member) offsetof (struct reg, member)
e6031aeb 47
6cfb2041
MK
48/* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct
49 reg' where the GDB register REGNUM is stored. Unsupported
e6031aeb 50 registers are marked with `-1'. */
6cfb2041 51static int i386bsd_r_reg_offset[] =
e6031aeb
MK
52{
53 REG_OFFSET (r_eax),
54 REG_OFFSET (r_ecx),
55 REG_OFFSET (r_edx),
2c48bda3 56 REG_OFFSET (r_ebx),
e6031aeb
MK
57 REG_OFFSET (r_esp),
58 REG_OFFSET (r_ebp),
59 REG_OFFSET (r_esi),
60 REG_OFFSET (r_edi),
61 REG_OFFSET (r_eip),
62 REG_OFFSET (r_eflags),
63 REG_OFFSET (r_cs),
64 REG_OFFSET (r_ss),
65 REG_OFFSET (r_ds),
66 REG_OFFSET (r_es),
422ea4b8 67#ifdef HAVE_STRUCT_REG_R_FS
e6031aeb
MK
68 REG_OFFSET (r_fs),
69#else
70 -1,
71#endif
422ea4b8 72#ifdef HAVE_STRUCT_REG_R_GS
e6031aeb
MK
73 REG_OFFSET (r_gs)
74#else
75 -1
76#endif
77};
78
7e89e357 79/* Macro to determine if a register is fetched with PT_GETREGS. */
283accbc
MK
80#define GETREGS_SUPPLIES(regnum) \
81 ((0 <= (regnum) && (regnum) <= 15))
7e89e357
JT
82
83#ifdef HAVE_PT_GETXMMREGS
84/* Set to 1 if the kernel supports PT_GETXMMREGS. Initialized to -1
85 so that we try PT_GETXMMREGS the first time around. */
86static int have_ptrace_xmmregs = -1;
87#endif
e6031aeb
MK
88\f
89
6cfb2041 90/* Supply the general-purpose registers in GREGS, to REGCACHE. */
e6031aeb 91
1fc7d519 92static void
6cfb2041 93i386bsd_supply_gregset (struct regcache *regcache, const void *gregs)
e6031aeb 94{
6cfb2041 95 const char *regs = gregs;
feae6502 96 int regnum;
e6031aeb 97
6cfb2041 98 for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++)
e6031aeb 99 {
6cfb2041
MK
100 int offset = i386bsd_r_reg_offset[regnum];
101
102 if (offset != -1)
103 regcache_raw_supply (regcache, regnum, regs + offset);
e6031aeb
MK
104 }
105}
106
6cfb2041
MK
107/* Collect register REGNUM from REGCACHE and store its contents in
108 GREGS. If REGNUM is -1, collect and store all appropriate
109 registers. */
e6031aeb 110
1fc7d519 111static void
6cfb2041
MK
112i386bsd_collect_gregset (const struct regcache *regcache,
113 void *gregs, int regnum)
e6031aeb 114{
6cfb2041 115 char *regs = gregs;
e6031aeb
MK
116 int i;
117
6cfb2041
MK
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];
e6031aeb 123
6cfb2041
MK
124 if (offset != -1)
125 regcache_raw_collect (regcache, i, regs + offset);
126 }
127 }
128}
e6031aeb 129
283accbc 130/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
e6031aeb
MK
131 for all registers (including the floating point registers). */
132
9692934b
MK
133static void
134i386bsd_fetch_inferior_registers (int regnum)
e6031aeb 135{
283accbc 136 if (regnum == -1 || GETREGS_SUPPLIES (regnum))
7e89e357 137 {
6cfb2041 138 struct reg regs;
7e89e357
JT
139
140 if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
9f8e0089 141 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
7e89e357 142 perror_with_name ("Couldn't get registers");
e6031aeb 143
6cfb2041 144 i386bsd_supply_gregset (current_regcache, &regs);
283accbc 145 if (regnum != -1)
7e89e357
JT
146 return;
147 }
e6031aeb 148
283accbc 149 if (regnum == -1 || regnum >= I386_ST0_REGNUM)
e6031aeb 150 {
6cfb2041 151 struct fpreg fpregs;
7e89e357
JT
152#ifdef HAVE_PT_GETXMMREGS
153 char xmmregs[512];
154
a144416f
MK
155 if (have_ptrace_xmmregs != 0
156 && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
9f8e0089 157 (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
7e89e357
JT
158 {
159 have_ptrace_xmmregs = 1;
41d041d6 160 i387_supply_fxsave (current_regcache, -1, xmmregs);
7e89e357
JT
161 }
162 else
163 {
164 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 165 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
7e89e357 166 perror_with_name ("Couldn't get floating point status");
e6031aeb 167
41d041d6 168 i387_supply_fsave (current_regcache, -1, &fpregs);
7e89e357
JT
169 }
170#else
39f77062 171 if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
9f8e0089 172 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
e6031aeb
MK
173 perror_with_name ("Couldn't get floating point status");
174
41d041d6 175 i387_supply_fsave (current_regcache, -1, &fpregs);
7e89e357 176#endif
e6031aeb 177 }
b051bfa4 178}
e6031aeb 179
283accbc 180/* Store register REGNUM back into the inferior. If REGNUM is -1, do
e6031aeb
MK
181 this for all registers (including the floating point registers). */
182
9692934b
MK
183static void
184i386bsd_store_inferior_registers (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)
7e89e357 192 perror_with_name ("Couldn't get registers");
e6031aeb 193
6cfb2041 194 i386bsd_collect_gregset (current_regcache, &regs, regnum);
e6031aeb 195
7e89e357 196 if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
9f8e0089 197 (PTRACE_TYPE_ARG3) &regs, 0) == -1)
7e89e357
JT
198 perror_with_name ("Couldn't write registers");
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
283accbc 216 i387_collect_fxsave (current_regcache, regnum, xmmregs);
e6031aeb 217
7e89e357 218 if (ptrace (PT_SETXMMREGS, PIDGET (inferior_ptid),
9f8e0089 219 (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
7e89e357
JT
220 perror_with_name ("Couldn't write XMM registers");
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)
7e89e357
JT
228 perror_with_name ("Couldn't get floating point status");
229
283accbc 230 i387_collect_fsave (current_regcache, regnum, &fpregs);
f5b1afdf 231
7e89e357 232 if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
9f8e0089 233 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
7e89e357
JT
234 perror_with_name ("Couldn't write floating point status");
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
266static void
267i386bsd_dr_set (int regnum, unsigned int value)
268{
269 struct dbreg dbregs;
270
39f77062 271 if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
9f8e0089 272 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
0afdd437
MK
273 perror_with_name ("Couldn't get debug registers");
274
275 /* For some mysterious reason, some of the reserved bits in the
276 debug control register get set. Mask these off, otherwise the
277 ptrace call below will fail. */
afdb036a 278 DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
0afdd437
MK
279
280 DBREG_DRX ((&dbregs), regnum) = value;
281
39f77062 282 if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
9f8e0089 283 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
0afdd437
MK
284 perror_with_name ("Couldn't write debug registers");
285}
286
287void
288i386bsd_dr_set_control (unsigned long control)
289{
290 i386bsd_dr_set (7, control);
291}
292
293void
294i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
295{
296 gdb_assert (regnum >= 0 && regnum <= 4);
297
298 i386bsd_dr_set (regnum, addr);
299}
300
301void
302i386bsd_dr_reset_addr (int regnum)
303{
304 gdb_assert (regnum >= 0 && regnum <= 4);
305
306 i386bsd_dr_set (regnum, 0);
307}
308
309unsigned long
310i386bsd_dr_get_status (void)
311{
312 struct dbreg dbregs;
313
314 /* FIXME: kettenis/2001-03-31: Calling perror_with_name if the
315 ptrace call fails breaks debugging remote targets. The correct
316 way to fix this is to add the hardware breakpoint and watchpoint
b7247919 317 stuff to the target vector. For now, just return zero if the
0afdd437 318 ptrace call fails. */
39f77062 319 if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
9f8e0089 320 (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
0afdd437
MK
321#if 0
322 perror_with_name ("Couldn't read debug registers");
323#else
324 return 0;
325#endif
326
afdb036a 327 return DBREG_DRX ((&dbregs), 6);
0afdd437
MK
328}
329
330#endif /* PT_GETDBREGS */
331\f
332
e6031aeb
MK
333/* Support for the user struct. */
334
283accbc 335/* Return the address register REGNUM. BLOCKEND is the value of
e6031aeb
MK
336 u.u_ar0, which should point to the registers. */
337
338CORE_ADDR
283accbc 339register_u_addr (CORE_ADDR blockend, int regnum)
e6031aeb 340{
6cfb2041
MK
341 gdb_assert (regnum >= 0 && regnum < ARRAY_SIZE (i386bsd_r_reg_offset));
342
343 return blockend + i386bsd_r_reg_offset[regnum];
e6031aeb
MK
344}
345
346#include <sys/param.h>
347#include <sys/user.h>
348
349/* Return the size of the user struct. */
350
351int
352kernel_u_size (void)
353{
354 return (sizeof (struct user));
355}
b7247919 356\f
b7247919
MK
357void
358_initialize_i386bsd_nat (void)
359{
a3386186 360 int offset;
8201327c 361
b7247919
MK
362 /* To support the recognition of signal handlers, i386bsd-tdep.c
363 hardcodes some constants. Inclusion of this file means that we
364 are compiling a native debugger, which means that we can use the
365 system header files and sysctl(3) to get at the relevant
366 information. */
367
8201327c 368#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
a3386186
MK
369#define SC_REG_OFFSET i386fbsd4_sc_reg_offset
370#elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
a3386186 371#define SC_REG_OFFSET i386fbsd_sc_reg_offset
005328e3 372#elif defined (NetBSD) || defined (__NetBSD_Version__)
a3386186 373#define SC_REG_OFFSET i386nbsd_sc_reg_offset
005328e3 374#elif defined (OpenBSD)
a3386186 375#define SC_REG_OFFSET i386obsd_sc_reg_offset
8201327c
MK
376#endif
377
bbe06c74
MK
378#ifdef SC_REG_OFFSET
379
a3386186
MK
380 /* We only check the program counter, stack pointer and frame
381 pointer since these members of `struct sigcontext' are essential
382 for providing backtraces. More checks could be added, but would
383 involve adding configure checks for the appropriate structure
384 members, since older BSD's don't provide all of them. */
385
386#define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
387#define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
388#define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
389
b7247919
MK
390 /* Override the default value for the offset of the program counter
391 in the sigcontext structure. */
a3386186 392 offset = offsetof (struct sigcontext, sc_pc);
8201327c 393
a3386186 394 if (SC_PC_OFFSET != offset)
8201327c
MK
395 {
396 warning ("\
397offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
a3386186
MK
398Please report this to <bug-gdb@gnu.org>.",
399 offset, SC_PC_OFFSET);
8201327c
MK
400 }
401
a3386186 402 SC_PC_OFFSET = offset;
6bff26de
MK
403
404 /* Likewise for the stack pointer. */
a3386186 405 offset = offsetof (struct sigcontext, sc_sp);
6bff26de 406
a3386186 407 if (SC_SP_OFFSET != offset)
6bff26de
MK
408 {
409 warning ("\
410offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
411Please report this to <bug-gdb@gnu.org>.",
a3386186
MK
412 offset, SC_SP_OFFSET);
413 }
414
415 SC_SP_OFFSET = offset;
416
417 /* And the frame pointer. */
418 offset = offsetof (struct sigcontext, sc_fp);
419
420 if (SC_FP_OFFSET != offset)
421 {
422 warning ("\
423offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
424Please report this to <bug-gdb@gnu.org>.",
425 offset, SC_FP_OFFSET);
6bff26de
MK
426 }
427
a3386186 428 SC_FP_OFFSET = offset;
bbe06c74
MK
429
430#endif /* SC_REG_OFFSET */
b7247919 431}
This page took 0.383323 seconds and 4 git commands to generate.