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