1 /* Native-dependent code for FreeBSD/amd64. 2 3 Copyright (C) 2003-2020 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 3 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, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "inferior.h" 22 #include "regcache.h" 23 #include "target.h" 24 25 #include <signal.h> 26 #include <sys/types.h> 27 #include <sys/ptrace.h> 28 #include <sys/sysctl.h> 29 #include <sys/user.h> 30 #include <machine/reg.h> 31 32 #include "fbsd-nat.h" 33 #include "amd64-tdep.h" 34 #include "amd64-nat.h" 35 #include "amd64-bsd-nat.h" 36 #include "x86-nat.h" 37 #include "gdbsupport/x86-xstate.h" 38 39 40 class amd64_fbsd_nat_target final 41 : public amd64_bsd_nat_target<fbsd_nat_target> 42 { 43 public: 44 /* Add some extra features to the common *BSD/amd64 target. */ 45 const struct target_desc *read_description () override; 46 47 #if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO) 48 bool supports_stopped_by_hw_breakpoint () override; 49 #endif 50 }; 51 52 static amd64_fbsd_nat_target the_amd64_fbsd_nat_target; 53 54 /* Offset in `struct reg' where MEMBER is stored. */ 55 #define REG_OFFSET(member) offsetof (struct reg, member) 56 57 /* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in 58 `struct reg' location where the GDB register REGNUM is stored. 59 Unsupported registers are marked with `-1'. */ 60 static int amd64fbsd64_r_reg_offset[] = 61 { 62 REG_OFFSET (r_rax), 63 REG_OFFSET (r_rbx), 64 REG_OFFSET (r_rcx), 65 REG_OFFSET (r_rdx), 66 REG_OFFSET (r_rsi), 67 REG_OFFSET (r_rdi), 68 REG_OFFSET (r_rbp), 69 REG_OFFSET (r_rsp), 70 REG_OFFSET (r_r8), 71 REG_OFFSET (r_r9), 72 REG_OFFSET (r_r10), 73 REG_OFFSET (r_r11), 74 REG_OFFSET (r_r12), 75 REG_OFFSET (r_r13), 76 REG_OFFSET (r_r14), 77 REG_OFFSET (r_r15), 78 REG_OFFSET (r_rip), 79 REG_OFFSET (r_rflags), 80 REG_OFFSET (r_cs), 81 REG_OFFSET (r_ss), 82 -1, 83 -1, 84 -1, 85 -1 86 }; 87 88 89 /* Mapping between the general-purpose registers in FreeBSD/amd64 90 `struct reg' format and GDB's register cache layout for 91 FreeBSD/i386. 92 93 Note that most FreeBSD/amd64 registers are 64-bit, while the 94 FreeBSD/i386 registers are all 32-bit, but since we're 95 little-endian we get away with that. */ 96 97 /* From <machine/reg.h>. */ 98 static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] = 99 { 100 14 * 8, 13 * 8, /* %eax, %ecx */ 101 12 * 8, 11 * 8, /* %edx, %ebx */ 102 20 * 8, 10 * 8, /* %esp, %ebp */ 103 9 * 8, 8 * 8, /* %esi, %edi */ 104 17 * 8, 19 * 8, /* %eip, %eflags */ 105 18 * 8, 21 * 8, /* %cs, %ss */ 106 -1, -1, -1, -1 /* %ds, %es, %fs, %gs */ 107 }; 108 109 110 /* Support for debugging kernel virtual memory images. */ 111 112 #include <machine/pcb.h> 113 #include <osreldate.h> 114 115 #include "bsd-kvm.h" 116 117 static int 118 amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) 119 { 120 /* The following is true for FreeBSD 5.2: 121 122 The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, 123 %ds, %es, %fs and %gs. This accounts for all callee-saved 124 registers specified by the psABI and then some. Here %esp 125 contains the stack pointer at the point just after the call to 126 cpu_switch(). From this information we reconstruct the register 127 state as it would like when we just returned from cpu_switch(). */ 128 129 /* The stack pointer shouldn't be zero. */ 130 if (pcb->pcb_rsp == 0) 131 return 0; 132 133 pcb->pcb_rsp += 8; 134 regcache->raw_supply (AMD64_RIP_REGNUM, &pcb->pcb_rip); 135 regcache->raw_supply (AMD64_RBX_REGNUM, &pcb->pcb_rbx); 136 regcache->raw_supply (AMD64_RSP_REGNUM, &pcb->pcb_rsp); 137 regcache->raw_supply (AMD64_RBP_REGNUM, &pcb->pcb_rbp); 138 regcache->raw_supply (12, &pcb->pcb_r12); 139 regcache->raw_supply (13, &pcb->pcb_r13); 140 regcache->raw_supply (14, &pcb->pcb_r14); 141 regcache->raw_supply (15, &pcb->pcb_r15); 142 #if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075) 143 /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only 144 up until __FreeBSD_version 800074: The removal of these fields 145 occurred on 2009-04-01 while the __FreeBSD_version number was 146 bumped to 800075 on 2009-04-06. So 800075 is the closest version 147 number where we should not try to access these fields. */ 148 regcache->raw_supply (AMD64_DS_REGNUM, &pcb->pcb_ds); 149 regcache->raw_supply (AMD64_ES_REGNUM, &pcb->pcb_es); 150 regcache->raw_supply (AMD64_FS_REGNUM, &pcb->pcb_fs); 151 regcache->raw_supply (AMD64_GS_REGNUM, &pcb->pcb_gs); 152 #endif 153 154 return 1; 155 } 156 157 158 /* Implement the read_description method. */ 159 160 const struct target_desc * 161 amd64_fbsd_nat_target::read_description () 162 { 163 #ifdef PT_GETXSTATE_INFO 164 static int xsave_probed; 165 static uint64_t xcr0; 166 #endif 167 struct reg regs; 168 int is64; 169 170 if (ptrace (PT_GETREGS, inferior_ptid.pid (), 171 (PTRACE_TYPE_ARG3) ®s, 0) == -1) 172 perror_with_name (_("Couldn't get registers")); 173 is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL)); 174 #ifdef PT_GETXSTATE_INFO 175 if (!xsave_probed) 176 { 177 struct ptrace_xstate_info info; 178 179 if (ptrace (PT_GETXSTATE_INFO, inferior_ptid.pid (), 180 (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) 181 { 182 x86bsd_xsave_len = info.xsave_len; 183 xcr0 = info.xsave_mask; 184 } 185 xsave_probed = 1; 186 } 187 188 if (x86bsd_xsave_len != 0) 189 { 190 if (is64) 191 return amd64_target_description (xcr0, true); 192 else 193 return i386_target_description (xcr0, true); 194 } 195 #endif 196 if (is64) 197 return amd64_target_description (X86_XSTATE_SSE_MASK, true); 198 else 199 return i386_target_description (X86_XSTATE_SSE_MASK, true); 200 } 201 202 #if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO) 203 /* Implement the supports_stopped_by_hw_breakpoints method. */ 204 205 bool 206 amd64_fbsd_nat_target::supports_stopped_by_hw_breakpoint () 207 { 208 return true; 209 } 210 #endif 211 212 void _initialize_amd64fbsd_nat (); 213 void 214 _initialize_amd64fbsd_nat () 215 { 216 int offset; 217 218 amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset; 219 amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset; 220 221 add_inf_child_target (&the_amd64_fbsd_nat_target); 222 223 /* Support debugging kernel virtual memory images. */ 224 bsd_kvm_add_target (amd64fbsd_supply_pcb); 225 226 /* To support the recognition of signal handlers, i386-bsd-tdep.c 227 hardcodes some constants. Inclusion of this file means that we 228 are compiling a native debugger, which means that we can use the 229 system header files and sysctl(3) to get at the relevant 230 information. */ 231 232 #define SC_REG_OFFSET amd64fbsd_sc_reg_offset 233 234 /* We only check the program counter, stack pointer and frame 235 pointer since these members of `struct sigcontext' are essential 236 for providing backtraces. */ 237 238 #define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM] 239 #define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM] 240 #define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM] 241 242 /* Override the default value for the offset of the program counter 243 in the sigcontext structure. */ 244 offset = offsetof (struct sigcontext, sc_rip); 245 246 if (SC_RIP_OFFSET != offset) 247 { 248 warning (_("\ 249 offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\ 250 Please report this to <bug-gdb@gnu.org>."), 251 offset, SC_RIP_OFFSET); 252 } 253 254 SC_RIP_OFFSET = offset; 255 256 /* Likewise for the stack pointer. */ 257 offset = offsetof (struct sigcontext, sc_rsp); 258 259 if (SC_RSP_OFFSET != offset) 260 { 261 warning (_("\ 262 offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\ 263 Please report this to <bug-gdb@gnu.org>."), 264 offset, SC_RSP_OFFSET); 265 } 266 267 SC_RSP_OFFSET = offset; 268 269 /* And the frame pointer. */ 270 offset = offsetof (struct sigcontext, sc_rbp); 271 272 if (SC_RBP_OFFSET != offset) 273 { 274 warning (_("\ 275 offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\ 276 Please report this to <bug-gdb@gnu.org>."), 277 offset, SC_RBP_OFFSET); 278 } 279 280 SC_RBP_OFFSET = offset; 281 282 #ifdef KERN_PROC_SIGTRAMP 283 /* Normally signal frames are detected via amd64fbsd_sigtramp_p. 284 However, FreeBSD 9.2 through 10.1 do not include the page holding 285 the signal code in core dumps. These releases do provide a 286 kern.proc.sigtramp.<pid> sysctl that returns the location of the 287 signal trampoline for a running process. We fetch the location 288 of the current (gdb) process and use this to identify signal 289 frames in core dumps from these releases. Note that this only 290 works for core dumps of 64-bit (FreeBSD/amd64) processes and does 291 not handle core dumps of 32-bit (FreeBSD/i386) processes. */ 292 { 293 int mib[4]; 294 struct kinfo_sigtramp kst; 295 size_t len; 296 297 mib[0] = CTL_KERN; 298 mib[1] = KERN_PROC; 299 mib[2] = KERN_PROC_SIGTRAMP; 300 mib[3] = getpid (); 301 len = sizeof (kst); 302 if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) 303 { 304 amd64fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start; 305 amd64fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end; 306 } 307 } 308 #endif 309 } 310