Fix test-cp-name-parser build, unused variable
[deliverable/binutils-gdb.git] / gdb / i386-fbsd-tdep.c
CommitLineData
8a96bc77
MK
1/* Target-dependent code for FreeBSD/i386.
2
42a4f53d 3 Copyright (C) 2003-2019 Free Software Foundation, Inc.
8a96bc77
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
8a96bc77
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/>. */
8a96bc77
MK
19
20#include "defs.h"
21#include "arch-utils.h"
fa565c2b 22#include "gdbcore.h"
8a96bc77 23#include "osabi.h"
fa565c2b 24#include "regcache.h"
97de3545 25#include "regset.h"
03b62bbb 26#include "i386-fbsd-tdep.h"
0747795c 27#include "common/x86-xstate.h"
fa565c2b 28
8a96bc77
MK
29#include "i386-tdep.h"
30#include "i387-tdep.h"
490496c3 31#include "fbsd-tdep.h"
7e654c37 32#include "solib-svr4.h"
8a96bc77 33
cf424aef
JB
34/* Support for signal handlers. */
35
36/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
37 routine. */
38
39/* FreeBSD/i386 supports three different signal trampolines, one for
40 versions before 4.0, a second for 4.x, and a third for 5.0 and
41 later. To complicate matters, FreeBSD/i386 binaries running under
42 an amd64 kernel use a different set of trampolines. These
43 trampolines differ from the i386 kernel trampolines in that they
44 omit a middle section that conditionally restores %gs. */
45
46static const gdb_byte i386fbsd_sigtramp_start[] =
47{
48 0x8d, 0x44, 0x24, 0x20, /* lea SIGF_UC(%esp),%eax */
49 0x50 /* pushl %eax */
50};
51
52static const gdb_byte i386fbsd_sigtramp_middle[] =
53{
54 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00,
55 /* testl $PSL_VM,UC_EFLAGS(%eax) */
56 0x75, 0x03, /* jne +3 */
57 0x8e, 0x68, 0x14 /* mov UC_GS(%eax),%gs */
58};
59
60static const gdb_byte i386fbsd_sigtramp_end[] =
61{
62 0xb8, 0xa1, 0x01, 0x00, 0x00, /* movl $SYS_sigreturn,%eax */
63 0x50, /* pushl %eax */
64 0xcd, 0x80 /* int $0x80 */
65};
66
67static const gdb_byte i386fbsd_freebsd4_sigtramp_start[] =
68{
69 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC4(%esp),%eax */
70 0x50 /* pushl %eax */
71};
72
73static const gdb_byte i386fbsd_freebsd4_sigtramp_middle[] =
74{
75 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00,
76 /* testl $PSL_VM,UC4_EFLAGS(%eax) */
77 0x75, 0x03, /* jne +3 */
78 0x8e, 0x68, 0x14 /* mov UC4_GS(%eax),%gs */
79};
80
81static const gdb_byte i386fbsd_freebsd4_sigtramp_end[] =
82{
83 0xb8, 0x58, 0x01, 0x00, 0x00, /* movl $344,%eax */
84 0x50, /* pushl %eax */
85 0xcd, 0x80 /* int $0x80 */
86};
87
88static const gdb_byte i386fbsd_osigtramp_start[] =
89{
90 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_SC(%esp),%eax */
91 0x50 /* pushl %eax */
92};
93
94static const gdb_byte i386fbsd_osigtramp_middle[] =
95{
96 0xf7, 0x40, 0x18, 0x00, 0x00, 0x02, 0x00,
97 /* testl $PSL_VM,SC_PS(%eax) */
98 0x75, 0x03, /* jne +3 */
99 0x8e, 0x68, 0x44 /* mov SC_GS(%eax),%gs */
100};
101
102static const gdb_byte i386fbsd_osigtramp_end[] =
103{
104 0xb8, 0x67, 0x00, 0x00, 0x00, /* movl $103,%eax */
105 0x50, /* pushl %eax */
106 0xcd, 0x80 /* int $0x80 */
107};
108
109/* The three different trampolines are all the same size. */
773eacf5
JB
110gdb_static_assert (sizeof i386fbsd_sigtramp_start
111 == sizeof i386fbsd_freebsd4_sigtramp_start);
112gdb_static_assert (sizeof i386fbsd_sigtramp_start
113 == sizeof i386fbsd_osigtramp_start);
114gdb_static_assert (sizeof i386fbsd_sigtramp_middle
115 == sizeof i386fbsd_freebsd4_sigtramp_middle);
116gdb_static_assert (sizeof i386fbsd_sigtramp_middle
117 == sizeof i386fbsd_osigtramp_middle);
118gdb_static_assert (sizeof i386fbsd_sigtramp_end
119 == sizeof i386fbsd_freebsd4_sigtramp_end);
120gdb_static_assert (sizeof i386fbsd_sigtramp_end
121 == sizeof i386fbsd_osigtramp_end);
cf424aef
JB
122
123/* We assume that the middle is the largest chunk below. */
773eacf5
JB
124gdb_static_assert (sizeof i386fbsd_sigtramp_middle
125 > sizeof i386fbsd_sigtramp_start);
126gdb_static_assert (sizeof i386fbsd_sigtramp_middle
127 > sizeof i386fbsd_sigtramp_end);
cf424aef
JB
128
129static int
130i386fbsd_sigtramp_p (struct frame_info *this_frame)
131{
132 CORE_ADDR pc = get_frame_pc (this_frame);
133 gdb_byte buf[sizeof i386fbsd_sigtramp_middle];
134 const gdb_byte *middle, *end;
135
136 /* Look for a matching start. */
137 if (!safe_frame_unwind_memory (this_frame, pc, buf,
138 sizeof i386fbsd_sigtramp_start))
139 return 0;
773eacf5
JB
140 if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start)
141 == 0)
142 {
143 middle = i386fbsd_sigtramp_middle;
144 end = i386fbsd_sigtramp_end;
145 }
146 else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start,
147 sizeof i386fbsd_freebsd4_sigtramp_start) == 0)
148 {
149 middle = i386fbsd_freebsd4_sigtramp_middle;
150 end = i386fbsd_freebsd4_sigtramp_end;
151 }
152 else if (memcmp (buf, i386fbsd_osigtramp_start,
153 sizeof i386fbsd_osigtramp_start) == 0)
154 {
155 middle = i386fbsd_osigtramp_middle;
156 end = i386fbsd_osigtramp_end;
157 }
158 else
cf424aef
JB
159 return 0;
160
161 /* Since the end is shorter than the middle, check for a matching end
162 next. */
163 pc += sizeof i386fbsd_sigtramp_start;
164 if (!safe_frame_unwind_memory (this_frame, pc, buf,
165 sizeof i386fbsd_sigtramp_end))
166 return 0;
167 if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) == 0)
168 return 1;
169
170 /* If the end didn't match, check for a matching middle. */
171 if (!safe_frame_unwind_memory (this_frame, pc, buf,
172 sizeof i386fbsd_sigtramp_middle))
173 return 0;
174 if (memcmp (buf, middle, sizeof i386fbsd_sigtramp_middle) != 0)
175 return 0;
176
177 /* The middle matched, check for a matching end. */
178 pc += sizeof i386fbsd_sigtramp_middle;
179 if (!safe_frame_unwind_memory (this_frame, pc, buf,
180 sizeof i386fbsd_sigtramp_end))
181 return 0;
182 if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) != 0)
183 return 0;
184
185 return 1;
186}
187
8a96bc77
MK
188/* FreeBSD 3.0-RELEASE or later. */
189
190/* From <machine/reg.h>. */
191static int i386fbsd_r_reg_offset[] =
192{
193 9 * 4, 8 * 4, 7 * 4, 6 * 4, /* %eax, %ecx, %edx, %ebx */
194 15 * 4, 4 * 4, /* %esp, %ebp */
195 3 * 4, 2 * 4, /* %esi, %edi */
196 12 * 4, 14 * 4, /* %eip, %eflags */
197 13 * 4, 16 * 4, /* %cs, %ss */
198 1 * 4, 0 * 4, -1, -1 /* %ds, %es, %fs, %gs */
199};
200
5d93ae8c 201/* Sigtramp routine location. */
cf424aef
JB
202CORE_ADDR i386fbsd_sigtramp_start_addr;
203CORE_ADDR i386fbsd_sigtramp_end_addr;
8a96bc77
MK
204
205/* From <machine/signal.h>. */
abfcdd21 206int i386fbsd_sc_reg_offset[] =
8a96bc77
MK
207{
208 8 + 14 * 4, /* %eax */
209 8 + 13 * 4, /* %ecx */
210 8 + 12 * 4, /* %edx */
211 8 + 11 * 4, /* %ebx */
212 8 + 0 * 4, /* %esp */
213 8 + 1 * 4, /* %ebp */
214 8 + 10 * 4, /* %esi */
215 8 + 9 * 4, /* %edi */
216 8 + 3 * 4, /* %eip */
217 8 + 4 * 4, /* %eflags */
218 8 + 7 * 4, /* %cs */
219 8 + 8 * 4, /* %ss */
220 8 + 6 * 4, /* %ds */
221 8 + 5 * 4, /* %es */
222 8 + 15 * 4, /* %fs */
223 8 + 16 * 4 /* %gs */
224};
225
97de3545
JB
226/* Get XSAVE extended state xcr0 from core dump. */
227
228uint64_t
229i386fbsd_core_read_xcr0 (bfd *abfd)
230{
231 asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate");
232 uint64_t xcr0;
233
234 if (xstate)
235 {
236 size_t size = bfd_section_size (abfd, xstate);
237
238 /* Check extended state size. */
239 if (size < X86_XSTATE_AVX_SIZE)
240 xcr0 = X86_XSTATE_SSE_MASK;
241 else
242 {
243 char contents[8];
244
245 if (! bfd_get_section_contents (abfd, xstate, contents,
246 I386_FBSD_XSAVE_XCR0_OFFSET,
247 8))
248 {
249 warning (_("Couldn't read `xcr0' bytes from "
250 "`.reg-xstate' section in core file."));
d78bdb54 251 return X86_XSTATE_SSE_MASK;
97de3545
JB
252 }
253
254 xcr0 = bfd_get_64 (abfd, contents);
255 }
256 }
257 else
d78bdb54 258 xcr0 = X86_XSTATE_SSE_MASK;
97de3545
JB
259
260 return xcr0;
261}
262
263/* Implement the core_read_description gdbarch method. */
264
265static const struct target_desc *
266i386fbsd_core_read_description (struct gdbarch *gdbarch,
267 struct target_ops *target,
268 bfd *abfd)
269{
270 return i386_target_description (i386fbsd_core_read_xcr0 (abfd));
271}
272
273/* Similar to i386_supply_fpregset, but use XSAVE extended state. */
274
275static void
276i386fbsd_supply_xstateregset (const struct regset *regset,
277 struct regcache *regcache, int regnum,
278 const void *xstateregs, size_t len)
279{
280 i387_supply_xsave (regcache, regnum, xstateregs);
281}
282
283/* Similar to i386_collect_fpregset, but use XSAVE extended state. */
284
285static void
286i386fbsd_collect_xstateregset (const struct regset *regset,
287 const struct regcache *regcache,
288 int regnum, void *xstateregs, size_t len)
289{
290 i387_collect_xsave (regcache, regnum, xstateregs, 1);
291}
292
293/* Register set definitions. */
294
295static const struct regset i386fbsd_xstateregset =
296 {
297 NULL,
298 i386fbsd_supply_xstateregset,
299 i386fbsd_collect_xstateregset
300 };
301
302/* Iterate over core file register note sections. */
303
304static void
305i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
306 iterate_over_regset_sections_cb *cb,
307 void *cb_data,
308 const struct regcache *regcache)
309{
310 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
311
a616bb94
AH
312 cb (".reg", tdep->sizeof_gregset, tdep->sizeof_gregset, &i386_gregset, NULL,
313 cb_data);
314 cb (".reg2", tdep->sizeof_fpregset, tdep->sizeof_fpregset, &i386_fpregset,
315 NULL, cb_data);
97de3545
JB
316
317 if (tdep->xcr0 & X86_XSTATE_AVX)
a616bb94
AH
318 cb (".reg-xstate", X86_XSTATE_SIZE (tdep->xcr0),
319 X86_XSTATE_SIZE (tdep->xcr0), &i386fbsd_xstateregset,
320 "XSAVE extended state", cb_data);
97de3545
JB
321}
322
8a96bc77 323static void
1736a7bd 324i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
8a96bc77
MK
325{
326 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
327
328 /* Obviously FreeBSD is BSD-based. */
329 i386bsd_init_abi (info, gdbarch);
330
331 /* FreeBSD has a different `struct reg', and reserves some space for
332 its FPU emulator in `struct fpreg'. */
333 tdep->gregset_reg_offset = i386fbsd_r_reg_offset;
334 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset);
335 tdep->sizeof_gregset = 18 * 4;
336 tdep->sizeof_fpregset = 176;
337
338 /* FreeBSD uses -freg-struct-return by default. */
339 tdep->struct_return = reg_struct_return;
340
cf424aef
JB
341 tdep->sigtramp_p = i386fbsd_sigtramp_p;
342
8a96bc77 343 /* FreeBSD uses a different memory layout. */
5d93ae8c
MK
344 tdep->sigtramp_start = i386fbsd_sigtramp_start_addr;
345 tdep->sigtramp_end = i386fbsd_sigtramp_end_addr;
8a96bc77
MK
346
347 /* FreeBSD has a more complete `struct sigcontext'. */
348 tdep->sc_reg_offset = i386fbsd_sc_reg_offset;
349 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset);
fa565c2b 350
8a96bc77
MK
351 i386_elf_init_abi (info, gdbarch);
352
1736a7bd 353 /* FreeBSD uses SVR4-style shared libraries. */
7e654c37
MK
354 set_solib_svr4_fetch_link_map_offsets
355 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
8a96bc77
MK
356}
357
358/* FreeBSD 4.0-RELEASE or later. */
359
360/* From <machine/reg.h>. */
361static int i386fbsd4_r_reg_offset[] =
362{
363 10 * 4, 9 * 4, 8 * 4, 7 * 4, /* %eax, %ecx, %edx, %ebx */
364 16 * 4, 5 * 4, /* %esp, %ebp */
365 4 * 4, 3 * 4, /* %esi, %edi */
366 13 * 4, 15 * 4, /* %eip, %eflags */
367 14 * 4, 17 * 4, /* %cs, %ss */
368 2 * 4, 1 * 4, 0 * 4, 18 * 4 /* %ds, %es, %fs, %gs */
369};
370
371/* From <machine/signal.h>. */
372int i386fbsd4_sc_reg_offset[] =
373{
374 20 + 11 * 4, /* %eax */
375 20 + 10 * 4, /* %ecx */
376 20 + 9 * 4, /* %edx */
377 20 + 8 * 4, /* %ebx */
378 20 + 17 * 4, /* %esp */
379 20 + 6 * 4, /* %ebp */
380 20 + 5 * 4, /* %esi */
381 20 + 4 * 4, /* %edi */
382 20 + 14 * 4, /* %eip */
383 20 + 16 * 4, /* %eflags */
384 20 + 15 * 4, /* %cs */
385 20 + 18 * 4, /* %ss */
386 20 + 3 * 4, /* %ds */
387 20 + 2 * 4, /* %es */
388 20 + 1 * 4, /* %fs */
389 20 + 0 * 4 /* %gs */
390};
391
392static void
393i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
394{
395 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
396
490496c3
AA
397 /* Generic FreeBSD support. */
398 fbsd_init_abi (info, gdbarch);
399
8a96bc77
MK
400 /* Inherit stuff from older releases. We assume that FreeBSD
401 4.0-RELEASE always uses ELF. */
402 i386fbsd_init_abi (info, gdbarch);
403
404 /* FreeBSD 4.0 introduced a new `struct reg'. */
405 tdep->gregset_reg_offset = i386fbsd4_r_reg_offset;
406 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset);
407 tdep->sizeof_gregset = 19 * 4;
408
409 /* FreeBSD 4.0 introduced a new `struct sigcontext'. */
410 tdep->sc_reg_offset = i386fbsd4_sc_reg_offset;
411 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset);
97de3545
JB
412
413 tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
414
415 /* Iterate over core file register note sections. */
416 set_gdbarch_iterate_over_regset_sections
417 (gdbarch, i386fbsd_iterate_over_regset_sections);
418
419 set_gdbarch_core_read_description (gdbarch,
420 i386fbsd_core_read_description);
8a96bc77
MK
421}
422
8a96bc77
MK
423void
424_initialize_i386fbsd_tdep (void)
425{
1736a7bd 426 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD,
8a96bc77
MK
427 i386fbsd4_init_abi);
428}
This page took 1.253414 seconds and 4 git commands to generate.