xref: /dragonfly/contrib/gdb-7/gdb/i386bsd-nat.c (revision ef5ccd6c)
15796c8dcSSimon Schubert /* Native-dependent code for modern i386 BSD's.
25796c8dcSSimon Schubert 
3*ef5ccd6cSJohn Marino    Copyright (C) 2000-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    This file is part of GDB.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    This program is free software; you can redistribute it and/or modify
85796c8dcSSimon Schubert    it under the terms of the GNU General Public License as published by
95796c8dcSSimon Schubert    the Free Software Foundation; either version 3 of the License, or
105796c8dcSSimon Schubert    (at your option) any later version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    This program is distributed in the hope that it will be useful,
135796c8dcSSimon Schubert    but WITHOUT ANY WARRANTY; without even the implied warranty of
145796c8dcSSimon Schubert    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155796c8dcSSimon Schubert    GNU General Public License for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert    You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
195796c8dcSSimon Schubert 
205796c8dcSSimon Schubert #include "defs.h"
215796c8dcSSimon Schubert #include "inferior.h"
225796c8dcSSimon Schubert #include "regcache.h"
235796c8dcSSimon Schubert 
245796c8dcSSimon Schubert #include "gdb_assert.h"
255796c8dcSSimon Schubert #include <signal.h>
265796c8dcSSimon Schubert #include <stddef.h>
275796c8dcSSimon Schubert #include <sys/types.h>
285796c8dcSSimon Schubert #include <sys/ptrace.h>
295796c8dcSSimon Schubert #include <machine/reg.h>
305796c8dcSSimon Schubert #include <machine/frame.h>
315796c8dcSSimon Schubert 
325796c8dcSSimon Schubert #include "i386-tdep.h"
335796c8dcSSimon Schubert #include "i387-tdep.h"
345796c8dcSSimon Schubert #include "i386bsd-nat.h"
355796c8dcSSimon Schubert #include "inf-ptrace.h"
365796c8dcSSimon Schubert 
375796c8dcSSimon Schubert 
385796c8dcSSimon Schubert /* In older BSD versions we cannot get at some of the segment
395796c8dcSSimon Schubert    registers.  FreeBSD for example didn't support the %fs and %gs
405796c8dcSSimon Schubert    registers until the 3.0 release.  We have autoconf checks for their
415796c8dcSSimon Schubert    presence, and deal gracefully with their absence.  */
425796c8dcSSimon Schubert 
435796c8dcSSimon Schubert /* Offset in `struct reg' where MEMBER is stored.  */
445796c8dcSSimon Schubert #define REG_OFFSET(member) offsetof (struct reg, member)
455796c8dcSSimon Schubert 
465796c8dcSSimon Schubert /* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct
475796c8dcSSimon Schubert    reg' where the GDB register REGNUM is stored.  Unsupported
485796c8dcSSimon Schubert    registers are marked with `-1'.  */
495796c8dcSSimon Schubert static int i386bsd_r_reg_offset[] =
505796c8dcSSimon Schubert {
515796c8dcSSimon Schubert   REG_OFFSET (r_eax),
525796c8dcSSimon Schubert   REG_OFFSET (r_ecx),
535796c8dcSSimon Schubert   REG_OFFSET (r_edx),
545796c8dcSSimon Schubert   REG_OFFSET (r_ebx),
555796c8dcSSimon Schubert   REG_OFFSET (r_esp),
565796c8dcSSimon Schubert   REG_OFFSET (r_ebp),
575796c8dcSSimon Schubert   REG_OFFSET (r_esi),
585796c8dcSSimon Schubert   REG_OFFSET (r_edi),
595796c8dcSSimon Schubert   REG_OFFSET (r_eip),
605796c8dcSSimon Schubert   REG_OFFSET (r_eflags),
615796c8dcSSimon Schubert   REG_OFFSET (r_cs),
625796c8dcSSimon Schubert   REG_OFFSET (r_ss),
635796c8dcSSimon Schubert   REG_OFFSET (r_ds),
645796c8dcSSimon Schubert   REG_OFFSET (r_es),
655796c8dcSSimon Schubert #ifdef HAVE_STRUCT_REG_R_FS
665796c8dcSSimon Schubert   REG_OFFSET (r_fs),
675796c8dcSSimon Schubert #else
685796c8dcSSimon Schubert   -1,
695796c8dcSSimon Schubert #endif
705796c8dcSSimon Schubert #ifdef HAVE_STRUCT_REG_R_GS
715796c8dcSSimon Schubert   REG_OFFSET (r_gs)
725796c8dcSSimon Schubert #else
735796c8dcSSimon Schubert   -1
745796c8dcSSimon Schubert #endif
755796c8dcSSimon Schubert };
765796c8dcSSimon Schubert 
775796c8dcSSimon Schubert /* Macro to determine if a register is fetched with PT_GETREGS.  */
785796c8dcSSimon Schubert #define GETREGS_SUPPLIES(regnum) \
795796c8dcSSimon Schubert   ((0 <= (regnum) && (regnum) <= 15))
805796c8dcSSimon Schubert 
815796c8dcSSimon Schubert #ifdef HAVE_PT_GETXMMREGS
825796c8dcSSimon Schubert /* Set to 1 if the kernel supports PT_GETXMMREGS.  Initialized to -1
835796c8dcSSimon Schubert    so that we try PT_GETXMMREGS the first time around.  */
845796c8dcSSimon Schubert static int have_ptrace_xmmregs = -1;
855796c8dcSSimon Schubert #endif
865796c8dcSSimon Schubert 
875796c8dcSSimon Schubert 
885796c8dcSSimon Schubert /* Supply the general-purpose registers in GREGS, to REGCACHE.  */
895796c8dcSSimon Schubert 
905796c8dcSSimon Schubert static void
i386bsd_supply_gregset(struct regcache * regcache,const void * gregs)915796c8dcSSimon Schubert i386bsd_supply_gregset (struct regcache *regcache, const void *gregs)
925796c8dcSSimon Schubert {
935796c8dcSSimon Schubert   const char *regs = gregs;
945796c8dcSSimon Schubert   int regnum;
955796c8dcSSimon Schubert 
965796c8dcSSimon Schubert   for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++)
975796c8dcSSimon Schubert     {
985796c8dcSSimon Schubert       int offset = i386bsd_r_reg_offset[regnum];
995796c8dcSSimon Schubert 
1005796c8dcSSimon Schubert       if (offset != -1)
1015796c8dcSSimon Schubert 	regcache_raw_supply (regcache, regnum, regs + offset);
1025796c8dcSSimon Schubert     }
1035796c8dcSSimon Schubert }
1045796c8dcSSimon Schubert 
1055796c8dcSSimon Schubert /* Collect register REGNUM from REGCACHE and store its contents in
1065796c8dcSSimon Schubert    GREGS.  If REGNUM is -1, collect and store all appropriate
1075796c8dcSSimon Schubert    registers.  */
1085796c8dcSSimon Schubert 
1095796c8dcSSimon Schubert static void
i386bsd_collect_gregset(const struct regcache * regcache,void * gregs,int regnum)1105796c8dcSSimon Schubert i386bsd_collect_gregset (const struct regcache *regcache,
1115796c8dcSSimon Schubert 			 void *gregs, int regnum)
1125796c8dcSSimon Schubert {
1135796c8dcSSimon Schubert   char *regs = gregs;
1145796c8dcSSimon Schubert   int i;
1155796c8dcSSimon Schubert 
1165796c8dcSSimon Schubert   for (i = 0; i < ARRAY_SIZE (i386bsd_r_reg_offset); i++)
1175796c8dcSSimon Schubert     {
1185796c8dcSSimon Schubert       if (regnum == -1 || regnum == i)
1195796c8dcSSimon Schubert 	{
1205796c8dcSSimon Schubert 	  int offset = i386bsd_r_reg_offset[i];
1215796c8dcSSimon Schubert 
1225796c8dcSSimon Schubert 	  if (offset != -1)
1235796c8dcSSimon Schubert 	    regcache_raw_collect (regcache, i, regs + offset);
1245796c8dcSSimon Schubert 	}
1255796c8dcSSimon Schubert     }
1265796c8dcSSimon Schubert }
1275796c8dcSSimon Schubert 
1285796c8dcSSimon Schubert /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
1295796c8dcSSimon Schubert    for all registers (including the floating point registers).  */
1305796c8dcSSimon Schubert 
1315796c8dcSSimon Schubert static void
i386bsd_fetch_inferior_registers(struct target_ops * ops,struct regcache * regcache,int regnum)1325796c8dcSSimon Schubert i386bsd_fetch_inferior_registers (struct target_ops *ops,
1335796c8dcSSimon Schubert 				  struct regcache *regcache, int regnum)
1345796c8dcSSimon Schubert {
1355796c8dcSSimon Schubert   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
1365796c8dcSSimon Schubert     {
1375796c8dcSSimon Schubert       struct reg regs;
1385796c8dcSSimon Schubert 
1395796c8dcSSimon Schubert       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
1405796c8dcSSimon Schubert 		  (PTRACE_TYPE_ARG3) &regs, 0) == -1)
1415796c8dcSSimon Schubert 	perror_with_name (_("Couldn't get registers"));
1425796c8dcSSimon Schubert 
1435796c8dcSSimon Schubert       i386bsd_supply_gregset (regcache, &regs);
1445796c8dcSSimon Schubert       if (regnum != -1)
1455796c8dcSSimon Schubert 	return;
1465796c8dcSSimon Schubert     }
1475796c8dcSSimon Schubert 
1485796c8dcSSimon Schubert   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
1495796c8dcSSimon Schubert     {
1505796c8dcSSimon Schubert       struct fpreg fpregs;
1515796c8dcSSimon Schubert #ifdef HAVE_PT_GETXMMREGS
1525796c8dcSSimon Schubert       char xmmregs[512];
1535796c8dcSSimon Schubert 
1545796c8dcSSimon Schubert       if (have_ptrace_xmmregs != 0
1555796c8dcSSimon Schubert 	  && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
1565796c8dcSSimon Schubert 		    (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
1575796c8dcSSimon Schubert 	{
1585796c8dcSSimon Schubert 	  have_ptrace_xmmregs = 1;
1595796c8dcSSimon Schubert 	  i387_supply_fxsave (regcache, -1, xmmregs);
1605796c8dcSSimon Schubert 	}
1615796c8dcSSimon Schubert       else
1625796c8dcSSimon Schubert 	{
1635796c8dcSSimon Schubert           if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
1645796c8dcSSimon Schubert 		      (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
1655796c8dcSSimon Schubert 	    perror_with_name (_("Couldn't get floating point status"));
1665796c8dcSSimon Schubert 
1675796c8dcSSimon Schubert 	  i387_supply_fsave (regcache, -1, &fpregs);
1685796c8dcSSimon Schubert 	}
1695796c8dcSSimon Schubert #else
1705796c8dcSSimon Schubert       if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
1715796c8dcSSimon Schubert 		  (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
1725796c8dcSSimon Schubert 	perror_with_name (_("Couldn't get floating point status"));
1735796c8dcSSimon Schubert 
1745796c8dcSSimon Schubert       i387_supply_fsave (regcache, -1, &fpregs);
1755796c8dcSSimon Schubert #endif
1765796c8dcSSimon Schubert     }
1775796c8dcSSimon Schubert }
1785796c8dcSSimon Schubert 
1795796c8dcSSimon Schubert /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
1805796c8dcSSimon Schubert    this for all registers (including the floating point registers).  */
1815796c8dcSSimon Schubert 
1825796c8dcSSimon Schubert static void
i386bsd_store_inferior_registers(struct target_ops * ops,struct regcache * regcache,int regnum)1835796c8dcSSimon Schubert i386bsd_store_inferior_registers (struct target_ops *ops,
1845796c8dcSSimon Schubert 				  struct regcache *regcache, int regnum)
1855796c8dcSSimon Schubert {
1865796c8dcSSimon Schubert   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
1875796c8dcSSimon Schubert     {
1885796c8dcSSimon Schubert       struct reg regs;
1895796c8dcSSimon Schubert 
1905796c8dcSSimon Schubert       if (ptrace (PT_GETREGS, PIDGET (inferior_ptid),
1915796c8dcSSimon Schubert                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
1925796c8dcSSimon Schubert         perror_with_name (_("Couldn't get registers"));
1935796c8dcSSimon Schubert 
1945796c8dcSSimon Schubert       i386bsd_collect_gregset (regcache, &regs, regnum);
1955796c8dcSSimon Schubert 
1965796c8dcSSimon Schubert       if (ptrace (PT_SETREGS, PIDGET (inferior_ptid),
1975796c8dcSSimon Schubert 	          (PTRACE_TYPE_ARG3) &regs, 0) == -1)
1985796c8dcSSimon Schubert         perror_with_name (_("Couldn't write registers"));
1995796c8dcSSimon Schubert 
2005796c8dcSSimon Schubert       if (regnum != -1)
2015796c8dcSSimon Schubert 	return;
2025796c8dcSSimon Schubert     }
2035796c8dcSSimon Schubert 
2045796c8dcSSimon Schubert   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
2055796c8dcSSimon Schubert     {
2065796c8dcSSimon Schubert       struct fpreg fpregs;
2075796c8dcSSimon Schubert #ifdef HAVE_PT_GETXMMREGS
2085796c8dcSSimon Schubert       char xmmregs[512];
2095796c8dcSSimon Schubert 
2105796c8dcSSimon Schubert       if (have_ptrace_xmmregs != 0
2115796c8dcSSimon Schubert 	  && ptrace(PT_GETXMMREGS, PIDGET (inferior_ptid),
2125796c8dcSSimon Schubert 		    (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
2135796c8dcSSimon Schubert 	{
2145796c8dcSSimon Schubert 	  have_ptrace_xmmregs = 1;
2155796c8dcSSimon Schubert 
2165796c8dcSSimon Schubert 	  i387_collect_fxsave (regcache, regnum, xmmregs);
2175796c8dcSSimon Schubert 
2185796c8dcSSimon Schubert 	  if (ptrace (PT_SETXMMREGS, PIDGET (inferior_ptid),
2195796c8dcSSimon Schubert 		      (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
2205796c8dcSSimon Schubert             perror_with_name (_("Couldn't write XMM registers"));
2215796c8dcSSimon Schubert 	}
2225796c8dcSSimon Schubert       else
2235796c8dcSSimon Schubert 	{
2245796c8dcSSimon Schubert 	  have_ptrace_xmmregs = 0;
2255796c8dcSSimon Schubert #endif
2265796c8dcSSimon Schubert           if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid),
2275796c8dcSSimon Schubert 		      (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
2285796c8dcSSimon Schubert 	    perror_with_name (_("Couldn't get floating point status"));
2295796c8dcSSimon Schubert 
2305796c8dcSSimon Schubert           i387_collect_fsave (regcache, regnum, &fpregs);
2315796c8dcSSimon Schubert 
2325796c8dcSSimon Schubert           if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid),
2335796c8dcSSimon Schubert 		      (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
2345796c8dcSSimon Schubert 	    perror_with_name (_("Couldn't write floating point status"));
2355796c8dcSSimon Schubert #ifdef HAVE_PT_GETXMMREGS
2365796c8dcSSimon Schubert         }
2375796c8dcSSimon Schubert #endif
2385796c8dcSSimon Schubert     }
2395796c8dcSSimon Schubert }
2405796c8dcSSimon Schubert 
2415796c8dcSSimon Schubert /* Create a prototype *BSD/i386 target.  The client can override it
2425796c8dcSSimon Schubert    with local methods.  */
2435796c8dcSSimon Schubert 
2445796c8dcSSimon Schubert struct target_ops *
i386bsd_target(void)2455796c8dcSSimon Schubert i386bsd_target (void)
2465796c8dcSSimon Schubert {
2475796c8dcSSimon Schubert   struct target_ops *t;
2485796c8dcSSimon Schubert 
2495796c8dcSSimon Schubert   t = inf_ptrace_target ();
2505796c8dcSSimon Schubert   t->to_fetch_registers = i386bsd_fetch_inferior_registers;
2515796c8dcSSimon Schubert   t->to_store_registers = i386bsd_store_inferior_registers;
2525796c8dcSSimon Schubert   return t;
2535796c8dcSSimon Schubert }
2545796c8dcSSimon Schubert 
2555796c8dcSSimon Schubert 
2565796c8dcSSimon Schubert /* Support for debug registers.  */
2575796c8dcSSimon Schubert 
2585796c8dcSSimon Schubert #ifdef HAVE_PT_GETDBREGS
2595796c8dcSSimon Schubert 
2605796c8dcSSimon Schubert /* Not all versions of FreeBSD/i386 that support the debug registers
2615796c8dcSSimon Schubert    have this macro.  */
2625796c8dcSSimon Schubert #ifndef DBREG_DRX
2635796c8dcSSimon Schubert #define DBREG_DRX(d, x) ((&d->dr0)[x])
2645796c8dcSSimon Schubert #endif
2655796c8dcSSimon Schubert 
266*ef5ccd6cSJohn Marino static unsigned long
i386bsd_dr_get(ptid_t ptid,int regnum)267*ef5ccd6cSJohn Marino i386bsd_dr_get (ptid_t ptid, int regnum)
268*ef5ccd6cSJohn Marino {
269*ef5ccd6cSJohn Marino   struct dbreg dbregs;
270*ef5ccd6cSJohn Marino 
271*ef5ccd6cSJohn Marino   if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
272*ef5ccd6cSJohn Marino 	      (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
273*ef5ccd6cSJohn Marino     perror_with_name (_("Couldn't read debug registers"));
274*ef5ccd6cSJohn Marino 
275*ef5ccd6cSJohn Marino   return DBREG_DRX ((&dbregs), regnum);
276*ef5ccd6cSJohn Marino }
277*ef5ccd6cSJohn Marino 
2785796c8dcSSimon Schubert static void
i386bsd_dr_set(int regnum,unsigned int value)2795796c8dcSSimon Schubert i386bsd_dr_set (int regnum, unsigned int value)
2805796c8dcSSimon Schubert {
2815796c8dcSSimon Schubert   struct dbreg dbregs;
2825796c8dcSSimon Schubert 
2835796c8dcSSimon Schubert   if (ptrace (PT_GETDBREGS, PIDGET (inferior_ptid),
2845796c8dcSSimon Schubert               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
2855796c8dcSSimon Schubert     perror_with_name (_("Couldn't get debug registers"));
2865796c8dcSSimon Schubert 
2875796c8dcSSimon Schubert   /* For some mysterious reason, some of the reserved bits in the
2885796c8dcSSimon Schubert      debug control register get set.  Mask these off, otherwise the
2895796c8dcSSimon Schubert      ptrace call below will fail.  */
2905796c8dcSSimon Schubert   DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
2915796c8dcSSimon Schubert 
2925796c8dcSSimon Schubert   DBREG_DRX ((&dbregs), regnum) = value;
2935796c8dcSSimon Schubert 
2945796c8dcSSimon Schubert   if (ptrace (PT_SETDBREGS, PIDGET (inferior_ptid),
2955796c8dcSSimon Schubert               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
2965796c8dcSSimon Schubert     perror_with_name (_("Couldn't write debug registers"));
2975796c8dcSSimon Schubert }
2985796c8dcSSimon Schubert 
2995796c8dcSSimon Schubert void
i386bsd_dr_set_control(unsigned long control)3005796c8dcSSimon Schubert i386bsd_dr_set_control (unsigned long control)
3015796c8dcSSimon Schubert {
3025796c8dcSSimon Schubert   i386bsd_dr_set (7, control);
3035796c8dcSSimon Schubert }
3045796c8dcSSimon Schubert 
3055796c8dcSSimon Schubert void
i386bsd_dr_set_addr(int regnum,CORE_ADDR addr)3065796c8dcSSimon Schubert i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
3075796c8dcSSimon Schubert {
3085796c8dcSSimon Schubert   gdb_assert (regnum >= 0 && regnum <= 4);
3095796c8dcSSimon Schubert 
3105796c8dcSSimon Schubert   i386bsd_dr_set (regnum, addr);
3115796c8dcSSimon Schubert }
3125796c8dcSSimon Schubert 
313*ef5ccd6cSJohn Marino CORE_ADDR
i386bsd_dr_get_addr(int regnum)314*ef5ccd6cSJohn Marino i386bsd_dr_get_addr (int regnum)
3155796c8dcSSimon Schubert {
316*ef5ccd6cSJohn Marino   return i386bsd_dr_get (inferior_ptid, regnum);
3175796c8dcSSimon Schubert }
3185796c8dcSSimon Schubert 
3195796c8dcSSimon Schubert unsigned long
i386bsd_dr_get_status(void)3205796c8dcSSimon Schubert i386bsd_dr_get_status (void)
3215796c8dcSSimon Schubert {
322*ef5ccd6cSJohn Marino   return i386bsd_dr_get (inferior_ptid, 6);
323*ef5ccd6cSJohn Marino }
3245796c8dcSSimon Schubert 
325*ef5ccd6cSJohn Marino unsigned long
i386bsd_dr_get_control(void)326*ef5ccd6cSJohn Marino i386bsd_dr_get_control (void)
327*ef5ccd6cSJohn Marino {
328*ef5ccd6cSJohn Marino   return i386bsd_dr_get (inferior_ptid, 7);
3295796c8dcSSimon Schubert }
3305796c8dcSSimon Schubert 
3315796c8dcSSimon Schubert #endif /* PT_GETDBREGS */
3325796c8dcSSimon Schubert 
3335796c8dcSSimon Schubert 
334*ef5ccd6cSJohn Marino /* Provide a prototype to silence -Wmissing-prototypes.  */
335*ef5ccd6cSJohn Marino void _initialize_i386bsd_nat (void);
336*ef5ccd6cSJohn Marino 
3375796c8dcSSimon Schubert void
_initialize_i386bsd_nat(void)3385796c8dcSSimon Schubert _initialize_i386bsd_nat (void)
3395796c8dcSSimon Schubert {
3405796c8dcSSimon Schubert   int offset;
3415796c8dcSSimon Schubert 
3425796c8dcSSimon Schubert   /* To support the recognition of signal handlers, i386bsd-tdep.c
3435796c8dcSSimon Schubert      hardcodes some constants.  Inclusion of this file means that we
3445796c8dcSSimon Schubert      are compiling a native debugger, which means that we can use the
3455796c8dcSSimon Schubert      system header files and sysctl(3) to get at the relevant
3465796c8dcSSimon Schubert      information.  */
3475796c8dcSSimon Schubert 
3485796c8dcSSimon Schubert #if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
3495796c8dcSSimon Schubert #define SC_REG_OFFSET i386fbsd4_sc_reg_offset
3505796c8dcSSimon Schubert #elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
3515796c8dcSSimon Schubert #define SC_REG_OFFSET i386fbsd_sc_reg_offset
3525796c8dcSSimon Schubert #elif defined (NetBSD) || defined (__NetBSD_Version__)
3535796c8dcSSimon Schubert #define SC_REG_OFFSET i386nbsd_sc_reg_offset
3545796c8dcSSimon Schubert #elif defined (OpenBSD)
3555796c8dcSSimon Schubert #define SC_REG_OFFSET i386obsd_sc_reg_offset
3565796c8dcSSimon Schubert #elif defined (DragonFly)
3575796c8dcSSimon Schubert #define SC_REG_OFFSET i386dfly_sc_reg_offset
3585796c8dcSSimon Schubert #endif
3595796c8dcSSimon Schubert 
3605796c8dcSSimon Schubert #ifdef SC_REG_OFFSET
3615796c8dcSSimon Schubert 
3625796c8dcSSimon Schubert   /* We only check the program counter, stack pointer and frame
3635796c8dcSSimon Schubert      pointer since these members of `struct sigcontext' are essential
3645796c8dcSSimon Schubert      for providing backtraces.  More checks could be added, but would
3655796c8dcSSimon Schubert      involve adding configure checks for the appropriate structure
3665796c8dcSSimon Schubert      members, since older BSD's don't provide all of them.  */
3675796c8dcSSimon Schubert 
3685796c8dcSSimon Schubert #define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
3695796c8dcSSimon Schubert #define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
3705796c8dcSSimon Schubert #define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
3715796c8dcSSimon Schubert 
3725796c8dcSSimon Schubert   /* Override the default value for the offset of the program counter
3735796c8dcSSimon Schubert      in the sigcontext structure.  */
3745796c8dcSSimon Schubert   offset = offsetof (struct sigcontext, sc_pc);
3755796c8dcSSimon Schubert 
3765796c8dcSSimon Schubert   if (SC_PC_OFFSET != offset)
3775796c8dcSSimon Schubert     {
3785796c8dcSSimon Schubert       warning (_("\
3795796c8dcSSimon Schubert offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
3805796c8dcSSimon Schubert Please report this to <bug-gdb@gnu.org>."),
3815796c8dcSSimon Schubert 	       offset, SC_PC_OFFSET);
3825796c8dcSSimon Schubert     }
3835796c8dcSSimon Schubert 
3845796c8dcSSimon Schubert   SC_PC_OFFSET = offset;
3855796c8dcSSimon Schubert 
3865796c8dcSSimon Schubert   /* Likewise for the stack pointer.  */
3875796c8dcSSimon Schubert   offset = offsetof (struct sigcontext, sc_sp);
3885796c8dcSSimon Schubert 
3895796c8dcSSimon Schubert   if (SC_SP_OFFSET != offset)
3905796c8dcSSimon Schubert     {
3915796c8dcSSimon Schubert       warning (_("\
3925796c8dcSSimon Schubert offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
3935796c8dcSSimon Schubert Please report this to <bug-gdb@gnu.org>."),
3945796c8dcSSimon Schubert 	       offset, SC_SP_OFFSET);
3955796c8dcSSimon Schubert     }
3965796c8dcSSimon Schubert 
3975796c8dcSSimon Schubert   SC_SP_OFFSET = offset;
3985796c8dcSSimon Schubert 
3995796c8dcSSimon Schubert   /* And the frame pointer.  */
4005796c8dcSSimon Schubert   offset = offsetof (struct sigcontext, sc_fp);
4015796c8dcSSimon Schubert 
4025796c8dcSSimon Schubert   if (SC_FP_OFFSET != offset)
4035796c8dcSSimon Schubert     {
4045796c8dcSSimon Schubert       warning (_("\
4055796c8dcSSimon Schubert offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
4065796c8dcSSimon Schubert Please report this to <bug-gdb@gnu.org>."),
4075796c8dcSSimon Schubert 	       offset, SC_FP_OFFSET);
4085796c8dcSSimon Schubert     }
4095796c8dcSSimon Schubert 
4105796c8dcSSimon Schubert   SC_FP_OFFSET = offset;
4115796c8dcSSimon Schubert 
412 #endif /* SC_REG_OFFSET */
413 }
414