d8556ea460acf6cd579d8359f107ed10582901b5
[deliverable/binutils-gdb.git] / gdb / i386obsd-tdep.c
1 /* Target-dependent code for OpenBSD/i386.
2
3 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002,
4 2003, 2004
5 Free Software Foundation, Inc.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
23
24 #include "defs.h"
25 #include "arch-utils.h"
26 #include "gdbcore.h"
27 #include "regcache.h"
28 #include "regset.h"
29 #include "osabi.h"
30 #include "target.h"
31
32 #include "gdb_assert.h"
33 #include "gdb_string.h"
34
35 #include "i386-tdep.h"
36 #include "i387-tdep.h"
37 #include "solib-svr4.h"
38
39 /* Support for signal handlers. */
40
41 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
42 in virtual memory. The randomness makes it somewhat tricky to
43 detect it, but fortunately we can rely on the fact that the start
44 of the sigtramp routine is page-aligned. By the way, the mapping
45 is read-only, so you cannot place a breakpoint in the signal
46 trampoline. */
47
48 /* Default page size. */
49 static const int i386obsd_page_size = 4096;
50
51 /* Return whether PC is in an OpenBSD sigtramp routine. */
52
53 static int
54 i386obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
55 {
56 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
57 const char sigreturn[] =
58 {
59 0xb8,
60 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */
61 0xcd, 0x80 /* int $0x80 */
62 };
63 char *buf;
64
65 /* Avoid reading memory from the target if possible. If we're in a
66 named function, we're certainly not in a sigtramp routine
67 provided by the kernel. Take synthetic function names into
68 account though. */
69 if (name && name[0] != '<')
70 return 0;
71
72 /* If we can't read the instructions at START_PC, return zero. */
73 buf = alloca (sizeof sigreturn);
74 if (target_read_memory (start_pc + 0x14, buf, sizeof sigreturn))
75 return 0;
76
77 /* Check for sigreturn(2). */
78 if (memcmp (buf, sigreturn, sizeof sigreturn) == 0)
79 return 1;
80
81 /* Check for a traditional BSD sigtramp routine. */
82 return i386bsd_pc_in_sigtramp (pc, name);
83 }
84
85 /* Return the start address of the sigtramp routine. */
86
87 static CORE_ADDR
88 i386obsd_sigtramp_start (CORE_ADDR pc)
89 {
90 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
91
92 if (i386bsd_pc_in_sigtramp (pc, NULL))
93 return i386bsd_sigtramp_start (pc);
94
95 return start_pc;
96 }
97
98 /* Return the end address of the sigtramp routine. */
99
100 static CORE_ADDR
101 i386obsd_sigtramp_end (CORE_ADDR pc)
102 {
103 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
104
105 if (i386bsd_pc_in_sigtramp (pc, NULL))
106 return i386bsd_sigtramp_end (pc);
107
108 return start_pc + 0x22;
109 }
110 \f
111 /* Mapping between the general-purpose registers in `struct reg'
112 format and GDB's register cache layout. */
113
114 /* From <machine/reg.h>. */
115 static int i386obsd_r_reg_offset[] =
116 {
117 0 * 4, /* %eax */
118 1 * 4, /* %ecx */
119 2 * 4, /* %edx */
120 3 * 4, /* %ebx */
121 4 * 4, /* %esp */
122 5 * 4, /* %ebp */
123 6 * 4, /* %esi */
124 7 * 4, /* %edi */
125 8 * 4, /* %eip */
126 9 * 4, /* %eflags */
127 10 * 4, /* %cs */
128 11 * 4, /* %ss */
129 12 * 4, /* %ds */
130 13 * 4, /* %es */
131 14 * 4, /* %fs */
132 15 * 4 /* %gs */
133 };
134
135 static void
136 i386obsd_aout_supply_regset (const struct regset *regset,
137 struct regcache *regcache, int regnum,
138 const void *regs, size_t len)
139 {
140 const struct gdbarch_tdep *tdep = regset->descr;
141
142 gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
143
144 i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
145 i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset);
146 }
147
148 static const struct regset *
149 i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
150 const char *sect_name,
151 size_t sect_size)
152 {
153 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
154
155 /* OpenBSD a.out core dumps don't use seperate register sets for the
156 general-purpose and floating-point registers. */
157
158 if (strcmp (sect_name, ".reg") == 0
159 && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
160 {
161 if (tdep->gregset == NULL)
162 {
163 tdep->gregset = XMALLOC (struct regset);
164 tdep->gregset->descr = tdep;
165 tdep->gregset->supply_regset = i386obsd_aout_supply_regset;
166 }
167 return tdep->gregset;
168 }
169
170 return NULL;
171 }
172 \f
173
174 /* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */
175 CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
176 CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
177
178 /* From <machine/signal.h>. */
179 int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
180 {
181 10 * 4, /* %eax */
182 9 * 4, /* %ecx */
183 8 * 4, /* %edx */
184 7 * 4, /* %ebx */
185 14 * 4, /* %esp */
186 6 * 4, /* %ebp */
187 5 * 4, /* %esi */
188 4 * 4, /* %edi */
189 11 * 4, /* %eip */
190 13 * 4, /* %eflags */
191 12 * 4, /* %cs */
192 15 * 4, /* %ss */
193 3 * 4, /* %ds */
194 2 * 4, /* %es */
195 1 * 4, /* %fs */
196 0 * 4 /* %gs */
197 };
198
199 static void
200 i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
201 {
202 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
203
204 /* Obviously OpenBSD is BSD-based. */
205 i386bsd_init_abi (info, gdbarch);
206
207 /* OpenBSD has a different `struct reg'. */
208 tdep->gregset_reg_offset = i386obsd_r_reg_offset;
209 tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset);
210 tdep->sizeof_gregset = 16 * 4;
211
212 /* OpenBSD uses -freg-struct-return by default. */
213 tdep->struct_return = reg_struct_return;
214
215 /* OpenBSD uses a different memory layout. */
216 tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
217 tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
218 set_gdbarch_pc_in_sigtramp (gdbarch, i386obsd_pc_in_sigtramp);
219 set_gdbarch_sigtramp_start (gdbarch, i386obsd_sigtramp_start);
220 set_gdbarch_sigtramp_end (gdbarch, i386obsd_sigtramp_end);
221
222 /* OpenBSD has a `struct sigcontext' that's different from the
223 origional 4.3 BSD. */
224 tdep->sc_reg_offset = i386obsd_sc_reg_offset;
225 tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
226 }
227
228 /* OpenBSD a.out. */
229
230 static void
231 i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
232 {
233 i386obsd_init_abi (info, gdbarch);
234
235 /* OpenBSD a.out has a single register set. */
236 set_gdbarch_regset_from_core_section
237 (gdbarch, i386obsd_aout_regset_from_core_section);
238 }
239
240 /* OpenBSD ELF. */
241
242 static void
243 i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
244 {
245 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
246
247 /* It's still OpenBSD. */
248 i386obsd_init_abi (info, gdbarch);
249
250 /* But ELF-based. */
251 i386_elf_init_abi (info, gdbarch);
252
253 /* OpenBSD ELF uses SVR4-style shared libraries. */
254 set_gdbarch_in_solib_call_trampoline
255 (gdbarch, generic_in_solib_call_trampoline);
256 set_solib_svr4_fetch_link_map_offsets
257 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
258 }
259 \f
260
261 /* Provide a prototype to silence -Wmissing-prototypes. */
262 void _initialize_i386obsd_tdep (void);
263
264 void
265 _initialize_i386obsd_tdep (void)
266 {
267 /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are
268 indistingushable from NetBSD/i386 a.out binaries, building a GDB
269 that should support both these targets will probably not work as
270 expected. */
271 #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
272
273 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT,
274 i386obsd_aout_init_abi);
275 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF,
276 i386obsd_elf_init_abi);
277 }
This page took 0.035188 seconds and 3 git commands to generate.