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