* i386-tdep.c (i386_breakpoint_from_pc): Change return type to
[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, 2005
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 "frame.h"
27 #include "gdbcore.h"
28 #include "regcache.h"
29 #include "regset.h"
30 #include "symtab.h"
31 #include "objfiles.h"
32 #include "osabi.h"
33 #include "target.h"
34
35 #include "gdb_assert.h"
36 #include "gdb_string.h"
37
38 #include "i386-tdep.h"
39 #include "i387-tdep.h"
40 #include "solib-svr4.h"
41 #include "bsd-uthread.h"
42
43 /* Support for signal handlers. */
44
45 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
46 in virtual memory. The randomness makes it somewhat tricky to
47 detect it, but fortunately we can rely on the fact that the start
48 of the sigtramp routine is page-aligned. By the way, the mapping
49 is read-only, so you cannot place a breakpoint in the signal
50 trampoline. */
51
52 /* Default page size. */
53 static const int i386obsd_page_size = 4096;
54
55 /* Return whether the frame preceding NEXT_FRAME corresponds to an
56 OpenBSD sigtramp routine. */
57
58 static int
59 i386obsd_sigtramp_p (struct frame_info *next_frame)
60 {
61 CORE_ADDR pc = frame_pc_unwind (next_frame);
62 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
63 const gdb_byte sigreturn[] =
64 {
65 0xb8,
66 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */
67 0xcd, 0x80 /* int $0x80 */
68 };
69 size_t buflen = sizeof sigreturn;
70 gdb_byte *buf;
71 char *name;
72
73 /* If the function has a valid symbol name, it isn't a
74 trampoline. */
75 find_pc_partial_function (pc, &name, NULL, NULL);
76 if (name != NULL)
77 return 0;
78
79 /* If the function lives in a valid section (even without a starting
80 point) it isn't a trampoline. */
81 if (find_pc_section (pc) != NULL)
82 return 0;
83
84 /* Allocate buffer. */
85 buf = alloca (buflen);
86
87 /* If we can't read the instructions at START_PC, return zero. */
88 if (!safe_frame_unwind_memory (next_frame, start_pc + 0x0a, buf, buflen))
89 return 0;
90
91 /* Check for sigreturn(2). */
92 if (memcmp (buf, sigreturn, buflen) == 0)
93 return 1;
94
95 /* If we can't read the instructions at START_PC, return zero. */
96 if (!safe_frame_unwind_memory (next_frame, start_pc + 0x14, buf, buflen))
97 return 0;
98
99 /* Check for sigreturn(2) (again). */
100 if (memcmp (buf, sigreturn, buflen) == 0)
101 return 1;
102
103 return 0;
104 }
105 \f
106 /* Mapping between the general-purpose registers in `struct reg'
107 format and GDB's register cache layout. */
108
109 /* From <machine/reg.h>. */
110 static int i386obsd_r_reg_offset[] =
111 {
112 0 * 4, /* %eax */
113 1 * 4, /* %ecx */
114 2 * 4, /* %edx */
115 3 * 4, /* %ebx */
116 4 * 4, /* %esp */
117 5 * 4, /* %ebp */
118 6 * 4, /* %esi */
119 7 * 4, /* %edi */
120 8 * 4, /* %eip */
121 9 * 4, /* %eflags */
122 10 * 4, /* %cs */
123 11 * 4, /* %ss */
124 12 * 4, /* %ds */
125 13 * 4, /* %es */
126 14 * 4, /* %fs */
127 15 * 4 /* %gs */
128 };
129
130 static void
131 i386obsd_aout_supply_regset (const struct regset *regset,
132 struct regcache *regcache, int regnum,
133 const void *regs, size_t len)
134 {
135 const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
136
137 gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
138
139 i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
140 i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset);
141 }
142
143 static const struct regset *
144 i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
145 const char *sect_name,
146 size_t sect_size)
147 {
148 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
149
150 /* OpenBSD a.out core dumps don't use seperate register sets for the
151 general-purpose and floating-point registers. */
152
153 if (strcmp (sect_name, ".reg") == 0
154 && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
155 {
156 if (tdep->gregset == NULL)
157 tdep->gregset =
158 regset_alloc (gdbarch, i386obsd_aout_supply_regset, NULL);
159 return tdep->gregset;
160 }
161
162 return NULL;
163 }
164 \f
165
166 /* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */
167 CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
168 CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
169
170 /* From <machine/signal.h>. */
171 int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
172 {
173 10 * 4, /* %eax */
174 9 * 4, /* %ecx */
175 8 * 4, /* %edx */
176 7 * 4, /* %ebx */
177 14 * 4, /* %esp */
178 6 * 4, /* %ebp */
179 5 * 4, /* %esi */
180 4 * 4, /* %edi */
181 11 * 4, /* %eip */
182 13 * 4, /* %eflags */
183 12 * 4, /* %cs */
184 15 * 4, /* %ss */
185 3 * 4, /* %ds */
186 2 * 4, /* %es */
187 1 * 4, /* %fs */
188 0 * 4 /* %gs */
189 };
190
191 /* From /usr/src/lib/libpthread/arch/i386/uthread_machdep.c. */
192 static int i386obsd_uthread_reg_offset[] =
193 {
194 11 * 4, /* %eax */
195 10 * 4, /* %ecx */
196 9 * 4, /* %edx */
197 8 * 4, /* %ebx */
198 -1, /* %esp */
199 6 * 4, /* %ebp */
200 5 * 4, /* %esi */
201 4 * 4, /* %edi */
202 12 * 4, /* %eip */
203 -1, /* %eflags */
204 13 * 4, /* %cs */
205 -1, /* %ss */
206 3 * 4, /* %ds */
207 2 * 4, /* %es */
208 1 * 4, /* %fs */
209 0 * 4 /* %gs */
210 };
211
212 /* Offset within the thread structure where we can find the saved
213 stack pointer (%esp). */
214 #define I386OBSD_UTHREAD_ESP_OFFSET 176
215
216 static void
217 i386obsd_supply_uthread (struct regcache *regcache,
218 int regnum, CORE_ADDR addr)
219 {
220 CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
221 CORE_ADDR sp = 0;
222 gdb_byte buf[4];
223 int i;
224
225 gdb_assert (regnum >= -1);
226
227 if (regnum == -1 || regnum == I386_ESP_REGNUM)
228 {
229 int offset;
230
231 /* Fetch stack pointer from thread structure. */
232 sp = read_memory_unsigned_integer (sp_addr, 4);
233
234 /* Adjust the stack pointer such that it looks as if we just
235 returned from _thread_machdep_switch. */
236 offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
237 store_unsigned_integer (buf, 4, sp + offset);
238 regcache_raw_supply (regcache, I386_ESP_REGNUM, buf);
239 }
240
241 for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
242 {
243 if (i386obsd_uthread_reg_offset[i] != -1
244 && (regnum == -1 || regnum == i))
245 {
246 /* Fetch stack pointer from thread structure (if we didn't
247 do so already). */
248 if (sp == 0)
249 sp = read_memory_unsigned_integer (sp_addr, 4);
250
251 /* Read the saved register from the stack frame. */
252 read_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
253 regcache_raw_supply (regcache, i, buf);
254 }
255 }
256
257 }
258
259 static void
260 i386obsd_collect_uthread (const struct regcache *regcache,
261 int regnum, CORE_ADDR addr)
262 {
263 CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
264 CORE_ADDR sp = 0;
265 gdb_byte buf[4];
266 int i;
267
268 gdb_assert (regnum >= -1);
269
270 if (regnum == -1 || regnum == I386_ESP_REGNUM)
271 {
272 int offset;
273
274 /* Calculate the stack pointer (frame pointer) that will be
275 stored into the thread structure. */
276 offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
277 regcache_raw_collect (regcache, I386_ESP_REGNUM, buf);
278 sp = extract_unsigned_integer (buf, 4) - offset;
279
280 /* Store the stack pointer. */
281 write_memory_unsigned_integer (sp_addr, 4, sp);
282
283 /* The stack pointer was (potentially) modified. Make sure we
284 build a proper stack frame. */
285 regnum = -1;
286 }
287
288 for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
289 {
290 if (i386obsd_uthread_reg_offset[i] != -1
291 && (regnum == -1 || regnum == i))
292 {
293 /* Fetch stack pointer from thread structure (if we didn't
294 calculate it already). */
295 if (sp == 0)
296 sp = read_memory_unsigned_integer (sp_addr, 4);
297
298 /* Write the register into the stack frame. */
299 regcache_raw_collect (regcache, i, buf);
300 write_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
301 }
302 }
303 }
304
305 static void
306 i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
307 {
308 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
309
310 /* Obviously OpenBSD is BSD-based. */
311 i386bsd_init_abi (info, gdbarch);
312
313 /* OpenBSD has a different `struct reg'. */
314 tdep->gregset_reg_offset = i386obsd_r_reg_offset;
315 tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset);
316 tdep->sizeof_gregset = 16 * 4;
317
318 /* OpenBSD uses -freg-struct-return by default. */
319 tdep->struct_return = reg_struct_return;
320
321 /* OpenBSD uses a different memory layout. */
322 tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
323 tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
324 tdep->sigtramp_p = i386obsd_sigtramp_p;
325
326 /* OpenBSD has a `struct sigcontext' that's different from the
327 original 4.3 BSD. */
328 tdep->sc_reg_offset = i386obsd_sc_reg_offset;
329 tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
330
331 /* OpenBSD provides a user-level threads implementation. */
332 bsd_uthread_set_supply_uthread (gdbarch, i386obsd_supply_uthread);
333 bsd_uthread_set_collect_uthread (gdbarch, i386obsd_collect_uthread);
334 }
335
336 /* OpenBSD a.out. */
337
338 static void
339 i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
340 {
341 i386obsd_init_abi (info, gdbarch);
342
343 /* OpenBSD a.out has a single register set. */
344 set_gdbarch_regset_from_core_section
345 (gdbarch, i386obsd_aout_regset_from_core_section);
346 }
347
348 /* OpenBSD ELF. */
349
350 static void
351 i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
352 {
353 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
354
355 /* It's still OpenBSD. */
356 i386obsd_init_abi (info, gdbarch);
357
358 /* But ELF-based. */
359 i386_elf_init_abi (info, gdbarch);
360
361 /* OpenBSD ELF uses SVR4-style shared libraries. */
362 set_solib_svr4_fetch_link_map_offsets
363 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
364 }
365 \f
366
367 /* Provide a prototype to silence -Wmissing-prototypes. */
368 void _initialize_i386obsd_tdep (void);
369
370 void
371 _initialize_i386obsd_tdep (void)
372 {
373 /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are
374 indistingushable from NetBSD/i386 a.out binaries, building a GDB
375 that should support both these targets will probably not work as
376 expected. */
377 #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
378
379 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT,
380 i386obsd_aout_init_abi);
381 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF,
382 i386obsd_elf_init_abi);
383 }
This page took 0.053046 seconds and 5 git commands to generate.