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