2004-04-03 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / i386obsd-tdep.c
CommitLineData
005328e3 1/* Target-dependent code for OpenBSD/i386.
67457012 2
60a6eeb6
MK
3 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002,
4 2003, 2004
005328e3
MK
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"
67457012 28#include "regset.h"
4be87837 29#include "osabi.h"
5d93ae8c 30#include "target.h"
005328e3 31
67457012
MK
32#include "gdb_assert.h"
33#include "gdb_string.h"
34
005328e3
MK
35#include "i386-tdep.h"
36#include "i387-tdep.h"
60a6eeb6 37#include "solib-svr4.h"
005328e3 38
5d93ae8c
MK
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. */
49static const int i386obsd_page_size = 4096;
50
51/* Return whether PC is in an OpenBSD sigtramp routine. */
52
53static int
54i386obsd_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
87static CORE_ADDR
88i386obsd_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
100static CORE_ADDR
101i386obsd_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
67457012
MK
114/* From <machine/reg.h>. */
115static 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};
005328e3
MK
134
135static void
67457012
MK
136i386obsd_aout_supply_regset (const struct regset *regset,
137 struct regcache *regcache, int regnum,
138 const void *regs, size_t len)
005328e3 139{
67457012
MK
140 const struct gdbarch_tdep *tdep = regset->descr;
141
142 gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
005328e3 143
67457012
MK
144 i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
145 i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset);
005328e3
MK
146}
147
49cfa46f 148static const struct regset *
67457012
MK
149i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
150 const char *sect_name,
151 size_t sect_size)
005328e3 152{
67457012 153 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
005328e3 154
67457012
MK
155 /* OpenBSD a.out core dumps don't use seperate register sets for the
156 general-purpose and floating-point registers. */
005328e3 157
67457012
MK
158 if (strcmp (sect_name, ".reg") == 0
159 && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
005328e3 160 {
67457012
MK
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;
005328e3
MK
168 }
169
67457012 170 return NULL;
005328e3 171}
005328e3
MK
172\f
173
5d93ae8c
MK
174/* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */
175CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
176CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
005328e3
MK
177
178/* From <machine/signal.h>. */
a3386186
MK
179int 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};
005328e3
MK
198
199static void
200i386obsd_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
67457012
MK
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
005328e3
MK
212 /* OpenBSD uses -freg-struct-return by default. */
213 tdep->struct_return = reg_struct_return;
214
215 /* OpenBSD uses a different memory layout. */
5d93ae8c
MK
216 tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
217 tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
f561f026 218 set_gdbarch_deprecated_pc_in_sigtramp (gdbarch, i386obsd_pc_in_sigtramp);
aa2a3f87
AC
219 set_gdbarch_deprecated_sigtramp_start (gdbarch, i386obsd_sigtramp_start);
220 set_gdbarch_deprecated_sigtramp_end (gdbarch, i386obsd_sigtramp_end);
005328e3
MK
221
222 /* OpenBSD has a `struct sigcontext' that's different from the
f2e7c15d 223 original 4.3 BSD. */
a3386186 224 tdep->sc_reg_offset = i386obsd_sc_reg_offset;
67457012 225 tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
005328e3 226}
60a6eeb6
MK
227
228/* OpenBSD a.out. */
229
230static void
231i386obsd_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
242static void
243i386obsd_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}
67457012
MK
259\f
260
261/* Provide a prototype to silence -Wmissing-prototypes. */
262void _initialize_i386obsd_tdep (void);
005328e3
MK
263
264void
265_initialize_i386obsd_tdep (void)
266{
005328e3
MK
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
05816f70 273 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT,
60a6eeb6
MK
274 i386obsd_aout_init_abi);
275 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF,
276 i386obsd_elf_init_abi);
005328e3 277}
This page took 0.174483 seconds and 4 git commands to generate.