GDB (API)
/home/stan/gdb/src/gdb/i386bsd-nat.c
Go to the documentation of this file.
00001 /* Native-dependent code for modern i386 BSD's.
00002 
00003    Copyright (C) 2000-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "inferior.h"
00022 #include "regcache.h"
00023 
00024 #include "gdb_assert.h"
00025 #include <signal.h>
00026 #include <stddef.h>
00027 #include <sys/types.h>
00028 #include <sys/ptrace.h>
00029 #include <machine/reg.h>
00030 #include <machine/frame.h>
00031 
00032 #include "i386-tdep.h"
00033 #include "i387-tdep.h"
00034 #include "i386bsd-nat.h"
00035 #include "inf-ptrace.h"
00036 
00037 
00038 /* In older BSD versions we cannot get at some of the segment
00039    registers.  FreeBSD for example didn't support the %fs and %gs
00040    registers until the 3.0 release.  We have autoconf checks for their
00041    presence, and deal gracefully with their absence.  */
00042 
00043 /* Offset in `struct reg' where MEMBER is stored.  */
00044 #define REG_OFFSET(member) offsetof (struct reg, member)
00045 
00046 /* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct
00047    reg' where the GDB register REGNUM is stored.  Unsupported
00048    registers are marked with `-1'.  */
00049 static int i386bsd_r_reg_offset[] =
00050 {
00051   REG_OFFSET (r_eax),
00052   REG_OFFSET (r_ecx),
00053   REG_OFFSET (r_edx),
00054   REG_OFFSET (r_ebx),
00055   REG_OFFSET (r_esp),
00056   REG_OFFSET (r_ebp),
00057   REG_OFFSET (r_esi),
00058   REG_OFFSET (r_edi),
00059   REG_OFFSET (r_eip),
00060   REG_OFFSET (r_eflags),
00061   REG_OFFSET (r_cs),
00062   REG_OFFSET (r_ss),
00063   REG_OFFSET (r_ds),
00064   REG_OFFSET (r_es),
00065 #ifdef HAVE_STRUCT_REG_R_FS
00066   REG_OFFSET (r_fs),
00067 #else
00068   -1,
00069 #endif
00070 #ifdef HAVE_STRUCT_REG_R_GS
00071   REG_OFFSET (r_gs)
00072 #else
00073   -1
00074 #endif
00075 };
00076 
00077 /* Macro to determine if a register is fetched with PT_GETREGS.  */
00078 #define GETREGS_SUPPLIES(regnum) \
00079   ((0 <= (regnum) && (regnum) <= 15))
00080 
00081 #ifdef HAVE_PT_GETXMMREGS
00082 /* Set to 1 if the kernel supports PT_GETXMMREGS.  Initialized to -1
00083    so that we try PT_GETXMMREGS the first time around.  */
00084 static int have_ptrace_xmmregs = -1;
00085 #endif
00086 
00087 
00088 /* Supply the general-purpose registers in GREGS, to REGCACHE.  */
00089 
00090 static void
00091 i386bsd_supply_gregset (struct regcache *regcache, const void *gregs)
00092 {
00093   const char *regs = gregs;
00094   int regnum;
00095 
00096   for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++)
00097     {
00098       int offset = i386bsd_r_reg_offset[regnum];
00099 
00100       if (offset != -1)
00101         regcache_raw_supply (regcache, regnum, regs + offset);
00102     }
00103 }
00104 
00105 /* Collect register REGNUM from REGCACHE and store its contents in
00106    GREGS.  If REGNUM is -1, collect and store all appropriate
00107    registers.  */
00108 
00109 static void
00110 i386bsd_collect_gregset (const struct regcache *regcache,
00111                          void *gregs, int regnum)
00112 {
00113   char *regs = gregs;
00114   int i;
00115 
00116   for (i = 0; i < ARRAY_SIZE (i386bsd_r_reg_offset); i++)
00117     {
00118       if (regnum == -1 || regnum == i)
00119         {
00120           int offset = i386bsd_r_reg_offset[i];
00121 
00122           if (offset != -1)
00123             regcache_raw_collect (regcache, i, regs + offset);
00124         }
00125     }
00126 }
00127 
00128 /* Fetch register REGNUM from the inferior.  If REGNUM is -1, do this
00129    for all registers (including the floating point registers).  */
00130 
00131 static void
00132 i386bsd_fetch_inferior_registers (struct target_ops *ops,
00133                                   struct regcache *regcache, int regnum)
00134 {
00135   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
00136     {
00137       struct reg regs;
00138 
00139       if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
00140                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
00141         perror_with_name (_("Couldn't get registers"));
00142 
00143       i386bsd_supply_gregset (regcache, &regs);
00144       if (regnum != -1)
00145         return;
00146     }
00147 
00148   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
00149     {
00150       struct fpreg fpregs;
00151 #ifdef HAVE_PT_GETXMMREGS
00152       char xmmregs[512];
00153 
00154       if (have_ptrace_xmmregs != 0
00155           && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid),
00156                     (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
00157         {
00158           have_ptrace_xmmregs = 1;
00159           i387_supply_fxsave (regcache, -1, xmmregs);
00160         }
00161       else
00162         {
00163           if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
00164                       (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
00165             perror_with_name (_("Couldn't get floating point status"));
00166 
00167           i387_supply_fsave (regcache, -1, &fpregs);
00168         }
00169 #else
00170       if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
00171                   (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
00172         perror_with_name (_("Couldn't get floating point status"));
00173 
00174       i387_supply_fsave (regcache, -1, &fpregs);
00175 #endif
00176     }
00177 }
00178 
00179 /* Store register REGNUM back into the inferior.  If REGNUM is -1, do
00180    this for all registers (including the floating point registers).  */
00181 
00182 static void
00183 i386bsd_store_inferior_registers (struct target_ops *ops,
00184                                   struct regcache *regcache, int regnum)
00185 {
00186   if (regnum == -1 || GETREGS_SUPPLIES (regnum))
00187     {
00188       struct reg regs;
00189 
00190       if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid),
00191                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
00192         perror_with_name (_("Couldn't get registers"));
00193 
00194       i386bsd_collect_gregset (regcache, &regs, regnum);
00195 
00196       if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid),
00197                   (PTRACE_TYPE_ARG3) &regs, 0) == -1)
00198         perror_with_name (_("Couldn't write registers"));
00199 
00200       if (regnum != -1)
00201         return;
00202     }
00203 
00204   if (regnum == -1 || regnum >= I386_ST0_REGNUM)
00205     {
00206       struct fpreg fpregs;
00207 #ifdef HAVE_PT_GETXMMREGS
00208       char xmmregs[512];
00209 
00210       if (have_ptrace_xmmregs != 0
00211           && ptrace(PT_GETXMMREGS, ptid_get_pid (inferior_ptid),
00212                     (PTRACE_TYPE_ARG3) xmmregs, 0) == 0)
00213         {
00214           have_ptrace_xmmregs = 1;
00215 
00216           i387_collect_fxsave (regcache, regnum, xmmregs);
00217 
00218           if (ptrace (PT_SETXMMREGS, ptid_get_pid (inferior_ptid),
00219                       (PTRACE_TYPE_ARG3) xmmregs, 0) == -1)
00220             perror_with_name (_("Couldn't write XMM registers"));
00221         }
00222       else
00223         {
00224           have_ptrace_xmmregs = 0;
00225 #endif
00226           if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid),
00227                       (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
00228             perror_with_name (_("Couldn't get floating point status"));
00229 
00230           i387_collect_fsave (regcache, regnum, &fpregs);
00231 
00232           if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid),
00233                       (PTRACE_TYPE_ARG3) &fpregs, 0) == -1)
00234             perror_with_name (_("Couldn't write floating point status"));
00235 #ifdef HAVE_PT_GETXMMREGS
00236         }
00237 #endif
00238     }
00239 }
00240 
00241 /* Create a prototype *BSD/i386 target.  The client can override it
00242    with local methods.  */
00243 
00244 struct target_ops *
00245 i386bsd_target (void)
00246 {
00247   struct target_ops *t;
00248 
00249   t = inf_ptrace_target ();
00250   t->to_fetch_registers = i386bsd_fetch_inferior_registers;
00251   t->to_store_registers = i386bsd_store_inferior_registers;
00252   return t;
00253 }
00254 
00255 
00256 /* Support for debug registers.  */
00257 
00258 #ifdef HAVE_PT_GETDBREGS
00259 
00260 /* Not all versions of FreeBSD/i386 that support the debug registers
00261    have this macro.  */
00262 #ifndef DBREG_DRX
00263 #define DBREG_DRX(d, x) ((&d->dr0)[x])
00264 #endif
00265 
00266 static unsigned long
00267 i386bsd_dr_get (ptid_t ptid, int regnum)
00268 {
00269   struct dbreg dbregs;
00270 
00271   if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid),
00272               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
00273     perror_with_name (_("Couldn't read debug registers"));
00274 
00275   return DBREG_DRX ((&dbregs), regnum);
00276 }
00277 
00278 static void
00279 i386bsd_dr_set (int regnum, unsigned int value)
00280 {
00281   struct dbreg dbregs;
00282 
00283   if (ptrace (PT_GETDBREGS, ptid_get_pid (inferior_ptid),
00284               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
00285     perror_with_name (_("Couldn't get debug registers"));
00286 
00287   /* For some mysterious reason, some of the reserved bits in the
00288      debug control register get set.  Mask these off, otherwise the
00289      ptrace call below will fail.  */
00290   DBREG_DRX ((&dbregs), 7) &= ~(0x0000fc00);
00291 
00292   DBREG_DRX ((&dbregs), regnum) = value;
00293 
00294   if (ptrace (PT_SETDBREGS, ptid_get_pid (inferior_ptid),
00295               (PTRACE_TYPE_ARG3) &dbregs, 0) == -1)
00296     perror_with_name (_("Couldn't write debug registers"));
00297 }
00298 
00299 void
00300 i386bsd_dr_set_control (unsigned long control)
00301 {
00302   i386bsd_dr_set (7, control);
00303 }
00304 
00305 void
00306 i386bsd_dr_set_addr (int regnum, CORE_ADDR addr)
00307 {
00308   gdb_assert (regnum >= 0 && regnum <= 4);
00309 
00310   i386bsd_dr_set (regnum, addr);
00311 }
00312 
00313 CORE_ADDR
00314 i386bsd_dr_get_addr (int regnum)
00315 {
00316   return i386bsd_dr_get (inferior_ptid, regnum);
00317 }
00318 
00319 unsigned long
00320 i386bsd_dr_get_status (void)
00321 {
00322   return i386bsd_dr_get (inferior_ptid, 6);
00323 }
00324 
00325 unsigned long
00326 i386bsd_dr_get_control (void)
00327 {
00328   return i386bsd_dr_get (inferior_ptid, 7);
00329 }
00330 
00331 #endif /* PT_GETDBREGS */
00332 
00333 
00334 /* Provide a prototype to silence -Wmissing-prototypes.  */
00335 void _initialize_i386bsd_nat (void);
00336 
00337 void
00338 _initialize_i386bsd_nat (void)
00339 {
00340   int offset;
00341 
00342   /* To support the recognition of signal handlers, i386bsd-tdep.c
00343      hardcodes some constants.  Inclusion of this file means that we
00344      are compiling a native debugger, which means that we can use the
00345      system header files and sysctl(3) to get at the relevant
00346      information.  */
00347 
00348 #if defined (__FreeBSD_version) && __FreeBSD_version >= 400011
00349 #define SC_REG_OFFSET i386fbsd4_sc_reg_offset
00350 #elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005
00351 #define SC_REG_OFFSET i386fbsd_sc_reg_offset
00352 #elif defined (NetBSD) || defined (__NetBSD_Version__)
00353 #define SC_REG_OFFSET i386nbsd_sc_reg_offset
00354 #elif defined (OpenBSD)
00355 #define SC_REG_OFFSET i386obsd_sc_reg_offset
00356 #endif
00357 
00358 #ifdef SC_REG_OFFSET
00359 
00360   /* We only check the program counter, stack pointer and frame
00361      pointer since these members of `struct sigcontext' are essential
00362      for providing backtraces.  More checks could be added, but would
00363      involve adding configure checks for the appropriate structure
00364      members, since older BSD's don't provide all of them.  */
00365 
00366 #define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM]
00367 #define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM]
00368 #define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM]
00369 
00370   /* Override the default value for the offset of the program counter
00371      in the sigcontext structure.  */
00372   offset = offsetof (struct sigcontext, sc_pc);
00373 
00374   if (SC_PC_OFFSET != offset)
00375     {
00376       warning (_("\
00377 offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\
00378 Please report this to <bug-gdb@gnu.org>."), 
00379                offset, SC_PC_OFFSET);
00380     }
00381 
00382   SC_PC_OFFSET = offset;
00383 
00384   /* Likewise for the stack pointer.  */
00385   offset = offsetof (struct sigcontext, sc_sp);
00386 
00387   if (SC_SP_OFFSET != offset)
00388     {
00389       warning (_("\
00390 offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\
00391 Please report this to <bug-gdb@gnu.org>."),
00392                offset, SC_SP_OFFSET);
00393     }
00394 
00395   SC_SP_OFFSET = offset;
00396 
00397   /* And the frame pointer.  */
00398   offset = offsetof (struct sigcontext, sc_fp);
00399 
00400   if (SC_FP_OFFSET != offset)
00401     {
00402       warning (_("\
00403 offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\
00404 Please report this to <bug-gdb@gnu.org>."),
00405                offset, SC_FP_OFFSET);
00406     }
00407 
00408   SC_FP_OFFSET = offset;
00409 
00410 #endif /* SC_REG_OFFSET */
00411 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines