]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/amd64-fbsd-tdep.c
Generated files
[thirdparty/binutils-gdb.git] / gdb / amd64-fbsd-tdep.c
CommitLineData
68cc0bfb 1/* Target-dependent code for FreeBSD/amd64.
477f40d1 2
e2882c85 3 Copyright (C) 2003-2018 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 26#include "regset.h"
03b62bbb 27#include "i386-fbsd-tdep.h"
97de3545 28#include "x86-xstate.h"
68cc0bfb 29
85be1ca6 30#include "amd64-tdep.h"
490496c3 31#include "fbsd-tdep.h"
7e654c37 32#include "solib-svr4.h"
68cc0bfb
MK
33
34/* Support for signal handlers. */
35
cf424aef
JB
36/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
37 routine. */
38
39static const gdb_byte amd64fbsd_sigtramp_code[] =
40{
41 0x48, 0x8d, 0x7c, 0x24, 0x10, /* lea SIGF_UC(%rsp),%rdi */
42 0x6a, 0x00, /* pushq $0 */
43 0x48, 0xc7, 0xc0, 0xa1, 0x01, 0x00, 0x00,
44 /* movq $SYS_sigreturn,%rax */
45 0x0f, 0x05 /* syscall */
46};
47
48static int
49amd64fbsd_sigtramp_p (struct frame_info *this_frame)
50{
51 CORE_ADDR pc = get_frame_pc (this_frame);
52 gdb_byte buf[sizeof amd64fbsd_sigtramp_code];
53
54 if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf))
55 return 0;
773eacf5
JB
56 if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code)
57 != 0)
cf424aef
JB
58 return 0;
59
60 return 1;
61}
62
10458914
DJ
63/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the
64 address of the associated sigcontext structure. */
68cc0bfb
MK
65
66static CORE_ADDR
10458914 67amd64fbsd_sigcontext_addr (struct frame_info *this_frame)
68cc0bfb 68{
c5cb74ee
JB
69 struct gdbarch *gdbarch = get_frame_arch (this_frame);
70 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
68cc0bfb 71 CORE_ADDR sp;
c5cb74ee 72 gdb_byte buf[8];
68cc0bfb 73
212c460c
MK
74 /* The `struct sigcontext' (which really is an `ucontext_t' on
75 FreeBSD/amd64) lives at a fixed offset in the signal frame. See
76 <machine/sigframe.h>. */
c5cb74ee
JB
77 get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
78 sp = extract_unsigned_integer (buf, 8, byte_order);
212c460c 79 return sp + 16;
68cc0bfb
MK
80}
81\f
82/* FreeBSD 5.1-RELEASE or later. */
83
477f40d1
MK
84/* Mapping between the general-purpose registers in `struct reg'
85 format and GDB's register cache layout.
86
87 Note that some registers are 32-bit, but since we're little-endian
88 we get away with that. */
89
90/* From <machine/reg.h>. */
91static int amd64fbsd_r_reg_offset[] =
92{
af233647
MK
93 14 * 8, /* %rax */
94 11 * 8, /* %rbx */
95 13 * 8, /* %rcx */
96 12 * 8, /* %rdx */
97 9 * 8, /* %rsi */
98 8 * 8, /* %rdi */
99 10 * 8, /* %rbp */
100 20 * 8, /* %rsp */
0963b4bd 101 7 * 8, /* %r8 ... */
af233647
MK
102 6 * 8,
103 5 * 8,
104 4 * 8,
105 3 * 8,
106 2 * 8,
107 1 * 8,
108 0 * 8, /* ... %r15 */
109 17 * 8, /* %rip */
110 19 * 8, /* %eflags */
111 18 * 8, /* %cs */
112 21 * 8, /* %ss */
113 -1, /* %ds */
114 -1, /* %es */
115 -1, /* %fs */
116 -1 /* %gs */
477f40d1
MK
117};
118
68cc0bfb 119/* Location of the signal trampoline. */
cf424aef
JB
120CORE_ADDR amd64fbsd_sigtramp_start_addr;
121CORE_ADDR amd64fbsd_sigtramp_end_addr;
68cc0bfb
MK
122
123/* From <machine/signal.h>. */
af233647 124int amd64fbsd_sc_reg_offset[] =
68cc0bfb 125{
212c460c
MK
126 24 + 6 * 8, /* %rax */
127 24 + 7 * 8, /* %rbx */
128 24 + 3 * 8, /* %rcx */
129 24 + 2 * 8, /* %rdx */
130 24 + 1 * 8, /* %rsi */
131 24 + 0 * 8, /* %rdi */
132 24 + 8 * 8, /* %rbp */
dac94105 133 24 + 22 * 8, /* %rsp */
0963b4bd 134 24 + 4 * 8, /* %r8 ... */
af233647
MK
135 24 + 5 * 8,
136 24 + 9 * 8,
137 24 + 10 * 8,
138 24 + 11 * 8,
139 24 + 12 * 8,
140 24 + 13 * 8,
141 24 + 14 * 8, /* ... %r15 */
dac94105
MK
142 24 + 19 * 8, /* %rip */
143 24 + 21 * 8, /* %eflags */
af233647
MK
144 24 + 20 * 8, /* %cs */
145 24 + 23 * 8, /* %ss */
68cc0bfb
MK
146 -1, /* %ds */
147 -1, /* %es */
148 -1, /* %fs */
149 -1 /* %gs */
150};
151
97de3545
JB
152/* Implement the core_read_description gdbarch method. */
153
154static const struct target_desc *
155amd64fbsd_core_read_description (struct gdbarch *gdbarch,
156 struct target_ops *target,
157 bfd *abfd)
158{
159 return amd64_target_description (i386fbsd_core_read_xcr0 (abfd));
160}
161
162/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */
163
164static void
165amd64fbsd_supply_xstateregset (const struct regset *regset,
166 struct regcache *regcache, int regnum,
167 const void *xstateregs, size_t len)
168{
169 amd64_supply_xsave (regcache, regnum, xstateregs);
170}
171
172/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */
173
174static void
175amd64fbsd_collect_xstateregset (const struct regset *regset,
176 const struct regcache *regcache,
177 int regnum, void *xstateregs, size_t len)
178{
179 amd64_collect_xsave (regcache, regnum, xstateregs, 1);
180}
181
182static const struct regset amd64fbsd_xstateregset =
183 {
184 NULL,
185 amd64fbsd_supply_xstateregset,
186 amd64fbsd_collect_xstateregset
187 };
188
189/* Iterate over core file register note sections. */
190
191static void
192amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
193 iterate_over_regset_sections_cb *cb,
194 void *cb_data,
195 const struct regcache *regcache)
196{
197 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
198
199 cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data);
200 cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data);
201 cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0),
202 &amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
203}
204
63807e1d 205static void
68cc0bfb
MK
206amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
207{
208 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
209
490496c3
AA
210 /* Generic FreeBSD support. */
211 fbsd_init_abi (info, gdbarch);
212
68cc0bfb
MK
213 /* Obviously FreeBSD is BSD-based. */
214 i386bsd_init_abi (info, gdbarch);
215
477f40d1
MK
216 tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
217 tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
218 tdep->sizeof_gregset = 22 * 8;
219
2434b019
YQ
220 amd64_init_abi (info, gdbarch,
221 amd64_target_description (X86_XSTATE_SSE_MASK));
68cc0bfb 222
cf424aef 223 tdep->sigtramp_p = amd64fbsd_sigtramp_p;
10fc94a4
MK
224 tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
225 tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
68cc0bfb
MK
226 tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
227 tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
477f40d1 228 tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
7e654c37 229
97de3545
JB
230 tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
231
232 /* Iterate over core file register note sections. */
233 set_gdbarch_iterate_over_regset_sections
234 (gdbarch, amd64fbsd_iterate_over_regset_sections);
235
236 set_gdbarch_core_read_description (gdbarch,
237 amd64fbsd_core_read_description);
238
7e654c37
MK
239 /* FreeBSD uses SVR4-style shared libraries. */
240 set_solib_svr4_fetch_link_map_offsets
241 (gdbarch, svr4_lp64_fetch_link_map_offsets);
68cc0bfb 242}
68cc0bfb
MK
243
244void
245_initialize_amd64fbsd_tdep (void)
246{
247 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
1736a7bd 248 GDB_OSABI_FREEBSD, amd64fbsd_init_abi);
68cc0bfb 249}