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