1b725ae77Skettenis /* Native-dependent code for FreeBSD/amd64.
2b725ae77Skettenis
3b725ae77Skettenis Copyright 2003, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis
5b725ae77Skettenis This file is part of GDB.
6b725ae77Skettenis
7b725ae77Skettenis This program is free software; you can redistribute it and/or modify
8b725ae77Skettenis it under the terms of the GNU General Public License as published by
9b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
10b725ae77Skettenis (at your option) any later version.
11b725ae77Skettenis
12b725ae77Skettenis This program is distributed in the hope that it will be useful,
13b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
14b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15b725ae77Skettenis GNU General Public License for more details.
16b725ae77Skettenis
17b725ae77Skettenis You should have received a copy of the GNU General Public License
18b725ae77Skettenis along with this program; if not, write to the Free Software
19b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
20b725ae77Skettenis Boston, MA 02111-1307, USA. */
21b725ae77Skettenis
22b725ae77Skettenis #include "defs.h"
23b725ae77Skettenis #include "inferior.h"
24b725ae77Skettenis #include "regcache.h"
25*11efff7fSkettenis #include "target.h"
26b725ae77Skettenis
27b725ae77Skettenis #include "gdb_assert.h"
28b725ae77Skettenis #include <signal.h>
29b725ae77Skettenis #include <stddef.h>
30b725ae77Skettenis #include <sys/types.h>
31b725ae77Skettenis #include <sys/ptrace.h>
32b725ae77Skettenis #include <sys/sysctl.h>
33b725ae77Skettenis #include <machine/reg.h>
34b725ae77Skettenis
35*11efff7fSkettenis #include "fbsd-nat.h"
36b725ae77Skettenis #include "amd64-tdep.h"
37b725ae77Skettenis #include "amd64-nat.h"
38b725ae77Skettenis
39b725ae77Skettenis
40*11efff7fSkettenis /* Offset in `struct reg' where MEMBER is stored. */
41*11efff7fSkettenis #define REG_OFFSET(member) offsetof (struct reg, member)
42b725ae77Skettenis
43*11efff7fSkettenis /* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in
44*11efff7fSkettenis `struct reg' location where the GDB register REGNUM is stored.
45*11efff7fSkettenis Unsupported registers are marked with `-1'. */
46*11efff7fSkettenis static int amd64fbsd64_r_reg_offset[] =
47b725ae77Skettenis {
48b725ae77Skettenis REG_OFFSET (r_rax),
49b725ae77Skettenis REG_OFFSET (r_rbx),
50b725ae77Skettenis REG_OFFSET (r_rcx),
51b725ae77Skettenis REG_OFFSET (r_rdx),
52b725ae77Skettenis REG_OFFSET (r_rsi),
53b725ae77Skettenis REG_OFFSET (r_rdi),
54b725ae77Skettenis REG_OFFSET (r_rbp),
55b725ae77Skettenis REG_OFFSET (r_rsp),
56b725ae77Skettenis REG_OFFSET (r_r8),
57b725ae77Skettenis REG_OFFSET (r_r9),
58b725ae77Skettenis REG_OFFSET (r_r10),
59b725ae77Skettenis REG_OFFSET (r_r11),
60b725ae77Skettenis REG_OFFSET (r_r12),
61b725ae77Skettenis REG_OFFSET (r_r13),
62b725ae77Skettenis REG_OFFSET (r_r14),
63b725ae77Skettenis REG_OFFSET (r_r15),
64b725ae77Skettenis REG_OFFSET (r_rip),
65b725ae77Skettenis REG_OFFSET (r_rflags),
66b725ae77Skettenis REG_OFFSET (r_cs),
67b725ae77Skettenis REG_OFFSET (r_ss),
68b725ae77Skettenis -1,
69b725ae77Skettenis -1,
70b725ae77Skettenis -1,
71b725ae77Skettenis -1
72b725ae77Skettenis };
73b725ae77Skettenis
74b725ae77Skettenis
75b725ae77Skettenis /* Mapping between the general-purpose registers in FreeBSD/amd64
76b725ae77Skettenis `struct reg' format and GDB's register cache layout for
77b725ae77Skettenis FreeBSD/i386.
78b725ae77Skettenis
79b725ae77Skettenis Note that most FreeBSD/amd64 registers are 64-bit, while the
80b725ae77Skettenis FreeBSD/i386 registers are all 32-bit, but since we're
81b725ae77Skettenis little-endian we get away with that. */
82b725ae77Skettenis
83b725ae77Skettenis /* From <machine/reg.h>. */
84b725ae77Skettenis static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] =
85b725ae77Skettenis {
86b725ae77Skettenis 14 * 8, 13 * 8, /* %eax, %ecx */
87b725ae77Skettenis 12 * 8, 11 * 8, /* %edx, %ebx */
88b725ae77Skettenis 20 * 8, 10 * 8, /* %esp, %ebp */
89b725ae77Skettenis 9 * 8, 8 * 8, /* %esi, %edi */
90b725ae77Skettenis 17 * 8, 19 * 8, /* %eip, %eflags */
91b725ae77Skettenis 18 * 8, 21 * 8, /* %cs, %ss */
92b725ae77Skettenis -1, -1, -1, -1 /* %ds, %es, %fs, %gs */
93b725ae77Skettenis };
94b725ae77Skettenis
95b725ae77Skettenis
96*11efff7fSkettenis /* Support for debugging kernel virtual memory images. */
97b725ae77Skettenis
98*11efff7fSkettenis #include <sys/types.h>
99*11efff7fSkettenis #include <machine/pcb.h>
100b725ae77Skettenis
101*11efff7fSkettenis #include "bsd-kvm.h"
102*11efff7fSkettenis
103*11efff7fSkettenis static int
amd64fbsd_supply_pcb(struct regcache * regcache,struct pcb * pcb)104*11efff7fSkettenis amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
105b725ae77Skettenis {
106*11efff7fSkettenis /* The following is true for FreeBSD 5.2:
107b725ae77Skettenis
108*11efff7fSkettenis The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15,
109*11efff7fSkettenis %ds, %es, %fs and %gs. This accounts for all callee-saved
110*11efff7fSkettenis registers specified by the psABI and then some. Here %esp
111*11efff7fSkettenis contains the stack pointer at the point just after the call to
112*11efff7fSkettenis cpu_switch(). From this information we reconstruct the register
113*11efff7fSkettenis state as it would like when we just returned from cpu_switch(). */
114b725ae77Skettenis
115*11efff7fSkettenis /* The stack pointer shouldn't be zero. */
116*11efff7fSkettenis if (pcb->pcb_rsp == 0)
117*11efff7fSkettenis return 0;
118b725ae77Skettenis
119*11efff7fSkettenis pcb->pcb_rsp += 8;
120*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip);
121*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx);
122*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp);
123*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp);
124*11efff7fSkettenis regcache_raw_supply (regcache, 12, &pcb->pcb_r12);
125*11efff7fSkettenis regcache_raw_supply (regcache, 13, &pcb->pcb_r13);
126*11efff7fSkettenis regcache_raw_supply (regcache, 14, &pcb->pcb_r14);
127*11efff7fSkettenis regcache_raw_supply (regcache, 15, &pcb->pcb_r15);
128*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds);
129*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es);
130*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs);
131*11efff7fSkettenis regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs);
132b725ae77Skettenis
133*11efff7fSkettenis return 1;
134b725ae77Skettenis }
135b725ae77Skettenis
136b725ae77Skettenis
137b725ae77Skettenis /* Provide a prototype to silence -Wmissing-prototypes. */
138b725ae77Skettenis void _initialize_amd64fbsd_nat (void);
139b725ae77Skettenis
140b725ae77Skettenis void
_initialize_amd64fbsd_nat(void)141b725ae77Skettenis _initialize_amd64fbsd_nat (void)
142b725ae77Skettenis {
143*11efff7fSkettenis struct target_ops *t;
144b725ae77Skettenis int offset;
145b725ae77Skettenis
146b725ae77Skettenis amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset;
147*11efff7fSkettenis amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset;
148*11efff7fSkettenis
149*11efff7fSkettenis /* Add some extra features to the common *BSD/i386 target. */
150*11efff7fSkettenis t = amd64bsd_target ();
151*11efff7fSkettenis t->to_pid_to_exec_file = fbsd_pid_to_exec_file;
152*11efff7fSkettenis t->to_find_memory_regions = fbsd_find_memory_regions;
153*11efff7fSkettenis t->to_make_corefile_notes = fbsd_make_corefile_notes;
154*11efff7fSkettenis add_target (t);
155*11efff7fSkettenis
156*11efff7fSkettenis /* Support debugging kernel virtual memory images. */
157*11efff7fSkettenis bsd_kvm_add_target (amd64fbsd_supply_pcb);
158b725ae77Skettenis
159b725ae77Skettenis /* To support the recognition of signal handlers, i386bsd-tdep.c
160b725ae77Skettenis hardcodes some constants. Inclusion of this file means that we
161b725ae77Skettenis are compiling a native debugger, which means that we can use the
162b725ae77Skettenis system header files and sysctl(3) to get at the relevant
163b725ae77Skettenis information. */
164b725ae77Skettenis
165b725ae77Skettenis #define SC_REG_OFFSET amd64fbsd_sc_reg_offset
166b725ae77Skettenis
167b725ae77Skettenis /* We only check the program counter, stack pointer and frame
168b725ae77Skettenis pointer since these members of `struct sigcontext' are essential
169b725ae77Skettenis for providing backtraces. */
170b725ae77Skettenis
171b725ae77Skettenis #define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM]
172b725ae77Skettenis #define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM]
173b725ae77Skettenis #define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM]
174b725ae77Skettenis
175b725ae77Skettenis /* Override the default value for the offset of the program counter
176b725ae77Skettenis in the sigcontext structure. */
177b725ae77Skettenis offset = offsetof (struct sigcontext, sc_rip);
178b725ae77Skettenis
179b725ae77Skettenis if (SC_RIP_OFFSET != offset)
180b725ae77Skettenis {
181b725ae77Skettenis warning ("\
182b725ae77Skettenis offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\
183b725ae77Skettenis Please report this to <bug-gdb@gnu.org>.",
184b725ae77Skettenis offset, SC_RIP_OFFSET);
185b725ae77Skettenis }
186b725ae77Skettenis
187b725ae77Skettenis SC_RIP_OFFSET = offset;
188b725ae77Skettenis
189b725ae77Skettenis /* Likewise for the stack pointer. */
190b725ae77Skettenis offset = offsetof (struct sigcontext, sc_rsp);
191b725ae77Skettenis
192b725ae77Skettenis if (SC_RSP_OFFSET != offset)
193b725ae77Skettenis {
194b725ae77Skettenis warning ("\
195b725ae77Skettenis offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\
196b725ae77Skettenis Please report this to <bug-gdb@gnu.org>.",
197b725ae77Skettenis offset, SC_RSP_OFFSET);
198b725ae77Skettenis }
199b725ae77Skettenis
200b725ae77Skettenis SC_RSP_OFFSET = offset;
201b725ae77Skettenis
202b725ae77Skettenis /* And the frame pointer. */
203b725ae77Skettenis offset = offsetof (struct sigcontext, sc_rbp);
204b725ae77Skettenis
205b725ae77Skettenis if (SC_RBP_OFFSET != offset)
206b725ae77Skettenis {
207b725ae77Skettenis warning ("\
208b725ae77Skettenis offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\
209b725ae77Skettenis Please report this to <bug-gdb@gnu.org>.",
210b725ae77Skettenis offset, SC_RBP_OFFSET);
211b725ae77Skettenis }
212b725ae77Skettenis
213b725ae77Skettenis SC_RBP_OFFSET = offset;
214b725ae77Skettenis
215b725ae77Skettenis /* FreeBSD provides a kern.ps_strings sysctl that we can use to
216b725ae77Skettenis locate the sigtramp. That way we can still recognize a sigtramp
217b725ae77Skettenis if its location is changed in a new kernel. Of course this is
218b725ae77Skettenis still based on the assumption that the sigtramp is placed
219b725ae77Skettenis directly under the location where the program arguments and
220b725ae77Skettenis environment can be found. */
221b725ae77Skettenis {
222b725ae77Skettenis int mib[2];
223b725ae77Skettenis long ps_strings;
224b725ae77Skettenis size_t len;
225b725ae77Skettenis
226b725ae77Skettenis mib[0] = CTL_KERN;
227b725ae77Skettenis mib[1] = KERN_PS_STRINGS;
228b725ae77Skettenis len = sizeof (ps_strings);
229b725ae77Skettenis if (sysctl (mib, 2, &ps_strings, &len, NULL, 0) == 0)
230b725ae77Skettenis {
231b725ae77Skettenis amd64fbsd_sigtramp_start_addr = ps_strings - 32;
232b725ae77Skettenis amd64fbsd_sigtramp_end_addr = ps_strings;
233b725ae77Skettenis }
234b725ae77Skettenis }
235b725ae77Skettenis }
236