169e0f06dSSimon Schubert /* Native-dependent code for DragonFly/amd64. 269e0f06dSSimon Schubert 38a286ab3SJohn Marino Copyright (C) 2003-2013 Free Software Foundation, Inc. 469e0f06dSSimon Schubert 569e0f06dSSimon Schubert This file is part of GDB. 669e0f06dSSimon Schubert 769e0f06dSSimon Schubert This program is free software; you can redistribute it and/or modify 869e0f06dSSimon Schubert it under the terms of the GNU General Public License as published by 969e0f06dSSimon Schubert the Free Software Foundation; either version 3 of the License, or 1069e0f06dSSimon Schubert (at your option) any later version. 1169e0f06dSSimon Schubert 1269e0f06dSSimon Schubert This program is distributed in the hope that it will be useful, 1369e0f06dSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of 1469e0f06dSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1569e0f06dSSimon Schubert GNU General Public License for more details. 1669e0f06dSSimon Schubert 1769e0f06dSSimon Schubert You should have received a copy of the GNU General Public License 1869e0f06dSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1969e0f06dSSimon Schubert 2069e0f06dSSimon Schubert #include "defs.h" 2169e0f06dSSimon Schubert #include "inferior.h" 2269e0f06dSSimon Schubert #include "regcache.h" 2369e0f06dSSimon Schubert #include "target.h" 248a286ab3SJohn Marino #include "gregset.h" 2569e0f06dSSimon Schubert 2669e0f06dSSimon Schubert #include "gdb_assert.h" 2769e0f06dSSimon Schubert #include <signal.h> 2869e0f06dSSimon Schubert #include <stddef.h> 2969e0f06dSSimon Schubert #include <sys/types.h> 308a286ab3SJohn Marino #include <sys/procfs.h> 3169e0f06dSSimon Schubert #include <sys/ptrace.h> 3269e0f06dSSimon Schubert #include <sys/sysctl.h> 3369e0f06dSSimon Schubert #include <machine/reg.h> 3469e0f06dSSimon Schubert 3569e0f06dSSimon Schubert #include "fbsd-nat.h" 3669e0f06dSSimon Schubert #include "amd64-tdep.h" 3769e0f06dSSimon Schubert #include "amd64-nat.h" 388a286ab3SJohn Marino #include "amd64bsd-nat.h" 398a286ab3SJohn Marino #include "i386-nat.h" 40*e0cb4e00SSascha Wildner 4169e0f06dSSimon Schubert 4269e0f06dSSimon Schubert /* Offset in `struct reg' where MEMBER is stored. */ 4369e0f06dSSimon Schubert #define REG_OFFSET(member) offsetof (struct reg, member) 4469e0f06dSSimon Schubert 4569e0f06dSSimon Schubert /* At amd64dfly64_r_reg_offset[REGNUM] you'll find the offset in 4669e0f06dSSimon Schubert `struct reg' location where the GDB register REGNUM is stored. 4769e0f06dSSimon Schubert Unsupported registers are marked with `-1'. */ 4869e0f06dSSimon Schubert static int amd64dfly64_r_reg_offset[] = 4969e0f06dSSimon Schubert { 5069e0f06dSSimon Schubert REG_OFFSET (r_rax), 5169e0f06dSSimon Schubert REG_OFFSET (r_rbx), 5269e0f06dSSimon Schubert REG_OFFSET (r_rcx), 5369e0f06dSSimon Schubert REG_OFFSET (r_rdx), 5469e0f06dSSimon Schubert REG_OFFSET (r_rsi), 5569e0f06dSSimon Schubert REG_OFFSET (r_rdi), 5669e0f06dSSimon Schubert REG_OFFSET (r_rbp), 5769e0f06dSSimon Schubert REG_OFFSET (r_rsp), 5869e0f06dSSimon Schubert REG_OFFSET (r_r8), 5969e0f06dSSimon Schubert REG_OFFSET (r_r9), 6069e0f06dSSimon Schubert REG_OFFSET (r_r10), 6169e0f06dSSimon Schubert REG_OFFSET (r_r11), 6269e0f06dSSimon Schubert REG_OFFSET (r_r12), 6369e0f06dSSimon Schubert REG_OFFSET (r_r13), 6469e0f06dSSimon Schubert REG_OFFSET (r_r14), 6569e0f06dSSimon Schubert REG_OFFSET (r_r15), 6669e0f06dSSimon Schubert REG_OFFSET (r_rip), 6769e0f06dSSimon Schubert REG_OFFSET (r_rflags), 6869e0f06dSSimon Schubert REG_OFFSET (r_cs), 6969e0f06dSSimon Schubert REG_OFFSET (r_ss), 7069e0f06dSSimon Schubert -1, 7169e0f06dSSimon Schubert -1, 7269e0f06dSSimon Schubert -1, 7369e0f06dSSimon Schubert -1 7469e0f06dSSimon Schubert }; 75*e0cb4e00SSascha Wildner 7669e0f06dSSimon Schubert 7769e0f06dSSimon Schubert /* Mapping between the general-purpose registers in DragonFly/amd64 7869e0f06dSSimon Schubert `struct reg' format and GDB's register cache layout for 7969e0f06dSSimon Schubert DragonFly/i386. 8069e0f06dSSimon Schubert 8169e0f06dSSimon Schubert Note that most DragonFly/amd64 registers are 64-bit, while the 8269e0f06dSSimon Schubert DragonFly/i386 registers are all 32-bit, but since we're 8369e0f06dSSimon Schubert little-endian we get away with that. */ 8469e0f06dSSimon Schubert 8569e0f06dSSimon Schubert /* From <machine/reg.h>. */ 8669e0f06dSSimon Schubert static int amd64dfly32_r_reg_offset[I386_NUM_GREGS] = 8769e0f06dSSimon Schubert { 8869e0f06dSSimon Schubert 14 * 8, 13 * 8, /* %eax, %ecx */ 8969e0f06dSSimon Schubert 12 * 8, 11 * 8, /* %edx, %ebx */ 9069e0f06dSSimon Schubert 20 * 8, 10 * 8, /* %esp, %ebp */ 9169e0f06dSSimon Schubert 9 * 8, 8 * 8, /* %esi, %edi */ 9269e0f06dSSimon Schubert 17 * 8, 19 * 8, /* %eip, %eflags */ 9369e0f06dSSimon Schubert 18 * 8, 21 * 8, /* %cs, %ss */ 9469e0f06dSSimon Schubert -1, -1, -1, -1 /* %ds, %es, %fs, %gs */ 9569e0f06dSSimon Schubert }; 96*e0cb4e00SSascha Wildner 9769e0f06dSSimon Schubert 988a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY 998a286ab3SJohn Marino /* Transfering the registers between GDB, inferiors and core files. */ 1008a286ab3SJohn Marino 1018a286ab3SJohn Marino /* Fill GDB's register array with the general-purpose register values 1028a286ab3SJohn Marino in *GREGSETP. */ 1038a286ab3SJohn Marino 1048a286ab3SJohn Marino void 1058a286ab3SJohn Marino supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) 1068a286ab3SJohn Marino { 1078a286ab3SJohn Marino amd64_supply_native_gregset (regcache, gregsetp, -1); 1088a286ab3SJohn Marino } 1098a286ab3SJohn Marino 1108a286ab3SJohn Marino /* Fill register REGNUM (if it is a general-purpose register) in 1118a286ab3SJohn Marino *GREGSETPS with the value in GDB's register array. If REGNUM is -1, 1128a286ab3SJohn Marino do this for all registers. */ 1138a286ab3SJohn Marino 1148a286ab3SJohn Marino void 1158a286ab3SJohn Marino fill_gregset (const struct regcache *regcache, gdb_gregset_t *gregsetp, int regnum) 1168a286ab3SJohn Marino { 1178a286ab3SJohn Marino amd64_collect_native_gregset (regcache, gregsetp, regnum); 1188a286ab3SJohn Marino } 1198a286ab3SJohn Marino 1208a286ab3SJohn Marino /* Fill GDB's register array with the floating-point register values 1218a286ab3SJohn Marino in *FPREGSETP. */ 1228a286ab3SJohn Marino 1238a286ab3SJohn Marino void 1248a286ab3SJohn Marino supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) 1258a286ab3SJohn Marino { 1268a286ab3SJohn Marino amd64_supply_fxsave (regcache, -1, fpregsetp); 1278a286ab3SJohn Marino } 1288a286ab3SJohn Marino 1298a286ab3SJohn Marino /* Fill register REGNUM (if it is a floating-point register) in 1308a286ab3SJohn Marino *FPREGSETP with the value in GDB's register array. If REGNUM is -1, 1318a286ab3SJohn Marino do this for all registers. */ 1328a286ab3SJohn Marino 1338a286ab3SJohn Marino void 1348a286ab3SJohn Marino fill_fpregset (const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regnum) 1358a286ab3SJohn Marino { 1368a286ab3SJohn Marino amd64_collect_fxsave (regcache, regnum, fpregsetp); 1378a286ab3SJohn Marino } 138*e0cb4e00SSascha Wildner 1398a286ab3SJohn Marino /* Support for debugging kernel virtual memory images. */ 1408a286ab3SJohn Marino 1418a286ab3SJohn Marino #include <sys/types.h> 1428a286ab3SJohn Marino #include <machine/pcb.h> 1438a286ab3SJohn Marino #include <osreldate.h> 1448a286ab3SJohn Marino 1458a286ab3SJohn Marino #include "bsd-kvm.h" 1468a286ab3SJohn Marino 1478a286ab3SJohn Marino static int 1488a286ab3SJohn Marino amd64dfly_supply_pcb (struct regcache *regcache, struct pcb *pcb) 1498a286ab3SJohn Marino { 1508a286ab3SJohn Marino /* The following is true for FreeBSD 5.2: 151*e0cb4e00SSascha Wildner 152*e0cb4e00SSascha Wildner The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, 153*e0cb4e00SSascha Wildner %ds, %es, %fs and %gs. This accounts for all callee-saved 154*e0cb4e00SSascha Wildner registers specified by the psABI and then some. Here %esp 155*e0cb4e00SSascha Wildner contains the stack pointer at the point just after the call to 156*e0cb4e00SSascha Wildner cpu_switch(). From this information we reconstruct the register 157*e0cb4e00SSascha Wildner state as it would like when we just returned from cpu_switch(). */ 1588a286ab3SJohn Marino 1598a286ab3SJohn Marino /* The stack pointer shouldn't be zero. */ 1608a286ab3SJohn Marino if (pcb->pcb_rsp == 0) 1618a286ab3SJohn Marino return 0; 1628a286ab3SJohn Marino 1638a286ab3SJohn Marino pcb->pcb_rsp += 8; 1648a286ab3SJohn Marino regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip); 1658a286ab3SJohn Marino regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx); 1668a286ab3SJohn Marino regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp); 1678a286ab3SJohn Marino regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp); 1688a286ab3SJohn Marino regcache_raw_supply (regcache, 12, &pcb->pcb_r12); 1698a286ab3SJohn Marino regcache_raw_supply (regcache, 13, &pcb->pcb_r13); 1708a286ab3SJohn Marino regcache_raw_supply (regcache, 14, &pcb->pcb_r14); 1718a286ab3SJohn Marino regcache_raw_supply (regcache, 15, &pcb->pcb_r15); 172*e0cb4e00SSascha Wildner #if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075) 173*e0cb4e00SSascha Wildner /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only 174*e0cb4e00SSascha Wildner up until __FreeBSD_version 800074: The removal of these fields 175*e0cb4e00SSascha Wildner occurred on 2009-04-01 while the __FreeBSD_version number was 176*e0cb4e00SSascha Wildner bumped to 800075 on 2009-04-06. So 800075 is the closest version 177*e0cb4e00SSascha Wildner number where we should not try to access these fields. */ 178*e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds); 179*e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es); 180*e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs); 181*e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs); 182*e0cb4e00SSascha Wildner #endif 1838a286ab3SJohn Marino 1848a286ab3SJohn Marino return 1; 1858a286ab3SJohn Marino } 1868a286ab3SJohn Marino #endif /* DFLY_PCB_SUPPLY */ 187*e0cb4e00SSascha Wildner 1888a286ab3SJohn Marino 1898a286ab3SJohn Marino static void (*super_mourn_inferior) (struct target_ops *ops); 1908a286ab3SJohn Marino 191*e0cb4e00SSascha Wildner /* Work around vkernels not having PT_{GET,SET}DBREGS via ptrace(2) support. */ 192d84c7e63SAntonio Huete Jimenez static int 193d84c7e63SAntonio Huete Jimenez is_vkernel(void) 194d84c7e63SAntonio Huete Jimenez { 195d84c7e63SAntonio Huete Jimenez size_t len; 196d84c7e63SAntonio Huete Jimenez char buf[64]; 197d84c7e63SAntonio Huete Jimenez 198d84c7e63SAntonio Huete Jimenez len = sizeof(buf); 199*e0cb4e00SSascha Wildner if (sysctlbyname("kern.vmm_guest", buf, &len, NULL, 0) < 0) 200d84c7e63SAntonio Huete Jimenez return 0; 201d84c7e63SAntonio Huete Jimenez if (strncmp("vkernel", buf, len) == 0) 202d84c7e63SAntonio Huete Jimenez return 1; 203d84c7e63SAntonio Huete Jimenez else 204d84c7e63SAntonio Huete Jimenez return 0; 205d84c7e63SAntonio Huete Jimenez } 206d84c7e63SAntonio Huete Jimenez 2078a286ab3SJohn Marino static void 2088a286ab3SJohn Marino amd64dfly_mourn_inferior (struct target_ops *ops) 2098a286ab3SJohn Marino { 2108a286ab3SJohn Marino #ifdef HAVE_PT_GETDBREGS 211*e0cb4e00SSascha Wildner if (!isvkernel()) 2128a286ab3SJohn Marino i386_cleanup_dregs (); 2138a286ab3SJohn Marino #endif 2148a286ab3SJohn Marino super_mourn_inferior (ops); 2158a286ab3SJohn Marino } 2168a286ab3SJohn Marino 21769e0f06dSSimon Schubert /* Provide a prototype to silence -Wmissing-prototypes. */ 21869e0f06dSSimon Schubert void _initialize_amd64dfly_nat (void); 21969e0f06dSSimon Schubert 22069e0f06dSSimon Schubert void 22169e0f06dSSimon Schubert _initialize_amd64dfly_nat (void) 22269e0f06dSSimon Schubert { 22369e0f06dSSimon Schubert struct target_ops *t; 22469e0f06dSSimon Schubert int offset; 22569e0f06dSSimon Schubert 22669e0f06dSSimon Schubert amd64_native_gregset32_reg_offset = amd64dfly32_r_reg_offset; 22769e0f06dSSimon Schubert amd64_native_gregset64_reg_offset = amd64dfly64_r_reg_offset; 22869e0f06dSSimon Schubert 22969e0f06dSSimon Schubert /* Add some extra features to the common *BSD/i386 target. */ 23069e0f06dSSimon Schubert t = amd64bsd_target (); 2318a286ab3SJohn Marino 2328a286ab3SJohn Marino #ifdef HAVE_PT_GETDBREGS 2338a286ab3SJohn Marino 234d84c7e63SAntonio Huete Jimenez if (!is_vkernel()) { 2358a286ab3SJohn Marino i386_use_watchpoints (t); 2368a286ab3SJohn Marino 2378a286ab3SJohn Marino i386_dr_low.set_control = amd64bsd_dr_set_control; 2388a286ab3SJohn Marino i386_dr_low.set_addr = amd64bsd_dr_set_addr; 2398a286ab3SJohn Marino i386_dr_low.get_addr = amd64bsd_dr_get_addr; 2408a286ab3SJohn Marino i386_dr_low.get_status = amd64bsd_dr_get_status; 2418a286ab3SJohn Marino i386_dr_low.get_control = amd64bsd_dr_get_control; 2428a286ab3SJohn Marino i386_set_debug_register_length (8); 243d84c7e63SAntonio Huete Jimenez } 2448a286ab3SJohn Marino 2458a286ab3SJohn Marino #endif /* HAVE_PT_GETDBREGS */ 2468a286ab3SJohn Marino 2478a286ab3SJohn Marino super_mourn_inferior = t->to_mourn_inferior; 2488a286ab3SJohn Marino t->to_mourn_inferior = amd64dfly_mourn_inferior; 2498a286ab3SJohn Marino 25069e0f06dSSimon Schubert t->to_pid_to_exec_file = fbsd_pid_to_exec_file; 25169e0f06dSSimon Schubert t->to_find_memory_regions = fbsd_find_memory_regions; 25269e0f06dSSimon Schubert t->to_make_corefile_notes = fbsd_make_corefile_notes; 25369e0f06dSSimon Schubert add_target (t); 25469e0f06dSSimon Schubert 2558a286ab3SJohn Marino #ifdef DFLY_PCB_SUPPLY 2568a286ab3SJohn Marino /* Support debugging kernel virtual memory images. */ 2578a286ab3SJohn Marino bsd_kvm_add_target (amd64dfly_supply_pcb); 2588a286ab3SJohn Marino #endif 2598a286ab3SJohn Marino 26069e0f06dSSimon Schubert /* To support the recognition of signal handlers, i386bsd-tdep.c 261*e0cb4e00SSascha Wildner hardcodes some constants. Inclusion of this file means that we 262*e0cb4e00SSascha Wildner are compiling a native debugger, which means that we can use the 263*e0cb4e00SSascha Wildner system header files and sysctl(3) to get at the relevant 264*e0cb4e00SSascha Wildner information. */ 26569e0f06dSSimon Schubert 26669e0f06dSSimon Schubert #define SC_REG_OFFSET amd64dfly_sc_reg_offset 26769e0f06dSSimon Schubert 268*e0cb4e00SSascha Wildner /* We only check the program counter, stack pointer and frame 269*e0cb4e00SSascha Wildner pointer since these members of `struct sigcontext' are essential 270*e0cb4e00SSascha Wildner for providing backtraces. */ 27169e0f06dSSimon Schubert 27269e0f06dSSimon Schubert #define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM] 27369e0f06dSSimon Schubert #define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM] 27469e0f06dSSimon Schubert #define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM] 27569e0f06dSSimon Schubert 276*e0cb4e00SSascha Wildner /* Override the default value for the offset of the program counter 277*e0cb4e00SSascha Wildner in the sigcontext structure. */ 27869e0f06dSSimon Schubert offset = offsetof (struct sigcontext, sc_rip); 27969e0f06dSSimon Schubert 280*e0cb4e00SSascha Wildner if (SC_RIP_OFFSET != offset) 281*e0cb4e00SSascha Wildner { 28269e0f06dSSimon Schubert warning (_("\ 28369e0f06dSSimon Schubert offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\ 28469e0f06dSSimon Schubert Please report this to <bug-gdb@gnu.org>."), 28569e0f06dSSimon Schubert offset, SC_RIP_OFFSET); 28669e0f06dSSimon Schubert } 287*e0cb4e00SSascha Wildner 28869e0f06dSSimon Schubert SC_RIP_OFFSET = offset; 28969e0f06dSSimon Schubert 29069e0f06dSSimon Schubert /* Likewise for the stack pointer. */ 29169e0f06dSSimon Schubert offset = offsetof (struct sigcontext, sc_rsp); 29269e0f06dSSimon Schubert 293*e0cb4e00SSascha Wildner if (SC_RSP_OFFSET != offset) 294*e0cb4e00SSascha Wildner { 29569e0f06dSSimon Schubert warning (_("\ 29669e0f06dSSimon Schubert offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\ 29769e0f06dSSimon Schubert Please report this to <bug-gdb@gnu.org>."), 29869e0f06dSSimon Schubert offset, SC_RSP_OFFSET); 29969e0f06dSSimon Schubert } 300*e0cb4e00SSascha Wildner 30169e0f06dSSimon Schubert SC_RSP_OFFSET = offset; 30269e0f06dSSimon Schubert 30369e0f06dSSimon Schubert /* And the frame pointer. */ 30469e0f06dSSimon Schubert offset = offsetof (struct sigcontext, sc_rbp); 30569e0f06dSSimon Schubert 306*e0cb4e00SSascha Wildner if (SC_RBP_OFFSET != offset) 307*e0cb4e00SSascha Wildner { 30869e0f06dSSimon Schubert warning (_("\ 30969e0f06dSSimon Schubert offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\ 31069e0f06dSSimon Schubert Please report this to <bug-gdb@gnu.org>."), 31169e0f06dSSimon Schubert offset, SC_RBP_OFFSET); 31269e0f06dSSimon Schubert } 313*e0cb4e00SSascha Wildner 31469e0f06dSSimon Schubert SC_RBP_OFFSET = offset; 31569e0f06dSSimon Schubert 31669e0f06dSSimon Schubert /* DragonFly provides a kern.ps_strings sysctl that we can use to 317*e0cb4e00SSascha Wildner locate the sigtramp. That way we can still recognize a sigtramp 318*e0cb4e00SSascha Wildner if its location is changed in a new kernel. Of course this is 319*e0cb4e00SSascha Wildner still based on the assumption that the sigtramp is placed 320*e0cb4e00SSascha Wildner directly under the location where the program arguments and 321*e0cb4e00SSascha Wildner environment can be found. */ 32269e0f06dSSimon Schubert { 32369e0f06dSSimon Schubert int mib[2]; 32469e0f06dSSimon Schubert long ps_strings; 32569e0f06dSSimon Schubert size_t len; 32669e0f06dSSimon Schubert 32769e0f06dSSimon Schubert mib[0] = CTL_KERN; 32869e0f06dSSimon Schubert mib[1] = KERN_PS_STRINGS; 32969e0f06dSSimon Schubert len = sizeof (ps_strings); 330*e0cb4e00SSascha Wildner if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0) 331*e0cb4e00SSascha Wildner { 33269e0f06dSSimon Schubert amd64dfly_sigtramp_start_addr = ps_strings - 32; 33369e0f06dSSimon Schubert amd64dfly_sigtramp_end_addr = ps_strings; 33469e0f06dSSimon Schubert } 33569e0f06dSSimon Schubert } 33669e0f06dSSimon Schubert } 337