1 /* Target-dependent code for OpenBSD/i386.
3 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002,
5 Free Software Foundation, Inc.
7 This file is part of GDB.
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.
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.
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. */
25 #include "arch-utils.h"
32 #include "gdb_assert.h"
33 #include "gdb_string.h"
35 #include "i386-tdep.h"
36 #include "i387-tdep.h"
37 #include "solib-svr4.h"
39 /* Support for signal handlers. */
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
48 /* Default page size. */
49 static const int i386obsd_page_size = 4096;
51 /* Return whether PC is in an OpenBSD sigtramp routine. */
54 i386obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
56 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
57 const char sigreturn[] =
60 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */
61 0xcd, 0x80 /* int $0x80 */
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
69 if (name && name[0] != '<')
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))
77 /* Check for sigreturn(2). */
78 if (memcmp (buf, sigreturn, sizeof sigreturn) == 0)
81 /* Check for a traditional BSD sigtramp routine. */
82 return i386bsd_pc_in_sigtramp (pc, name);
85 /* Return the start address of the sigtramp routine. */
88 i386obsd_sigtramp_start (CORE_ADDR pc)
90 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
92 if (i386bsd_pc_in_sigtramp (pc, NULL))
93 return i386bsd_sigtramp_start (pc);
98 /* Return the end address of the sigtramp routine. */
101 i386obsd_sigtramp_end (CORE_ADDR pc)
103 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
105 if (i386bsd_pc_in_sigtramp (pc, NULL))
106 return i386bsd_sigtramp_end (pc);
108 return start_pc + 0x22;
111 /* Mapping between the general-purpose registers in `struct reg'
112 format and GDB's register cache layout. */
114 /* From <machine/reg.h>. */
115 static int i386obsd_r_reg_offset[] =
136 i386obsd_aout_supply_regset (const struct regset *regset,
137 struct regcache *regcache, int regnum,
138 const void *regs, size_t len)
140 const struct gdbarch_tdep *tdep = regset->descr;
142 gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
144 i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
145 i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset);
148 static const struct regset *
149 i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
150 const char *sect_name,
153 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
155 /* OpenBSD a.out core dumps don't use seperate register sets for the
156 general-purpose and floating-point registers. */
158 if (strcmp (sect_name, ".reg") == 0
159 && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
161 if (tdep->gregset == NULL)
163 tdep->gregset = XMALLOC (struct regset);
164 tdep->gregset->descr = tdep;
165 tdep->gregset->supply_regset = i386obsd_aout_supply_regset;
167 return tdep->gregset;
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;
178 /* From <machine/signal.h>. */
179 int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
190 13 * 4, /* %eflags */
200 i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
202 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
204 /* Obviously OpenBSD is BSD-based. */
205 i386bsd_init_abi (info, gdbarch);
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;
212 /* OpenBSD uses -freg-struct-return by default. */
213 tdep->struct_return = reg_struct_return;
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);
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);
231 i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
233 i386obsd_init_abi (info, gdbarch);
235 /* OpenBSD a.out has a single register set. */
236 set_gdbarch_regset_from_core_section
237 (gdbarch, i386obsd_aout_regset_from_core_section);
243 i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
245 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
247 /* It's still OpenBSD. */
248 i386obsd_init_abi (info, gdbarch);
251 i386_elf_init_abi (info, gdbarch);
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);
261 /* Provide a prototype to silence -Wmissing-prototypes. */
262 void _initialize_i386obsd_tdep (void);
265 _initialize_i386obsd_tdep (void)
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
271 #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
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);