jit: make gdb_symtab::blocks an std::forward_list
[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"
268a13a5 27#include "gdbsupport/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 {
fd361982 236 size_t size = bfd_section_size (xstate);
97de3545
JB
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{
dd6876c9 270 return i386_target_description (i386fbsd_core_read_xcr0 (abfd), true);
97de3545
JB
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
ce25aa57
JB
323/* Implement the get_thread_local_address gdbarch method. */
324
325static CORE_ADDR
326i386fbsd_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid,
327 CORE_ADDR lm_addr, CORE_ADDR offset)
328{
329 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
330 struct regcache *regcache;
331
332 if (tdep->fsbase_regnum == -1)
333 error (_("Unable to fetch %%gsbase"));
334
335 regcache = get_thread_arch_regcache (ptid, gdbarch);
336
337 target_fetch_registers (regcache, tdep->fsbase_regnum + 1);
338
339 ULONGEST gsbase;
340 if (regcache->cooked_read (tdep->fsbase_regnum + 1, &gsbase) != REG_VALID)
341 error (_("Unable to fetch %%gsbase"));
342
343 CORE_ADDR dtv_addr = gsbase + gdbarch_ptr_bit (gdbarch) / 8;
344 return fbsd_get_thread_local_address (gdbarch, dtv_addr, lm_addr, offset);
345}
346
8a96bc77 347static void
1736a7bd 348i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
8a96bc77
MK
349{
350 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
351
352 /* Obviously FreeBSD is BSD-based. */
353 i386bsd_init_abi (info, gdbarch);
354
355 /* FreeBSD has a different `struct reg', and reserves some space for
356 its FPU emulator in `struct fpreg'. */
357 tdep->gregset_reg_offset = i386fbsd_r_reg_offset;
358 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset);
359 tdep->sizeof_gregset = 18 * 4;
360 tdep->sizeof_fpregset = 176;
361
362 /* FreeBSD uses -freg-struct-return by default. */
363 tdep->struct_return = reg_struct_return;
364
cf424aef
JB
365 tdep->sigtramp_p = i386fbsd_sigtramp_p;
366
8a96bc77 367 /* FreeBSD uses a different memory layout. */
5d93ae8c
MK
368 tdep->sigtramp_start = i386fbsd_sigtramp_start_addr;
369 tdep->sigtramp_end = i386fbsd_sigtramp_end_addr;
8a96bc77
MK
370
371 /* FreeBSD has a more complete `struct sigcontext'. */
372 tdep->sc_reg_offset = i386fbsd_sc_reg_offset;
373 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset);
fa565c2b 374
8a96bc77
MK
375 i386_elf_init_abi (info, gdbarch);
376
1736a7bd 377 /* FreeBSD uses SVR4-style shared libraries. */
7e654c37
MK
378 set_solib_svr4_fetch_link_map_offsets
379 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
8a96bc77
MK
380}
381
382/* FreeBSD 4.0-RELEASE or later. */
383
384/* From <machine/reg.h>. */
385static int i386fbsd4_r_reg_offset[] =
386{
387 10 * 4, 9 * 4, 8 * 4, 7 * 4, /* %eax, %ecx, %edx, %ebx */
388 16 * 4, 5 * 4, /* %esp, %ebp */
389 4 * 4, 3 * 4, /* %esi, %edi */
390 13 * 4, 15 * 4, /* %eip, %eflags */
391 14 * 4, 17 * 4, /* %cs, %ss */
392 2 * 4, 1 * 4, 0 * 4, 18 * 4 /* %ds, %es, %fs, %gs */
393};
394
395/* From <machine/signal.h>. */
396int i386fbsd4_sc_reg_offset[] =
397{
398 20 + 11 * 4, /* %eax */
399 20 + 10 * 4, /* %ecx */
400 20 + 9 * 4, /* %edx */
401 20 + 8 * 4, /* %ebx */
402 20 + 17 * 4, /* %esp */
403 20 + 6 * 4, /* %ebp */
404 20 + 5 * 4, /* %esi */
405 20 + 4 * 4, /* %edi */
406 20 + 14 * 4, /* %eip */
407 20 + 16 * 4, /* %eflags */
408 20 + 15 * 4, /* %cs */
409 20 + 18 * 4, /* %ss */
410 20 + 3 * 4, /* %ds */
411 20 + 2 * 4, /* %es */
412 20 + 1 * 4, /* %fs */
413 20 + 0 * 4 /* %gs */
414};
415
416static void
417i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
418{
419 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
420
490496c3
AA
421 /* Generic FreeBSD support. */
422 fbsd_init_abi (info, gdbarch);
423
8a96bc77
MK
424 /* Inherit stuff from older releases. We assume that FreeBSD
425 4.0-RELEASE always uses ELF. */
426 i386fbsd_init_abi (info, gdbarch);
427
428 /* FreeBSD 4.0 introduced a new `struct reg'. */
429 tdep->gregset_reg_offset = i386fbsd4_r_reg_offset;
430 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset);
431 tdep->sizeof_gregset = 19 * 4;
432
433 /* FreeBSD 4.0 introduced a new `struct sigcontext'. */
434 tdep->sc_reg_offset = i386fbsd4_sc_reg_offset;
435 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset);
97de3545
JB
436
437 tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET;
438
439 /* Iterate over core file register note sections. */
440 set_gdbarch_iterate_over_regset_sections
441 (gdbarch, i386fbsd_iterate_over_regset_sections);
442
443 set_gdbarch_core_read_description (gdbarch,
444 i386fbsd_core_read_description);
ce25aa57
JB
445
446 set_gdbarch_fetch_tls_load_module_address (gdbarch,
447 svr4_fetch_objfile_link_map);
448 set_gdbarch_get_thread_local_address (gdbarch,
449 i386fbsd_get_thread_local_address);
8a96bc77
MK
450}
451
8a96bc77
MK
452void
453_initialize_i386fbsd_tdep (void)
454{
1736a7bd 455 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD,
8a96bc77
MK
456 i386fbsd4_init_abi);
457}
This page took 1.416501 seconds and 4 git commands to generate.