GDB (API)
|
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) ®s, 0) == -1) 00141 perror_with_name (_("Couldn't get registers")); 00142 00143 i386bsd_supply_gregset (regcache, ®s); 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) ®s, 0) == -1) 00192 perror_with_name (_("Couldn't get registers")); 00193 00194 i386bsd_collect_gregset (regcache, ®s, regnum); 00195 00196 if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), 00197 (PTRACE_TYPE_ARG3) ®s, 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 }