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