1 /* Native-dependent code for DragonFly/amd64.
3 Copyright (C) 2003-2013 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
26 #include "gdb_assert.h"
29 #include <sys/types.h>
30 #include <sys/procfs.h>
31 #include <sys/ptrace.h>
32 #include <sys/sysctl.h>
33 #include <machine/reg.h>
36 #include "amd64-tdep.h"
37 #include "amd64-nat.h"
38 #include "amd64bsd-nat.h"
41 /* Offset in `struct reg' where MEMBER is stored. */
42 #define REG_OFFSET(member) offsetof (struct reg, member)
44 /* At amd64dfly64_r_reg_offset[REGNUM] you'll find the offset in
45 `struct reg' location where the GDB register REGNUM is stored.
46 Unsupported registers are marked with `-1'. */
47 static int amd64dfly64_r_reg_offset[] =
75 /* Mapping between the general-purpose registers in DragonFly/amd64
76 `struct reg' format and GDB's register cache layout for
79 Note that most DragonFly/amd64 registers are 64-bit, while the
80 DragonFly/i386 registers are all 32-bit, but since we're
81 little-endian we get away with that. */
83 /* From <machine/reg.h>. */
84 static int amd64dfly32_r_reg_offset[I386_NUM_GREGS] =
86 14 * 8, 13 * 8, /* %eax, %ecx */
87 12 * 8, 11 * 8, /* %edx, %ebx */
88 20 * 8, 10 * 8, /* %esp, %ebp */
89 9 * 8, 8 * 8, /* %esi, %edi */
90 17 * 8, 19 * 8, /* %eip, %eflags */
91 18 * 8, 21 * 8, /* %cs, %ss */
92 -1, -1, -1, -1 /* %ds, %es, %fs, %gs */
95 #ifdef DFLY_PCB_SUPPLY
96 /* Transfering the registers between GDB, inferiors and core files. */
98 /* Fill GDB's register array with the general-purpose register values
102 supply_gregset(struct regcache *regcache, const gregset_t * gregsetp)
104 amd64_supply_native_gregset(regcache, gregsetp, -1);
107 /* Fill register REGNUM (if it is a general-purpose register) in
108 *GREGSETPS with the value in GDB's register array. If REGNUM is -1,
109 do this for all registers. */
112 fill_gregset(const struct regcache *regcache, gdb_gregset_t * gregsetp, int regnum)
114 amd64_collect_native_gregset(regcache, gregsetp, regnum);
117 /* Fill GDB's register array with the floating-point register values
121 supply_fpregset(struct regcache *regcache, const fpregset_t * fpregsetp)
123 amd64_supply_fxsave(regcache, -1, fpregsetp);
126 /* Fill register REGNUM (if it is a floating-point register) in
127 *FPREGSETP with the value in GDB's register array. If REGNUM is -1,
128 do this for all registers. */
131 fill_fpregset(const struct regcache *regcache, gdb_fpregset_t * fpregsetp, int regnum)
133 amd64_collect_fxsave(regcache, regnum, fpregsetp);
136 /* Support for debugging kernel virtual memory images. */
138 #include <sys/types.h>
139 #include <machine/pcb.h>
140 #include <osreldate.h>
145 amd64dfly_supply_pcb(struct regcache *regcache, struct pcb *pcb)
147 /* The following is true for FreeBSD 5.2:
149 * The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, %ds,
150 * %es, %fs and %gs. This accounts for all callee-saved registers
151 * specified by the psABI and then some. Here %esp contains the stack
152 * pointer at the point just after the call to cpu_switch(). From
153 * this information we reconstruct the register state as it would like
154 * when we just returned from cpu_switch(). */
156 /* The stack pointer shouldn't be zero. */
157 if (pcb->pcb_rsp == 0)
161 regcache_raw_supply(regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip);
162 regcache_raw_supply(regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx);
163 regcache_raw_supply(regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp);
164 regcache_raw_supply(regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp);
165 regcache_raw_supply(regcache, 12, &pcb->pcb_r12);
166 regcache_raw_supply(regcache, 13, &pcb->pcb_r13);
167 regcache_raw_supply(regcache, 14, &pcb->pcb_r14);
168 regcache_raw_supply(regcache, 15, &pcb->pcb_r15);
169 #if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075)
170 /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only up
171 * until __FreeBSD_version 800074: The removal of these fields
172 * occurred on 2009-04-01 while the __FreeBSD_version number was
173 * bumped to 800075 on 2009-04-06. So 800075 is the closest version
174 * number where we should not try to access these fields. */
175 regcache_raw_supply(regcache, AMD64_DS_REGNUM, &pcb->pcb_ds);
176 regcache_raw_supply(regcache, AMD64_ES_REGNUM, &pcb->pcb_es);
177 regcache_raw_supply(regcache, AMD64_FS_REGNUM, &pcb->pcb_fs);
178 regcache_raw_supply(regcache, AMD64_GS_REGNUM, &pcb->pcb_gs);
183 #endif /* DFLY_PCB_SUPPLY */
185 static void (*super_mourn_inferior) (struct target_ops *ops);
188 amd64dfly_mourn_inferior(struct target_ops *ops)
190 #ifdef HAVE_PT_GETDBREGS
191 i386_cleanup_dregs();
193 super_mourn_inferior(ops);
196 /* Provide a prototype to silence -Wmissing-prototypes. */
197 void _initialize_amd64dfly_nat(void);
200 _initialize_amd64dfly_nat(void)
202 struct target_ops *t;
205 amd64_native_gregset32_reg_offset = amd64dfly32_r_reg_offset;
206 amd64_native_gregset64_reg_offset = amd64dfly64_r_reg_offset;
208 /* Add some extra features to the common *BSD/i386 target. */
209 t = amd64bsd_target();
211 #ifdef HAVE_PT_GETDBREGS
213 i386_use_watchpoints(t);
215 i386_dr_low.set_control = amd64bsd_dr_set_control;
216 i386_dr_low.set_addr = amd64bsd_dr_set_addr;
217 i386_dr_low.get_addr = amd64bsd_dr_get_addr;
218 i386_dr_low.get_status = amd64bsd_dr_get_status;
219 i386_dr_low.get_control = amd64bsd_dr_get_control;
220 i386_set_debug_register_length(8);
222 #endif /* HAVE_PT_GETDBREGS */
224 super_mourn_inferior = t->to_mourn_inferior;
225 t->to_mourn_inferior = amd64dfly_mourn_inferior;
227 t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
228 t->to_find_memory_regions = fbsd_find_memory_regions;
229 t->to_make_corefile_notes = fbsd_make_corefile_notes;
232 #ifdef DFLY_PCB_SUPPLY
233 /* Support debugging kernel virtual memory images. */
234 bsd_kvm_add_target(amd64dfly_supply_pcb);
237 /* To support the recognition of signal handlers, i386bsd-tdep.c
238 * hardcodes some constants. Inclusion of this file means that we are
239 * compiling a native debugger, which means that we can use the system
240 * header files and sysctl(3) to get at the relevant information. */
242 #define SC_REG_OFFSET amd64dfly_sc_reg_offset
244 /* We only check the program counter, stack pointer and frame pointer
245 * since these members of `struct sigcontext' are essential for
246 * providing backtraces. */
248 #define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
249 #define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
250 #define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
252 /* Override the default value for the offset of the program counter in
253 * the sigcontext structure. */
254 offset = offsetof(struct sigcontext, sc_rip);
256 if (SC_RIP_OFFSET != offset) {
258 offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
259 Please report this to <bug-gdb@gnu.org>."),
260 offset, SC_RIP_OFFSET);
262 SC_RIP_OFFSET = offset;
264 /* Likewise for the stack pointer. */
265 offset = offsetof(struct sigcontext, sc_rsp);
267 if (SC_RSP_OFFSET != offset) {
269 offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
270 Please report this to <bug-gdb@gnu.org>."),
271 offset, SC_RSP_OFFSET);
273 SC_RSP_OFFSET = offset;
275 /* And the frame pointer. */
276 offset = offsetof(struct sigcontext, sc_rbp);
278 if (SC_RBP_OFFSET != offset) {
280 offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
281 Please report this to <bug-gdb@gnu.org>."),
282 offset, SC_RBP_OFFSET);
284 SC_RBP_OFFSET = offset;
286 /* DragonFly provides a kern.ps_strings sysctl that we can use to
287 * locate the sigtramp. That way we can still recognize a sigtramp if
288 * its location is changed in a new kernel. Of course this is still
289 * based on the assumption that the sigtramp is placed directly under
290 * the location where the program arguments and environment can be
298 mib[1] = KERN_PS_STRINGS;
299 len = sizeof(ps_strings);
300 if (sysctl(mib, 2, &ps_strings, &len, NULL, 0) == 0) {
301 amd64dfly_sigtramp_start_addr = ps_strings - 32;
302 amd64dfly_sigtramp_end_addr = ps_strings;