1 /* Native-dependent code for FreeBSD/amd64.
3 Copyright (C) 2003-2022 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 <sys/types.h>
27 #include <sys/ptrace.h>
28 #include <sys/sysctl.h>
30 #include <machine/reg.h>
33 #include "amd64-tdep.h"
34 #include "amd64-nat.h"
35 #include "amd64-bsd-nat.h"
37 #include "gdbsupport/x86-xstate.h"
40 class amd64_fbsd_nat_target final
41 : public amd64_bsd_nat_target
<fbsd_nat_target
>
44 /* Add some extra features to the common *BSD/amd64 target. */
45 const struct target_desc
*read_description () override
;
47 #if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
48 bool supports_stopped_by_hw_breakpoint () override
;
52 static amd64_fbsd_nat_target the_amd64_fbsd_nat_target
;
54 /* Offset in `struct reg' where MEMBER is stored. */
55 #define REG_OFFSET(member) offsetof (struct reg, member)
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
[] =
79 REG_OFFSET (r_rflags
),
89 /* Mapping between the general-purpose registers in FreeBSD/amd64
90 `struct reg' format and GDB's register cache layout for
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. */
97 /* From <machine/reg.h>. */
98 static int amd64fbsd32_r_reg_offset
[I386_NUM_GREGS
] =
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 */
110 /* Support for debugging kernel virtual memory images. */
112 #include <machine/pcb.h>
113 #include <osreldate.h>
118 amd64fbsd_supply_pcb (struct regcache
*regcache
, struct pcb
*pcb
)
120 /* The following is true for FreeBSD 5.2:
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(). */
129 /* The stack pointer shouldn't be zero. */
130 if (pcb
->pcb_rsp
== 0)
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
);
158 /* Implement the read_description method. */
160 const struct target_desc
*
161 amd64_fbsd_nat_target::read_description ()
163 #ifdef PT_GETXSTATE_INFO
164 static int xsave_probed
;
165 static uint64_t xcr0
;
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
177 struct ptrace_xstate_info info
;
179 if (ptrace (PT_GETXSTATE_INFO
, inferior_ptid
.pid (),
180 (PTRACE_TYPE_ARG3
) &info
, sizeof (info
)) == 0)
182 x86bsd_xsave_len
= info
.xsave_len
;
183 xcr0
= info
.xsave_mask
;
188 if (x86bsd_xsave_len
!= 0)
191 return amd64_target_description (xcr0
, true);
193 return i386_target_description (xcr0
, true);
197 return amd64_target_description (X86_XSTATE_SSE_MASK
, true);
199 return i386_target_description (X86_XSTATE_SSE_MASK
, true);
202 #if defined(HAVE_PT_GETDBREGS) && defined(USE_SIGTRAP_SIGINFO)
203 /* Implement the supports_stopped_by_hw_breakpoints method. */
206 amd64_fbsd_nat_target::supports_stopped_by_hw_breakpoint ()
212 void _initialize_amd64fbsd_nat ();
214 _initialize_amd64fbsd_nat ()
218 amd64_native_gregset32_reg_offset
= amd64fbsd32_r_reg_offset
;
219 amd64_native_gregset64_reg_offset
= amd64fbsd64_r_reg_offset
;
221 add_inf_child_target (&the_amd64_fbsd_nat_target
);
223 /* Support debugging kernel virtual memory images. */
224 bsd_kvm_add_target (amd64fbsd_supply_pcb
);
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
232 #define SC_REG_OFFSET amd64fbsd_sc_reg_offset
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. */
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]
242 /* Override the default value for the offset of the program counter
243 in the sigcontext structure. */
244 offset
= offsetof (struct sigcontext
, sc_rip
);
246 if (SC_RIP_OFFSET
!= offset
)
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
);
254 SC_RIP_OFFSET
= offset
;
256 /* Likewise for the stack pointer. */
257 offset
= offsetof (struct sigcontext
, sc_rsp
);
259 if (SC_RSP_OFFSET
!= offset
)
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
);
267 SC_RSP_OFFSET
= offset
;
269 /* And the frame pointer. */
270 offset
= offsetof (struct sigcontext
, sc_rbp
);
272 if (SC_RBP_OFFSET
!= offset
)
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
);
280 SC_RBP_OFFSET
= offset
;