* gdbint.texinfo (Target Architecture Definition): Remove
[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 "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
42 /* Support for signal handlers. */
43
44 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
45 in virtual memory. The randomness makes it somewhat tricky to
46 detect it, but fortunately we can rely on the fact that the start
47 of the sigtramp routine is page-aligned. By the way, the mapping
48 is read-only, so you cannot place a breakpoint in the signal
49 trampoline. */
50
51 /* Default page size. */
52 static const int i386obsd_page_size = 4096;
53
54 /* Return whether the frame preceding NEXT_FRAME corresponds to an
55 OpenBSD sigtramp routine. */
56
57 static int
58 i386obsd_sigtramp_p (struct frame_info *next_frame)
59 {
60 CORE_ADDR pc = frame_pc_unwind (next_frame);
61 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
62 const char sigreturn[] =
63 {
64 0xb8,
65 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */
66 0xcd, 0x80 /* int $0x80 */
67 };
68 char *name, *buf;
69
70 /* If the function has a valid symbol name, it isn't a
71 trampoline. */
72 find_pc_partial_function (pc, &name, NULL, NULL);
73 if (name != NULL)
74 return 0;
75
76 /* If the function lives in a valid section (even without a starting
77 point) it isn't a trampoline. */
78 if (find_pc_section (pc) != NULL)
79 return 0;
80
81 /* If we can't read the instructions at START_PC, return zero. */
82 buf = alloca (sizeof sigreturn);
83 if (target_read_memory (start_pc + 0x14, buf, sizeof sigreturn))
84 return 0;
85
86 /* Check for sigreturn(2). */
87 if (memcmp (buf, sigreturn, sizeof sigreturn) == 0)
88 return 1;
89
90 return 0;
91 }
92 \f
93 /* Mapping between the general-purpose registers in `struct reg'
94 format and GDB's register cache layout. */
95
96 /* From <machine/reg.h>. */
97 static int i386obsd_r_reg_offset[] =
98 {
99 0 * 4, /* %eax */
100 1 * 4, /* %ecx */
101 2 * 4, /* %edx */
102 3 * 4, /* %ebx */
103 4 * 4, /* %esp */
104 5 * 4, /* %ebp */
105 6 * 4, /* %esi */
106 7 * 4, /* %edi */
107 8 * 4, /* %eip */
108 9 * 4, /* %eflags */
109 10 * 4, /* %cs */
110 11 * 4, /* %ss */
111 12 * 4, /* %ds */
112 13 * 4, /* %es */
113 14 * 4, /* %fs */
114 15 * 4 /* %gs */
115 };
116
117 static void
118 i386obsd_aout_supply_regset (const struct regset *regset,
119 struct regcache *regcache, int regnum,
120 const void *regs, size_t len)
121 {
122 const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
123
124 gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
125
126 i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
127 i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset);
128 }
129
130 static const struct regset *
131 i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
132 const char *sect_name,
133 size_t sect_size)
134 {
135 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
136
137 /* OpenBSD a.out core dumps don't use seperate register sets for the
138 general-purpose and floating-point registers. */
139
140 if (strcmp (sect_name, ".reg") == 0
141 && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
142 {
143 if (tdep->gregset == NULL)
144 tdep->gregset =
145 regset_alloc (gdbarch, i386obsd_aout_supply_regset, NULL);
146 return tdep->gregset;
147 }
148
149 return NULL;
150 }
151 \f
152
153 /* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */
154 CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
155 CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
156
157 /* From <machine/signal.h>. */
158 int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
159 {
160 10 * 4, /* %eax */
161 9 * 4, /* %ecx */
162 8 * 4, /* %edx */
163 7 * 4, /* %ebx */
164 14 * 4, /* %esp */
165 6 * 4, /* %ebp */
166 5 * 4, /* %esi */
167 4 * 4, /* %edi */
168 11 * 4, /* %eip */
169 13 * 4, /* %eflags */
170 12 * 4, /* %cs */
171 15 * 4, /* %ss */
172 3 * 4, /* %ds */
173 2 * 4, /* %es */
174 1 * 4, /* %fs */
175 0 * 4 /* %gs */
176 };
177
178 static void
179 i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
180 {
181 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
182
183 /* Obviously OpenBSD is BSD-based. */
184 i386bsd_init_abi (info, gdbarch);
185
186 /* OpenBSD has a different `struct reg'. */
187 tdep->gregset_reg_offset = i386obsd_r_reg_offset;
188 tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset);
189 tdep->sizeof_gregset = 16 * 4;
190
191 /* OpenBSD uses -freg-struct-return by default. */
192 tdep->struct_return = reg_struct_return;
193
194 /* OpenBSD uses a different memory layout. */
195 tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
196 tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
197 tdep->sigtramp_p = i386obsd_sigtramp_p;
198
199 /* OpenBSD has a `struct sigcontext' that's different from the
200 original 4.3 BSD. */
201 tdep->sc_reg_offset = i386obsd_sc_reg_offset;
202 tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
203 }
204
205 /* OpenBSD a.out. */
206
207 static void
208 i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
209 {
210 i386obsd_init_abi (info, gdbarch);
211
212 /* OpenBSD a.out has a single register set. */
213 set_gdbarch_regset_from_core_section
214 (gdbarch, i386obsd_aout_regset_from_core_section);
215 }
216
217 /* OpenBSD ELF. */
218
219 static void
220 i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
221 {
222 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
223
224 /* It's still OpenBSD. */
225 i386obsd_init_abi (info, gdbarch);
226
227 /* But ELF-based. */
228 i386_elf_init_abi (info, gdbarch);
229
230 /* OpenBSD ELF uses SVR4-style shared libraries. */
231 set_gdbarch_in_solib_call_trampoline
232 (gdbarch, generic_in_solib_call_trampoline);
233 set_solib_svr4_fetch_link_map_offsets
234 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
235 }
236 \f
237
238 /* Provide a prototype to silence -Wmissing-prototypes. */
239 void _initialize_i386obsd_tdep (void);
240
241 void
242 _initialize_i386obsd_tdep (void)
243 {
244 /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are
245 indistingushable from NetBSD/i386 a.out binaries, building a GDB
246 that should support both these targets will probably not work as
247 expected. */
248 #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
249
250 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT,
251 i386obsd_aout_init_abi);
252 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF,
253 i386obsd_elf_init_abi);
254 }
This page took 0.034426 seconds and 4 git commands to generate.