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"
40e0cb4e00SSascha 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 };
75e0cb4e00SSascha 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 };
96e0cb4e00SSascha 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
supply_gregset(struct regcache * regcache,const gregset_t * gregsetp)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
fill_gregset(const struct regcache * regcache,gdb_gregset_t * gregsetp,int regnum)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
supply_fpregset(struct regcache * regcache,const fpregset_t * fpregsetp)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
fill_fpregset(const struct regcache * regcache,gdb_fpregset_t * fpregsetp,int regnum)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 }
138e0cb4e00SSascha 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
amd64dfly_supply_pcb(struct regcache * regcache,struct pcb * pcb)1488a286ab3SJohn Marino amd64dfly_supply_pcb (struct regcache *regcache, struct pcb *pcb)
1498a286ab3SJohn Marino {
1508a286ab3SJohn Marino /* The following is true for FreeBSD 5.2:
151e0cb4e00SSascha Wildner
152e0cb4e00SSascha Wildner The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15,
153e0cb4e00SSascha Wildner %ds, %es, %fs and %gs. This accounts for all callee-saved
154e0cb4e00SSascha Wildner registers specified by the psABI and then some. Here %esp
155e0cb4e00SSascha Wildner contains the stack pointer at the point just after the call to
156e0cb4e00SSascha Wildner cpu_switch(). From this information we reconstruct the register
157e0cb4e00SSascha 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);
172e0cb4e00SSascha Wildner #if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075)
173e0cb4e00SSascha Wildner /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only
174e0cb4e00SSascha Wildner up until __FreeBSD_version 800074: The removal of these fields
175e0cb4e00SSascha Wildner occurred on 2009-04-01 while the __FreeBSD_version number was
176e0cb4e00SSascha Wildner bumped to 800075 on 2009-04-06. So 800075 is the closest version
177e0cb4e00SSascha Wildner number where we should not try to access these fields. */
178e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds);
179e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es);
180e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs);
181e0cb4e00SSascha Wildner regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs);
182e0cb4e00SSascha Wildner #endif
1838a286ab3SJohn Marino
1848a286ab3SJohn Marino return 1;
1858a286ab3SJohn Marino }
1868a286ab3SJohn Marino #endif /* DFLY_PCB_SUPPLY */
187e0cb4e00SSascha Wildner
1888a286ab3SJohn Marino
1898a286ab3SJohn Marino static void (*super_mourn_inferior) (struct target_ops *ops);
1908a286ab3SJohn Marino
191e0cb4e00SSascha Wildner /* Work around vkernels not having PT_{GET,SET}DBREGS via ptrace(2) support. */
192d84c7e63SAntonio Huete Jimenez static int
is_vkernel(void)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);
199e0cb4e00SSascha 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
amd64dfly_mourn_inferior(struct target_ops * ops)2088a286ab3SJohn Marino amd64dfly_mourn_inferior (struct target_ops *ops)
2098a286ab3SJohn Marino {
2108a286ab3SJohn Marino #ifdef HAVE_PT_GETDBREGS
211*28800651SSepherosa Ziehau if (!is_vkernel())
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
_initialize_amd64dfly_nat(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
261e0cb4e00SSascha Wildner hardcodes some constants. Inclusion of this file means that we
262e0cb4e00SSascha Wildner are compiling a native debugger, which means that we can use the
263e0cb4e00SSascha Wildner system header files and sysctl(3) to get at the relevant
264e0cb4e00SSascha Wildner information. */
26569e0f06dSSimon Schubert
26669e0f06dSSimon Schubert #define SC_REG_OFFSET amd64dfly_sc_reg_offset
26769e0f06dSSimon Schubert
268e0cb4e00SSascha Wildner /* We only check the program counter, stack pointer and frame
269e0cb4e00SSascha Wildner pointer since these members of `struct sigcontext' are essential
270e0cb4e00SSascha 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
276e0cb4e00SSascha Wildner /* Override the default value for the offset of the program counter
277e0cb4e00SSascha Wildner in the sigcontext structure. */
27869e0f06dSSimon Schubert offset = offsetof (struct sigcontext, sc_rip);
27969e0f06dSSimon Schubert
280e0cb4e00SSascha Wildner if (SC_RIP_OFFSET != offset)
281e0cb4e00SSascha 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 }
287e0cb4e00SSascha 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
293e0cb4e00SSascha Wildner if (SC_RSP_OFFSET != offset)
294e0cb4e00SSascha 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 }
300e0cb4e00SSascha 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
306e0cb4e00SSascha Wildner if (SC_RBP_OFFSET != offset)
307e0cb4e00SSascha 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 }
313e0cb4e00SSascha Wildner
31469e0f06dSSimon Schubert SC_RBP_OFFSET = offset;
31569e0f06dSSimon Schubert
31669e0f06dSSimon Schubert /* DragonFly provides a kern.ps_strings sysctl that we can use to
317e0cb4e00SSascha Wildner locate the sigtramp. That way we can still recognize a sigtramp
318e0cb4e00SSascha Wildner if its location is changed in a new kernel. Of course this is
319e0cb4e00SSascha Wildner still based on the assumption that the sigtramp is placed
320e0cb4e00SSascha Wildner directly under the location where the program arguments and
321e0cb4e00SSascha 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);
330e0cb4e00SSascha Wildner if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
331e0cb4e00SSascha 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