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
i386obsd_sigtramp_p(struct frame_info * next_frame)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 
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
i386obsd_aout_supply_regset(const struct regset * regset,struct regcache * regcache,int regnum,const void * regs,size_t len)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 *
i386obsd_aout_regset_from_core_section(struct gdbarch * gdbarch,const char * sect_name,size_t sect_size)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 
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
i386obsd_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)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
i386obsd_aout_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)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
i386obsd_elf_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)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 
237 
238 /* Provide a prototype to silence -Wmissing-prototypes.  */
239 void _initialize_i386obsd_tdep (void);
240 
241 void
_initialize_i386obsd_tdep(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 }
255