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