Fix reading of .debug_str_offsets{,.dwo} twice.
[deliverable/binutils-gdb.git] / gdb / i386fbsd-tdep.c
CommitLineData
8a96bc77
MK
1/* Target-dependent code for FreeBSD/i386.
2
32d0add0 3 Copyright (C) 2003-2015 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
MK
24#include "regcache.h"
25
8a96bc77
MK
26#include "i386-tdep.h"
27#include "i387-tdep.h"
fa565c2b 28#include "bsd-uthread.h"
490496c3 29#include "fbsd-tdep.h"
7e654c37 30#include "solib-svr4.h"
8a96bc77 31
cf424aef
JB
32/* Support for signal handlers. */
33
34/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp
35 routine. */
36
37/* FreeBSD/i386 supports three different signal trampolines, one for
38 versions before 4.0, a second for 4.x, and a third for 5.0 and
39 later. To complicate matters, FreeBSD/i386 binaries running under
40 an amd64 kernel use a different set of trampolines. These
41 trampolines differ from the i386 kernel trampolines in that they
42 omit a middle section that conditionally restores %gs. */
43
44static const gdb_byte i386fbsd_sigtramp_start[] =
45{
46 0x8d, 0x44, 0x24, 0x20, /* lea SIGF_UC(%esp),%eax */
47 0x50 /* pushl %eax */
48};
49
50static const gdb_byte i386fbsd_sigtramp_middle[] =
51{
52 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00,
53 /* testl $PSL_VM,UC_EFLAGS(%eax) */
54 0x75, 0x03, /* jne +3 */
55 0x8e, 0x68, 0x14 /* mov UC_GS(%eax),%gs */
56};
57
58static const gdb_byte i386fbsd_sigtramp_end[] =
59{
60 0xb8, 0xa1, 0x01, 0x00, 0x00, /* movl $SYS_sigreturn,%eax */
61 0x50, /* pushl %eax */
62 0xcd, 0x80 /* int $0x80 */
63};
64
65static const gdb_byte i386fbsd_freebsd4_sigtramp_start[] =
66{
67 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC4(%esp),%eax */
68 0x50 /* pushl %eax */
69};
70
71static const gdb_byte i386fbsd_freebsd4_sigtramp_middle[] =
72{
73 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00,
74 /* testl $PSL_VM,UC4_EFLAGS(%eax) */
75 0x75, 0x03, /* jne +3 */
76 0x8e, 0x68, 0x14 /* mov UC4_GS(%eax),%gs */
77};
78
79static const gdb_byte i386fbsd_freebsd4_sigtramp_end[] =
80{
81 0xb8, 0x58, 0x01, 0x00, 0x00, /* movl $344,%eax */
82 0x50, /* pushl %eax */
83 0xcd, 0x80 /* int $0x80 */
84};
85
86static const gdb_byte i386fbsd_osigtramp_start[] =
87{
88 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_SC(%esp),%eax */
89 0x50 /* pushl %eax */
90};
91
92static const gdb_byte i386fbsd_osigtramp_middle[] =
93{
94 0xf7, 0x40, 0x18, 0x00, 0x00, 0x02, 0x00,
95 /* testl $PSL_VM,SC_PS(%eax) */
96 0x75, 0x03, /* jne +3 */
97 0x8e, 0x68, 0x44 /* mov SC_GS(%eax),%gs */
98};
99
100static const gdb_byte i386fbsd_osigtramp_end[] =
101{
102 0xb8, 0x67, 0x00, 0x00, 0x00, /* movl $103,%eax */
103 0x50, /* pushl %eax */
104 0xcd, 0x80 /* int $0x80 */
105};
106
107/* The three different trampolines are all the same size. */
773eacf5
JB
108gdb_static_assert (sizeof i386fbsd_sigtramp_start
109 == sizeof i386fbsd_freebsd4_sigtramp_start);
110gdb_static_assert (sizeof i386fbsd_sigtramp_start
111 == sizeof i386fbsd_osigtramp_start);
112gdb_static_assert (sizeof i386fbsd_sigtramp_middle
113 == sizeof i386fbsd_freebsd4_sigtramp_middle);
114gdb_static_assert (sizeof i386fbsd_sigtramp_middle
115 == sizeof i386fbsd_osigtramp_middle);
116gdb_static_assert (sizeof i386fbsd_sigtramp_end
117 == sizeof i386fbsd_freebsd4_sigtramp_end);
118gdb_static_assert (sizeof i386fbsd_sigtramp_end
119 == sizeof i386fbsd_osigtramp_end);
cf424aef
JB
120
121/* We assume that the middle is the largest chunk below. */
773eacf5
JB
122gdb_static_assert (sizeof i386fbsd_sigtramp_middle
123 > sizeof i386fbsd_sigtramp_start);
124gdb_static_assert (sizeof i386fbsd_sigtramp_middle
125 > sizeof i386fbsd_sigtramp_end);
cf424aef
JB
126
127static int
128i386fbsd_sigtramp_p (struct frame_info *this_frame)
129{
130 CORE_ADDR pc = get_frame_pc (this_frame);
131 gdb_byte buf[sizeof i386fbsd_sigtramp_middle];
132 const gdb_byte *middle, *end;
133
134 /* Look for a matching start. */
135 if (!safe_frame_unwind_memory (this_frame, pc, buf,
136 sizeof i386fbsd_sigtramp_start))
137 return 0;
773eacf5
JB
138 if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start)
139 == 0)
140 {
141 middle = i386fbsd_sigtramp_middle;
142 end = i386fbsd_sigtramp_end;
143 }
144 else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start,
145 sizeof i386fbsd_freebsd4_sigtramp_start) == 0)
146 {
147 middle = i386fbsd_freebsd4_sigtramp_middle;
148 end = i386fbsd_freebsd4_sigtramp_end;
149 }
150 else if (memcmp (buf, i386fbsd_osigtramp_start,
151 sizeof i386fbsd_osigtramp_start) == 0)
152 {
153 middle = i386fbsd_osigtramp_middle;
154 end = i386fbsd_osigtramp_end;
155 }
156 else
cf424aef
JB
157 return 0;
158
159 /* Since the end is shorter than the middle, check for a matching end
160 next. */
161 pc += sizeof i386fbsd_sigtramp_start;
162 if (!safe_frame_unwind_memory (this_frame, pc, buf,
163 sizeof i386fbsd_sigtramp_end))
164 return 0;
165 if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) == 0)
166 return 1;
167
168 /* If the end didn't match, check for a matching middle. */
169 if (!safe_frame_unwind_memory (this_frame, pc, buf,
170 sizeof i386fbsd_sigtramp_middle))
171 return 0;
172 if (memcmp (buf, middle, sizeof i386fbsd_sigtramp_middle) != 0)
173 return 0;
174
175 /* The middle matched, check for a matching end. */
176 pc += sizeof i386fbsd_sigtramp_middle;
177 if (!safe_frame_unwind_memory (this_frame, pc, buf,
178 sizeof i386fbsd_sigtramp_end))
179 return 0;
180 if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) != 0)
181 return 0;
182
183 return 1;
184}
185
8a96bc77
MK
186/* FreeBSD 3.0-RELEASE or later. */
187
188/* From <machine/reg.h>. */
189static int i386fbsd_r_reg_offset[] =
190{
191 9 * 4, 8 * 4, 7 * 4, 6 * 4, /* %eax, %ecx, %edx, %ebx */
192 15 * 4, 4 * 4, /* %esp, %ebp */
193 3 * 4, 2 * 4, /* %esi, %edi */
194 12 * 4, 14 * 4, /* %eip, %eflags */
195 13 * 4, 16 * 4, /* %cs, %ss */
196 1 * 4, 0 * 4, -1, -1 /* %ds, %es, %fs, %gs */
197};
198
5d93ae8c 199/* Sigtramp routine location. */
cf424aef
JB
200CORE_ADDR i386fbsd_sigtramp_start_addr;
201CORE_ADDR i386fbsd_sigtramp_end_addr;
8a96bc77
MK
202
203/* From <machine/signal.h>. */
abfcdd21 204int i386fbsd_sc_reg_offset[] =
8a96bc77
MK
205{
206 8 + 14 * 4, /* %eax */
207 8 + 13 * 4, /* %ecx */
208 8 + 12 * 4, /* %edx */
209 8 + 11 * 4, /* %ebx */
210 8 + 0 * 4, /* %esp */
211 8 + 1 * 4, /* %ebp */
212 8 + 10 * 4, /* %esi */
213 8 + 9 * 4, /* %edi */
214 8 + 3 * 4, /* %eip */
215 8 + 4 * 4, /* %eflags */
216 8 + 7 * 4, /* %cs */
217 8 + 8 * 4, /* %ss */
218 8 + 6 * 4, /* %ds */
219 8 + 5 * 4, /* %es */
220 8 + 15 * 4, /* %fs */
221 8 + 16 * 4 /* %gs */
222};
223
1c02b2a5 224/* From /usr/src/lib/libc/i386/gen/_setjmp.S. */
fa565c2b
MK
225static int i386fbsd_jmp_buf_reg_offset[] =
226{
227 -1, /* %eax */
228 -1, /* %ecx */
229 -1, /* %edx */
230 1 * 4, /* %ebx */
231 2 * 4, /* %esp */
232 3 * 4, /* %ebp */
233 4 * 4, /* %esi */
234 5 * 4, /* %edi */
235 0 * 4 /* %eip */
236};
237
238static void
239i386fbsd_supply_uthread (struct regcache *regcache,
240 int regnum, CORE_ADDR addr)
241{
e362b510 242 gdb_byte buf[4];
fa565c2b
MK
243 int i;
244
245 gdb_assert (regnum >= -1);
246
247 for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
248 {
249 if (i386fbsd_jmp_buf_reg_offset[i] != -1
250 && (regnum == -1 || regnum == i))
251 {
252 read_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
253 regcache_raw_supply (regcache, i, buf);
254 }
255 }
256}
257
258static void
259i386fbsd_collect_uthread (const struct regcache *regcache,
260 int regnum, CORE_ADDR addr)
261{
e362b510 262 gdb_byte buf[4];
fa565c2b
MK
263 int i;
264
265 gdb_assert (regnum >= -1);
266
267 for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
268 {
269 if (i386fbsd_jmp_buf_reg_offset[i] != -1
270 && (regnum == -1 || regnum == i))
271 {
272 regcache_raw_collect (regcache, i, buf);
273 write_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
274 }
275 }
276}
277
8a96bc77
MK
278static void
279i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
280{
281 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
282
283 /* Obviously FreeBSD is BSD-based. */
284 i386bsd_init_abi (info, gdbarch);
285
286 /* FreeBSD has a different `struct reg', and reserves some space for
287 its FPU emulator in `struct fpreg'. */
288 tdep->gregset_reg_offset = i386fbsd_r_reg_offset;
289 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset);
290 tdep->sizeof_gregset = 18 * 4;
291 tdep->sizeof_fpregset = 176;
292
293 /* FreeBSD uses -freg-struct-return by default. */
294 tdep->struct_return = reg_struct_return;
295
cf424aef
JB
296 tdep->sigtramp_p = i386fbsd_sigtramp_p;
297
8a96bc77 298 /* FreeBSD uses a different memory layout. */
5d93ae8c
MK
299 tdep->sigtramp_start = i386fbsd_sigtramp_start_addr;
300 tdep->sigtramp_end = i386fbsd_sigtramp_end_addr;
8a96bc77
MK
301
302 /* FreeBSD has a more complete `struct sigcontext'. */
303 tdep->sc_reg_offset = i386fbsd_sc_reg_offset;
304 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset);
fa565c2b
MK
305
306 /* FreeBSD provides a user-level threads implementation. */
307 bsd_uthread_set_supply_uthread (gdbarch, i386fbsd_supply_uthread);
308 bsd_uthread_set_collect_uthread (gdbarch, i386fbsd_collect_uthread);
8a96bc77
MK
309}
310
311static void
312i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
313{
314 /* It's almost identical to FreeBSD a.out. */
315 i386fbsdaout_init_abi (info, gdbarch);
316
317 /* Except that it uses ELF. */
318 i386_elf_init_abi (info, gdbarch);
319
320 /* FreeBSD ELF uses SVR4-style shared libraries. */
7e654c37
MK
321 set_solib_svr4_fetch_link_map_offsets
322 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
8a96bc77
MK
323}
324
325/* FreeBSD 4.0-RELEASE or later. */
326
327/* From <machine/reg.h>. */
328static int i386fbsd4_r_reg_offset[] =
329{
330 10 * 4, 9 * 4, 8 * 4, 7 * 4, /* %eax, %ecx, %edx, %ebx */
331 16 * 4, 5 * 4, /* %esp, %ebp */
332 4 * 4, 3 * 4, /* %esi, %edi */
333 13 * 4, 15 * 4, /* %eip, %eflags */
334 14 * 4, 17 * 4, /* %cs, %ss */
335 2 * 4, 1 * 4, 0 * 4, 18 * 4 /* %ds, %es, %fs, %gs */
336};
337
338/* From <machine/signal.h>. */
339int i386fbsd4_sc_reg_offset[] =
340{
341 20 + 11 * 4, /* %eax */
342 20 + 10 * 4, /* %ecx */
343 20 + 9 * 4, /* %edx */
344 20 + 8 * 4, /* %ebx */
345 20 + 17 * 4, /* %esp */
346 20 + 6 * 4, /* %ebp */
347 20 + 5 * 4, /* %esi */
348 20 + 4 * 4, /* %edi */
349 20 + 14 * 4, /* %eip */
350 20 + 16 * 4, /* %eflags */
351 20 + 15 * 4, /* %cs */
352 20 + 18 * 4, /* %ss */
353 20 + 3 * 4, /* %ds */
354 20 + 2 * 4, /* %es */
355 20 + 1 * 4, /* %fs */
356 20 + 0 * 4 /* %gs */
357};
358
359static void
360i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
361{
362 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
363
490496c3
AA
364 /* Generic FreeBSD support. */
365 fbsd_init_abi (info, gdbarch);
366
8a96bc77
MK
367 /* Inherit stuff from older releases. We assume that FreeBSD
368 4.0-RELEASE always uses ELF. */
369 i386fbsd_init_abi (info, gdbarch);
370
371 /* FreeBSD 4.0 introduced a new `struct reg'. */
372 tdep->gregset_reg_offset = i386fbsd4_r_reg_offset;
373 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset);
374 tdep->sizeof_gregset = 19 * 4;
375
376 /* FreeBSD 4.0 introduced a new `struct sigcontext'. */
377 tdep->sc_reg_offset = i386fbsd4_sc_reg_offset;
378 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset);
379}
380
381\f
382/* Provide a prototype to silence -Wmissing-prototypes. */
383void _initialize_i386fbsd_tdep (void);
384
385void
386_initialize_i386fbsd_tdep (void)
387{
388 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_AOUT,
389 i386fbsdaout_init_abi);
390 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_ELF,
391 i386fbsd4_init_abi);
392}
This page took 1.769295 seconds and 4 git commands to generate.