amd64fbsd-nat.c revision 258887
1/* Native-dependent code for FreeBSD/amd64. 2 3 Copyright 2003, 2004 Free Software Foundation, Inc. 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" 24#include "regcache.h" 25 26#include "gdb_assert.h" 27#include <signal.h> 28#include <stddef.h> 29#include <sys/types.h> 30#include <sys/ptrace.h> 31#include <sys/sysctl.h> 32#include <sys/user.h> 33#include <machine/reg.h> 34 35#ifdef HAVE_SYS_PROCFS_H 36#include <sys/procfs.h> 37#endif 38 39#ifndef HAVE_GREGSET_T 40typedef struct reg gregset_t; 41#endif 42 43#ifndef HAVE_FPREGSET_T 44typedef struct fpreg fpregset_t; 45#endif 46 47#include "gregset.h" 48#include "amd64-tdep.h" 49#include "amd64-nat.h" 50 51 52/* Offset to the gregset_t location where REG is stored. */ 53#define REG_OFFSET(reg) offsetof (gregset_t, reg) 54 55/* At reg_offset[REGNUM] you'll find the offset to the gregset_t 56 location where the GDB register REGNUM is stored. Unsupported 57 registers are marked with `-1'. */ 58static int reg_offset[] = 59{ 60 REG_OFFSET (r_rax), 61 REG_OFFSET (r_rbx), 62 REG_OFFSET (r_rcx), 63 REG_OFFSET (r_rdx), 64 REG_OFFSET (r_rsi), 65 REG_OFFSET (r_rdi), 66 REG_OFFSET (r_rbp), 67 REG_OFFSET (r_rsp), 68 REG_OFFSET (r_r8), 69 REG_OFFSET (r_r9), 70 REG_OFFSET (r_r10), 71 REG_OFFSET (r_r11), 72 REG_OFFSET (r_r12), 73 REG_OFFSET (r_r13), 74 REG_OFFSET (r_r14), 75 REG_OFFSET (r_r15), 76 REG_OFFSET (r_rip), 77 REG_OFFSET (r_rflags), 78 REG_OFFSET (r_cs), 79 REG_OFFSET (r_ss), 80 -1, 81 -1, 82 -1, 83 -1 84}; 85 86 87/* Mapping between the general-purpose registers in FreeBSD/amd64 88 `struct reg' format and GDB's register cache layout for 89 FreeBSD/i386. 90 91 Note that most FreeBSD/amd64 registers are 64-bit, while the 92 FreeBSD/i386 registers are all 32-bit, but since we're 93 little-endian we get away with that. */ 94 95/* From <machine/reg.h>. */ 96static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] = 97{ 98 14 * 8, 13 * 8, /* %eax, %ecx */ 99 12 * 8, 11 * 8, /* %edx, %ebx */ 100 20 * 8, 10 * 8, /* %esp, %ebp */ 101 9 * 8, 8 * 8, /* %esi, %edi */ 102 17 * 8, 19 * 8, /* %eip, %eflags */ 103 18 * 8, 21 * 8, /* %cs, %ss */ 104 -1, -1, -1, -1 /* %ds, %es, %fs, %gs */ 105}; 106 107 108/* Transfering the registers between GDB, inferiors and core files. */ 109 110/* Fill GDB's register array with the general-purpose register values 111 in *GREGSETP. */ 112 113void 114supply_gregset (gregset_t *gregsetp) 115{ 116 amd64_supply_native_gregset (current_regcache, gregsetp, -1); 117} 118 119/* Fill register REGNUM (if it is a general-purpose register) in 120 *GREGSETPS with the value in GDB's register array. If REGNUM is -1, 121 do this for all registers. */ 122 123void 124fill_gregset (gregset_t *gregsetp, int regnum) 125{ 126 amd64_collect_native_gregset (current_regcache, gregsetp, regnum); 127} 128 129/* Fill GDB's register array with the floating-point register values 130 in *FPREGSETP. */ 131 132void 133supply_fpregset (fpregset_t *fpregsetp) 134{ 135 amd64_supply_fxsave (current_regcache, -1, fpregsetp); 136} 137 138/* Fill register REGNUM (if it is a floating-point register) in 139 *FPREGSETP with the value in GDB's register array. If REGNUM is -1, 140 do this for all registers. */ 141 142void 143fill_fpregset (fpregset_t *fpregsetp, int regnum) 144{ 145 amd64_fill_fxsave ((char *) fpregsetp, regnum); 146} 147 148 149/* Provide a prototype to silence -Wmissing-prototypes. */ 150void _initialize_amd64fbsd_nat (void); 151 152void 153_initialize_amd64fbsd_nat (void) 154{ 155 int offset; 156 157 amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset; 158 amd64_native_gregset64_reg_offset = reg_offset; 159 160 /* To support the recognition of signal handlers, i386bsd-tdep.c 161 hardcodes some constants. Inclusion of this file means that we 162 are compiling a native debugger, which means that we can use the 163 system header files and sysctl(3) to get at the relevant 164 information. */ 165 166#define SC_REG_OFFSET amd64fbsd_sc_reg_offset 167 168 /* We only check the program counter, stack pointer and frame 169 pointer since these members of `struct sigcontext' are essential 170 for providing backtraces. */ 171 172#define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM] 173#define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM] 174#define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM] 175 176 /* Override the default value for the offset of the program counter 177 in the sigcontext structure. */ 178 offset = offsetof (struct sigcontext, sc_rip); 179 180 if (SC_RIP_OFFSET != offset) 181 { 182 warning ("\ 183offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\ 184Please report this to <bug-gdb@gnu.org>.", 185 offset, SC_RIP_OFFSET); 186 } 187 188 SC_RIP_OFFSET = offset; 189 190 /* Likewise for the stack pointer. */ 191 offset = offsetof (struct sigcontext, sc_rsp); 192 193 if (SC_RSP_OFFSET != offset) 194 { 195 warning ("\ 196offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\ 197Please report this to <bug-gdb@gnu.org>.", 198 offset, SC_RSP_OFFSET); 199 } 200 201 SC_RSP_OFFSET = offset; 202 203 /* And the frame pointer. */ 204 offset = offsetof (struct sigcontext, sc_rbp); 205 206 if (SC_RBP_OFFSET != offset) 207 { 208 warning ("\ 209offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\ 210Please report this to <bug-gdb@gnu.org>.", 211 offset, SC_RBP_OFFSET); 212 } 213 214 SC_RBP_OFFSET = offset; 215 216 /* FreeBSD provides a kern.proc.sigtramp sysctl that we can use to 217 locate the sigtramp. That way we can still recognize a sigtramp 218 if its location is changed in a new kernel. */ 219 { 220 int mib[4]; 221 struct kinfo_sigtramp kst; 222 size_t len; 223 224 mib[0] = CTL_KERN; 225 mib[1] = KERN_PROC; 226 mib[2] = KERN_PROC_SIGTRAMP; 227 mib[3] = getpid(); 228 len = sizeof (kst); 229 if (sysctl (mib, sizeof(mib) / sizeof(mib[0]), &kst, &len, NULL, 0) == 0) 230 { 231 amd64fbsd_sigtramp_start_addr = kst.ksigtramp_start; 232 amd64fbsd_sigtramp_end_addr = kst.ksigtramp_end; 233 } 234 } 235} 236