Multi-target support
[deliverable/binutils-gdb.git] / gdb / amd64-fbsd-tdep.c
CommitLineData
68cc0bfb 1/* Target-dependent code for FreeBSD/amd64.
477f40d1 2
b811d2c2 3 Copyright (C) 2003-2020 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"
d55e5aa6 24#include "regcache.h"
4de283e4 25#include "osabi.h"
97de3545 26#include "regset.h"
4de283e4 27#include "i386-fbsd-tdep.h"
268a13a5 28#include "gdbsupport/x86-xstate.h"
4de283e4
TT
29
30#include "amd64-tdep.h"
31#include "fbsd-tdep.h"
7e654c37 32#include "solib-svr4.h"
5b6d1e4f 33#include "inferior.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
97de3545
JB
153/* Implement the core_read_description gdbarch method. */
154
155static const struct target_desc *
156amd64fbsd_core_read_description (struct gdbarch *gdbarch,
157 struct target_ops *target,
158 bfd *abfd)
159{
41206e32 160 return amd64_target_description (i386fbsd_core_read_xcr0 (abfd), true);
97de3545
JB
161}
162
163/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */
164
165static void
166amd64fbsd_supply_xstateregset (const struct regset *regset,
167 struct regcache *regcache, int regnum,
168 const void *xstateregs, size_t len)
169{
170 amd64_supply_xsave (regcache, regnum, xstateregs);
171}
172
173/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */
174
175static void
176amd64fbsd_collect_xstateregset (const struct regset *regset,
177 const struct regcache *regcache,
178 int regnum, void *xstateregs, size_t len)
179{
180 amd64_collect_xsave (regcache, regnum, xstateregs, 1);
181}
182
183static const struct regset amd64fbsd_xstateregset =
184 {
185 NULL,
186 amd64fbsd_supply_xstateregset,
187 amd64fbsd_collect_xstateregset
188 };
189
190/* Iterate over core file register note sections. */
191
192static void
193amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
194 iterate_over_regset_sections_cb *cb,
195 void *cb_data,
196 const struct regcache *regcache)
197{
198 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
199
a616bb94
AH
200 cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
201 cb_data);
202 cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &amd64_fpregset,
203 NULL, cb_data);
204 cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0), X86_XSTATE_SIZE (tdep->xcr0),
97de3545
JB
205 &amd64fbsd_xstateregset, "XSAVE extended state", cb_data);
206}
207
f5424cfa
JB
208/* Implement the get_thread_local_address gdbarch method. */
209
210static CORE_ADDR
211amd64fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
212 CORE_ADDR lm_addr, CORE_ADDR offset)
213{
214 struct regcache *regcache;
215
5b6d1e4f
PA
216 regcache = get_thread_arch_regcache (current_inferior ()->process_target (),
217 ptid, gdbarch);
f5424cfa
JB
218
219 target_fetch_registers (regcache, AMD64_FSBASE_REGNUM);
220
221 ULONGEST fsbase;
222 if (regcache->cooked_read (AMD64_FSBASE_REGNUM, &fsbase) != REG_VALID)
223 error (_("Unable to fetch %%fsbase"));
224
225 CORE_ADDR dtv_addr = fsbase + gdbarch_ptr_bit (gdbarch) / 8;
226 return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset);
227}
228
63807e1d 229static void
68cc0bfb
MK
230amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
231{
232 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
233
490496c3
AA
234 /* Generic FreeBSD support. */
235 fbsd_init_abi (info, gdbarch);
236
68cc0bfb
MK
237 /* Obviously FreeBSD is BSD-based. */
238 i386bsd_init_abi (info, gdbarch);
239
477f40d1
MK
240 tdep->gregset_reg_offset = amd64fbsd_r_reg_offset;
241 tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset);
242 tdep->sizeof_gregset = 22 * 8;
243
2434b019 244 amd64_init_abi (info, gdbarch,
41206e32 245 amd64_target_description (X86_XSTATE_SSE_MASK, true));
68cc0bfb 246
cf424aef 247 tdep->sigtramp_p = amd64fbsd_sigtramp_p;
10fc94a4
MK
248 tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr;
249 tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr;
68cc0bfb
MK
250 tdep->sigcontext_addr = amd64fbsd_sigcontext_addr;
251 tdep->sc_reg_offset = amd64fbsd_sc_reg_offset;
477f40d1 252 tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset);
7e654c37 253
97de3545
JB
254 tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
255
256 /* Iterate over core file register note sections. */
257 set_gdbarch_iterate_over_regset_sections
258 (gdbarch, amd64fbsd_iterate_over_regset_sections);
259
260 set_gdbarch_core_read_description (gdbarch,
261 amd64fbsd_core_read_description);
262
7e654c37
MK
263 /* FreeBSD uses SVR4-style shared libraries. */
264 set_solib_svr4_fetch_link_map_offsets
265 (gdbarch, svr4_lp64_fetch_link_map_offsets);
f5424cfa
JB
266
267 set_gdbarch_fetch_tls_load_module_address (gdbarch,
268 svr4_fetch_objfile_link_map);
269 set_gdbarch_get_thread_local_address (gdbarch,
270 amd64fbsd_get_thread_local_address);
68cc0bfb 271}
68cc0bfb
MK
272
273void
274_initialize_amd64fbsd_tdep (void)
275{
276 gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
1736a7bd 277 GDB_OSABI_FREEBSD, amd64fbsd_init_abi);
68cc0bfb 278}
This page took 0.979658 seconds and 4 git commands to generate.