X86: Migrate from 'regset_from_core_section' to 'iterate_over_regset_sections'
[deliverable/binutils-gdb.git] / gdb / i386fbsd-tdep.c
CommitLineData
8a96bc77
MK
1/* Target-dependent code for FreeBSD/i386.
2
ecd75fc8 3 Copyright (C) 2003-2014 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
MK
31
32/* FreeBSD 3.0-RELEASE or later. */
33
34/* From <machine/reg.h>. */
35static int i386fbsd_r_reg_offset[] =
36{
37 9 * 4, 8 * 4, 7 * 4, 6 * 4, /* %eax, %ecx, %edx, %ebx */
38 15 * 4, 4 * 4, /* %esp, %ebp */
39 3 * 4, 2 * 4, /* %esi, %edi */
40 12 * 4, 14 * 4, /* %eip, %eflags */
41 13 * 4, 16 * 4, /* %cs, %ss */
42 1 * 4, 0 * 4, -1, -1 /* %ds, %es, %fs, %gs */
43};
44
5d93ae8c
MK
45/* Sigtramp routine location. */
46CORE_ADDR i386fbsd_sigtramp_start_addr = 0xbfbfdf20;
47CORE_ADDR i386fbsd_sigtramp_end_addr = 0xbfbfdff0;
8a96bc77
MK
48
49/* From <machine/signal.h>. */
abfcdd21 50int i386fbsd_sc_reg_offset[] =
8a96bc77
MK
51{
52 8 + 14 * 4, /* %eax */
53 8 + 13 * 4, /* %ecx */
54 8 + 12 * 4, /* %edx */
55 8 + 11 * 4, /* %ebx */
56 8 + 0 * 4, /* %esp */
57 8 + 1 * 4, /* %ebp */
58 8 + 10 * 4, /* %esi */
59 8 + 9 * 4, /* %edi */
60 8 + 3 * 4, /* %eip */
61 8 + 4 * 4, /* %eflags */
62 8 + 7 * 4, /* %cs */
63 8 + 8 * 4, /* %ss */
64 8 + 6 * 4, /* %ds */
65 8 + 5 * 4, /* %es */
66 8 + 15 * 4, /* %fs */
67 8 + 16 * 4 /* %gs */
68};
69
1c02b2a5 70/* From /usr/src/lib/libc/i386/gen/_setjmp.S. */
fa565c2b
MK
71static int i386fbsd_jmp_buf_reg_offset[] =
72{
73 -1, /* %eax */
74 -1, /* %ecx */
75 -1, /* %edx */
76 1 * 4, /* %ebx */
77 2 * 4, /* %esp */
78 3 * 4, /* %ebp */
79 4 * 4, /* %esi */
80 5 * 4, /* %edi */
81 0 * 4 /* %eip */
82};
83
84static void
85i386fbsd_supply_uthread (struct regcache *regcache,
86 int regnum, CORE_ADDR addr)
87{
e362b510 88 gdb_byte buf[4];
fa565c2b
MK
89 int i;
90
91 gdb_assert (regnum >= -1);
92
93 for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
94 {
95 if (i386fbsd_jmp_buf_reg_offset[i] != -1
96 && (regnum == -1 || regnum == i))
97 {
98 read_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
99 regcache_raw_supply (regcache, i, buf);
100 }
101 }
102}
103
104static void
105i386fbsd_collect_uthread (const struct regcache *regcache,
106 int regnum, CORE_ADDR addr)
107{
e362b510 108 gdb_byte buf[4];
fa565c2b
MK
109 int i;
110
111 gdb_assert (regnum >= -1);
112
113 for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++)
114 {
115 if (i386fbsd_jmp_buf_reg_offset[i] != -1
116 && (regnum == -1 || regnum == i))
117 {
118 regcache_raw_collect (regcache, i, buf);
119 write_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4);
120 }
121 }
122}
123
8a96bc77
MK
124static void
125i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
126{
127 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
128
129 /* Obviously FreeBSD is BSD-based. */
130 i386bsd_init_abi (info, gdbarch);
131
132 /* FreeBSD has a different `struct reg', and reserves some space for
133 its FPU emulator in `struct fpreg'. */
134 tdep->gregset_reg_offset = i386fbsd_r_reg_offset;
135 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset);
136 tdep->sizeof_gregset = 18 * 4;
137 tdep->sizeof_fpregset = 176;
138
139 /* FreeBSD uses -freg-struct-return by default. */
140 tdep->struct_return = reg_struct_return;
141
142 /* FreeBSD uses a different memory layout. */
5d93ae8c
MK
143 tdep->sigtramp_start = i386fbsd_sigtramp_start_addr;
144 tdep->sigtramp_end = i386fbsd_sigtramp_end_addr;
8a96bc77
MK
145
146 /* FreeBSD has a more complete `struct sigcontext'. */
147 tdep->sc_reg_offset = i386fbsd_sc_reg_offset;
148 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset);
fa565c2b
MK
149
150 /* FreeBSD provides a user-level threads implementation. */
151 bsd_uthread_set_supply_uthread (gdbarch, i386fbsd_supply_uthread);
152 bsd_uthread_set_collect_uthread (gdbarch, i386fbsd_collect_uthread);
8a96bc77
MK
153}
154
155static void
156i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
157{
158 /* It's almost identical to FreeBSD a.out. */
159 i386fbsdaout_init_abi (info, gdbarch);
160
161 /* Except that it uses ELF. */
162 i386_elf_init_abi (info, gdbarch);
163
164 /* FreeBSD ELF uses SVR4-style shared libraries. */
7e654c37
MK
165 set_solib_svr4_fetch_link_map_offsets
166 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
8a96bc77
MK
167}
168
169/* FreeBSD 4.0-RELEASE or later. */
170
171/* From <machine/reg.h>. */
172static int i386fbsd4_r_reg_offset[] =
173{
174 10 * 4, 9 * 4, 8 * 4, 7 * 4, /* %eax, %ecx, %edx, %ebx */
175 16 * 4, 5 * 4, /* %esp, %ebp */
176 4 * 4, 3 * 4, /* %esi, %edi */
177 13 * 4, 15 * 4, /* %eip, %eflags */
178 14 * 4, 17 * 4, /* %cs, %ss */
179 2 * 4, 1 * 4, 0 * 4, 18 * 4 /* %ds, %es, %fs, %gs */
180};
181
182/* From <machine/signal.h>. */
183int i386fbsd4_sc_reg_offset[] =
184{
185 20 + 11 * 4, /* %eax */
186 20 + 10 * 4, /* %ecx */
187 20 + 9 * 4, /* %edx */
188 20 + 8 * 4, /* %ebx */
189 20 + 17 * 4, /* %esp */
190 20 + 6 * 4, /* %ebp */
191 20 + 5 * 4, /* %esi */
192 20 + 4 * 4, /* %edi */
193 20 + 14 * 4, /* %eip */
194 20 + 16 * 4, /* %eflags */
195 20 + 15 * 4, /* %cs */
196 20 + 18 * 4, /* %ss */
197 20 + 3 * 4, /* %ds */
198 20 + 2 * 4, /* %es */
199 20 + 1 * 4, /* %fs */
200 20 + 0 * 4 /* %gs */
201};
202
203static void
204i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
205{
206 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
207
490496c3
AA
208 /* Generic FreeBSD support. */
209 fbsd_init_abi (info, gdbarch);
210
8a96bc77
MK
211 /* Inherit stuff from older releases. We assume that FreeBSD
212 4.0-RELEASE always uses ELF. */
213 i386fbsd_init_abi (info, gdbarch);
214
215 /* FreeBSD 4.0 introduced a new `struct reg'. */
216 tdep->gregset_reg_offset = i386fbsd4_r_reg_offset;
217 tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset);
218 tdep->sizeof_gregset = 19 * 4;
219
220 /* FreeBSD 4.0 introduced a new `struct sigcontext'. */
221 tdep->sc_reg_offset = i386fbsd4_sc_reg_offset;
222 tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset);
223}
224
225\f
226/* Provide a prototype to silence -Wmissing-prototypes. */
227void _initialize_i386fbsd_tdep (void);
228
229void
230_initialize_i386fbsd_tdep (void)
231{
232 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_AOUT,
233 i386fbsdaout_init_abi);
234 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_ELF,
235 i386fbsd4_init_abi);
236}
This page took 1.247602 seconds and 4 git commands to generate.