]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/amd64fbsd-tdep.c
Makefiles: Flatten and sort file lists
[thirdparty/binutils-gdb.git] / gdb / amd64fbsd-tdep.c
CommitLineData
68cc0bfb 1/* Target-dependent code for FreeBSD/amd64.
477f40d1 2
618f726f 3 Copyright (C) 2003-2016 Free Software Foundation, Inc.
68cc0bfb
MK
4
5 This file is part of GDB.
6
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
68cc0bfb
MK
10 (at your option) any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
68cc0bfb
MK
19
20#include "defs.h"
21#include "arch-utils.h"
22#include "frame.h"
23#include "gdbcore.h"
24#include "regcache.h"
25#include "osabi.h"
97de3545
JB
26#include "regset.h"
27#include "i386fbsd-tdep.h"
28#include "x86-xstate.h"
68cc0bfb 29
85be1ca6 30#include "amd64-tdep.h"
1c02b2a5 31#include "bsd-uthread.h"
490496c3 32#include "fbsd-tdep.h"
7e654c37 33#include "solib-svr4.h"
68cc0bfb
MK
34
35/* Support for signal handlers. */
36
cf424aef
JB
37/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
38 routine. */
39
40static const gdb_byte amd64fbsd_sigtramp_code[] =
41{
42 0x48, 0x8d, 0x7c, 0x24, 0x10, /* lea SIGF_UC(%rsp),%rdi */
43 0x6a, 0x00, /* pushq $0 */
44 0x48, 0xc7, 0xc0, 0xa1, 0x01, 0x00, 0x00,
45 /* movq $SYS_sigreturn,%rax */
46 0x0f, 0x05 /* syscall */
47};
48
49static int
50amd64fbsd_sigtramp_p (struct frame_info *this_frame)
51{
52 CORE_ADDR pc = get_frame_pc (this_frame);
53 gdb_byte buf[sizeof amd64fbsd_sigtramp_code];
54
55 if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf))
56 return 0;
773eacf5
JB
57 if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code)
58 != 0)
cf424aef
JB
59 return 0;
60
61 return 1;
62}
63
10458914
DJ
64/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the
65 address of the associated sigcontext structure. */
68cc0bfb
MK
66
67static CORE_ADDR
10458914 68amd64fbsd_sigcontext_addr (struct frame_info *this_frame)
68cc0bfb 69{
c5cb74ee
JB
70 struct gdbarch *gdbarch = get_frame_arch (this_frame);
71 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
68cc0bfb 72 CORE_ADDR sp;
c5cb74ee 73 gdb_byte buf[8];
68cc0bfb 74
212c460c
MK
75 /* The `struct sigcontext' (which really is an `ucontext_t' on
76 FreeBSD/amd64) lives at a fixed offset in the signal frame. See
77 <machine/sigframe.h>. */
c5cb74ee
JB
78 get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
79 sp = extract_unsigned_integer (buf, 8, byte_order);
212c460c 80 return sp + 16;
68cc0bfb
MK
81}
82\f
83/* FreeBSD 5.1-RELEASE or later. */
84
477f40d1
MK
85/* Mapping between the general-purpose registers in `struct reg'
86 format and GDB's register cache layout.
87
88 Note that some registers are 32-bit, but since we're little-endian
89 we get away with that. */
90
91/* From <machine/reg.h>. */
92static int amd64fbsd_r_reg_offset[] =
93{
af233647
MK
94 14 * 8, /* %rax */
95 11 * 8, /* %rbx */
96 13 * 8, /* %rcx */
97 12 * 8, /* %rdx */
98 9 * 8, /* %rsi */
99 8 * 8, /* %rdi */
100 10 * 8, /* %rbp */
101 20 * 8, /* %rsp */
0963b4bd 102 7 * 8, /* %r8 ... */
af233647
MK
103 6 * 8,
104 5 * 8,
105 4 * 8,
106 3 * 8,
107 2 * 8,
108 1 * 8,
109 0 * 8, /* ... %r15 */
110 17 * 8, /* %rip */
111 19 * 8, /* %eflags */
112 18 * 8, /* %cs */
113 21 * 8, /* %ss */
114 -1, /* %ds */
115 -1, /* %es */
116 -1, /* %fs */
117 -1 /* %gs */
477f40d1
MK
118};
119
68cc0bfb 120/* Location of the signal trampoline. */
cf424aef
JB
121CORE_ADDR amd64fbsd_sigtramp_start_addr;
122CORE_ADDR amd64fbsd_sigtramp_end_addr;
68cc0bfb
MK
123
124/* From <machine/signal.h>. */
af233647 125int amd64fbsd_sc_reg_offset[] =
68cc0bfb 126{
212c460c
MK
127 24 + 6 * 8, /* %rax */
128 24 + 7 * 8, /* %rbx */
129 24 + 3 * 8, /* %rcx */
130 24 + 2 * 8, /* %rdx */
131 24 + 1 * 8, /* %rsi */
132 24 + 0 * 8, /* %rdi */
133 24 + 8 * 8, /* %rbp */
dac94105 134 24 + 22 * 8, /* %rsp */
0963b4bd 135 24 + 4 * 8, /* %r8 ... */
af233647
MK
136 24 + 5 * 8,
137 24 + 9 * 8,
138 24 + 10 * 8,
139 24 + 11 * 8,
140 24 + 12 * 8,
141 24 + 13 * 8,
142 24 + 14 * 8, /* ... %r15 */
dac94105
MK
143 24 + 19 * 8, /* %rip */
144 24 + 21 * 8, /* %eflags */
af233647
MK
145 24 + 20 * 8, /* %cs */
146 24 + 23 * 8, /* %ss */
68cc0bfb
MK
147 -1, /* %ds */
148 -1, /* %es */
149 -1, /* %fs */
150 -1 /* %gs */
151};
152
1c02b2a5
MK
153/* From /usr/src/lib/libc/amd64/gen/_setjmp.S. */
154static int amd64fbsd_jmp_buf_reg_offset[] =
155{
156 -1, /* %rax */
157 1 * 8, /* %rbx */
158 -1, /* %rcx */
159 -1, /* %rdx */
160 -1, /* %rsi */
161 -1, /* %rdi */
162 3 * 8, /* %rbp */
163 2 * 8, /* %rsp */
0963b4bd 164 -1, /* %r8 ... */
1c02b2a5
MK
165 -1,
166 -1,
167 -1, /* ... %r11 */
0963b4bd 168 4 * 8, /* %r12 ... */
1c02b2a5
MK
169 5 * 8,
170 6 * 8,
171 7 * 8, /* ... %r15 */
172 0 * 8 /* %rip */
173};
174
97de3545
JB
175/* Implement the core_read_description gdbarch method. */
176
177static const struct target_desc *
178amd64fbsd_core_read_description (struct gdbarch *gdbarch,
179 struct target_ops *target,
180 bfd *abfd)
181{
182 return amd64_target_description (i386fbsd_core_read_xcr0 (abfd));
183}
184
185/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */
186
187static void
188amd64fbsd_supply_xstateregset (const struct regset *regset,
189 struct regcache *regcache, int regnum,
190 const void *xstateregs, size_t len)
191{
192 amd64_supply_xsave (regcache, regnum, xstateregs);
193}
194
195/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */
196
197static void
198amd64fbsd_collect_xstateregset (const struct regset *regset,
199 const struct regcache *regcache,
200 int regnum, void *xstateregs, size_t len)
201{
202 amd64_collect_xsave (regcache, regnum, xstateregs, 1);
203}
204
205static const struct regset amd64fbsd_xstateregset =
206 {
207 NULL,
208 amd64fbsd_supply_xstateregset,
209 amd64fbsd_collect_xstateregset
210 };
211
212/* Iterate over core file register note sections. */
213
214static void
215amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
216 iterate_over_regset_sections_cb *cb,
217 void *cb_data,
218 const struct regcache *regcache)
219{
220 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
221
222 cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data);
223 cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data);
224 cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0),
225 &amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
226}
227
1c02b2a5
MK
228static void
229amd64fbsd_supply_uthread (struct regcache *regcache,
230 int regnum, CORE_ADDR addr)
231{
4252dc94 232 gdb_byte buf[8];
1c02b2a5
MK
233 int i;
234
235 gdb_assert (regnum >= -1);
236
237 for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
238 {
239 if (amd64fbsd_jmp_buf_reg_offset[i] != -1
240 && (regnum == -1 || regnum == i))
241 {
242 read_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
243 regcache_raw_supply (regcache, i, buf);
244 }
245 }
246}
247
248static void
249amd64fbsd_collect_uthread (const struct regcache *regcache,
250 int regnum, CORE_ADDR addr)
251{
4252dc94 252 gdb_byte buf[8];
1c02b2a5
MK
253 int i;
254
255 gdb_assert (regnum >= -1);
256
257 for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++)
258 {
259 if (amd64fbsd_jmp_buf_reg_offset[i] != -1
260 && (regnum == -1 || regnum == i))
261 {
262 regcache_raw_collect (regcache, i, buf);
263 write_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8);
264 }
265 }
266}
267
63807e1d 268static void
68cc0bfb
MK
269amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
270{
271 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
272
490496c3
AA
273 /* Generic FreeBSD support. */
274 fbsd_init_abi (info, gdbarch);
275
68cc0bfb
MK
276 /* Obviously FreeBSD is BSD-based. */
277 i386bsd_init_abi (info, gdbarch);
278
477f40d1
MK
279 tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
280 tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
281 tdep->sizeof_gregset = 22 * 8;
282
90f90721 283 amd64_init_abi (info, gdbarch);
68cc0bfb 284
cf424aef 285 tdep->sigtramp_p = amd64fbsd_sigtramp_p;
10fc94a4
MK
286 tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
287 tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
68cc0bfb
MK
288 tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
289 tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
477f40d1 290 tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
7e654c37 291
97de3545
JB
292 tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
293
294 /* Iterate over core file register note sections. */
295 set_gdbarch_iterate_over_regset_sections
296 (gdbarch, amd64fbsd_iterate_over_regset_sections);
297
298 set_gdbarch_core_read_description (gdbarch,
299 amd64fbsd_core_read_description);
300
1c02b2a5
MK
301 /* FreeBSD provides a user-level threads implementation. */
302 bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread);
303 bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread);
304
7e654c37
MK
305 /* FreeBSD uses SVR4-style shared libraries. */
306 set_solib_svr4_fetch_link_map_offsets
307 (gdbarch, svr4_lp64_fetch_link_map_offsets);
68cc0bfb
MK
308}
309\f
310
311/* Provide a prototype to silence -Wmissing-prototypes. */
312void _initialize_amd64fbsd_tdep (void);
313
314void
315_initialize_amd64fbsd_tdep (void)
316{
317 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
318 GDB_OSABI_FREEBSD_ELF, amd64fbsd_init_abi);
319}