xref: /openbsd-src/gnu/usr.bin/binutils/gdb/i386obsd-tdep.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
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 "frame-unwind.h"
28 #include "gdbcore.h"
29 #include "regcache.h"
30 #include "regset.h"
31 #include "symtab.h"
32 #include "objfiles.h"
33 #include "osabi.h"
34 #include "target.h"
35 #include "trad-frame.h"
36 
37 #include "gdb_assert.h"
38 #include "gdb_string.h"
39 
40 #include "i386-tdep.h"
41 #include "i387-tdep.h"
42 #include "solib-svr4.h"
43 #include "bsd-uthread.h"
44 
45 /* Support for signal handlers.  */
46 
47 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
48    in virtual memory.  The randomness makes it somewhat tricky to
49    detect it, but fortunately we can rely on the fact that the start
50    of the sigtramp routine is page-aligned.  By the way, the mapping
51    is read-only, so you cannot place a breakpoint in the signal
52    trampoline.  */
53 
54 /* Default page size.  */
55 static const int i386obsd_page_size = 4096;
56 
57 /* Offset for sigreturn(2).  */
58 static const int i386obsd_sigreturn_offset[] = {
59   0x0a,				/* OpenBSD 3.2 */
60   0x14,				/* OpenBSD 3.6 */
61   0x3a,				/* OpenBSD 3.8 */
62   -1
63 };
64 
65 /* Return whether the frame preceding NEXT_FRAME corresponds to an
66    OpenBSD sigtramp routine.  */
67 
68 static int
69 i386obsd_sigtramp_p (struct frame_info *next_frame)
70 {
71   CORE_ADDR pc = frame_pc_unwind (next_frame);
72   CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
73   const char sigreturn[] =
74   {
75     0xb8,
76     0x67, 0x00, 0x00, 0x00,	/* movl $SYS_sigreturn, %eax */
77     0xcd, 0x80			/* int $0x80 */
78   };
79   size_t buflen = sizeof sigreturn;
80   const int *offset;
81   char *name, *buf;
82 
83   /* If the function has a valid symbol name, it isn't a
84      trampoline.  */
85   find_pc_partial_function (pc, &name, NULL, NULL);
86   if (name != NULL)
87     return 0;
88 
89   /* If the function lives in a valid section (even without a starting
90      point) it isn't a trampoline.  */
91   if (find_pc_section (pc) != NULL)
92     return 0;
93 
94   /* Allocate buffer.  */
95   buf = alloca (buflen);
96 
97   /* Loop over all offsets.  */
98   for (offset = i386obsd_sigreturn_offset; *offset != -1; offset++)
99     {
100       /* If we can't read the instructions, return zero.  */
101       if (!safe_frame_unwind_memory (next_frame, start_pc + *offset,
102 				     buf, buflen))
103 	return 0;
104 
105       /* Check for sigreturn(2).  */
106       if (memcmp (buf, sigreturn, buflen) == 0)
107 	return 1;
108     }
109 
110   return 0;
111 }
112 
113 /* Mapping between the general-purpose registers in `struct reg'
114    format and GDB's register cache layout.  */
115 
116 /* From <machine/reg.h>.  */
117 static int i386obsd_r_reg_offset[] =
118 {
119   0 * 4,			/* %eax */
120   1 * 4,			/* %ecx */
121   2 * 4,			/* %edx */
122   3 * 4,			/* %ebx */
123   4 * 4,			/* %esp */
124   5 * 4,			/* %ebp */
125   6 * 4,			/* %esi */
126   7 * 4,			/* %edi */
127   8 * 4,			/* %eip */
128   9 * 4,			/* %eflags */
129   10 * 4,			/* %cs */
130   11 * 4,			/* %ss */
131   12 * 4,			/* %ds */
132   13 * 4,			/* %es */
133   14 * 4,			/* %fs */
134   15 * 4			/* %gs */
135 };
136 
137 static void
138 i386obsd_aout_supply_regset (const struct regset *regset,
139 			     struct regcache *regcache, int regnum,
140 			     const void *regs, size_t len)
141 {
142   const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
143 
144   gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
145 
146   i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
147   i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset);
148 }
149 
150 static const struct regset *
151 i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
152 					const char *sect_name,
153 					size_t sect_size)
154 {
155   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
156 
157   /* OpenBSD a.out core dumps don't use seperate register sets for the
158      general-purpose and floating-point registers.  */
159 
160   if (strcmp (sect_name, ".reg") == 0
161       && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
162     {
163       if (tdep->gregset == NULL)
164         tdep->gregset =
165 	  regset_alloc (gdbarch, i386obsd_aout_supply_regset, NULL);
166       return tdep->gregset;
167     }
168 
169   return NULL;
170 }
171 
172 
173 /* Sigtramp routine location for OpenBSD 3.1 and earlier releases.  */
174 CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
175 CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
176 
177 /* From <machine/signal.h>.  */
178 int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
179 {
180   10 * 4,			/* %eax */
181   9 * 4,			/* %ecx */
182   8 * 4,			/* %edx */
183   7 * 4,			/* %ebx */
184   14 * 4,			/* %esp */
185   6 * 4,			/* %ebp */
186   5 * 4,			/* %esi */
187   4 * 4,			/* %edi */
188   11 * 4,			/* %eip */
189   13 * 4,			/* %eflags */
190   12 * 4,			/* %cs */
191   15 * 4,			/* %ss */
192   3 * 4,			/* %ds */
193   2 * 4,			/* %es */
194   1 * 4,			/* %fs */
195   0 * 4				/* %gs */
196 };
197 
198 /* From /usr/src/lib/libpthread/arch/i386/uthread_machdep.c.  */
199 static int i386obsd_uthread_reg_offset[] =
200 {
201   11 * 4,			/* %eax */
202   10 * 4,			/* %ecx */
203   9 * 4,			/* %edx */
204   8 * 4,			/* %ebx */
205   -1,				/* %esp */
206   6 * 4,			/* %ebp */
207   5 * 4,			/* %esi */
208   4 * 4,			/* %edi */
209   12 * 4,			/* %eip */
210   -1,				/* %eflags */
211   13 * 4,			/* %cs */
212   -1,				/* %ss */
213   3 * 4,			/* %ds */
214   2 * 4,			/* %es */
215   1 * 4,			/* %fs */
216   0 * 4				/* %gs */
217 };
218 
219 /* Offset within the thread structure where we can find the saved
220    stack pointer (%esp).  */
221 #define I386OBSD_UTHREAD_ESP_OFFSET	176
222 
223 static void
224 i386obsd_supply_uthread (struct regcache *regcache,
225 			 int regnum, CORE_ADDR addr)
226 {
227   CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
228   CORE_ADDR sp = 0;
229   char buf[4];
230   int i;
231 
232   gdb_assert (regnum >= -1);
233 
234   if (regnum == -1 || regnum == I386_ESP_REGNUM)
235     {
236       int offset;
237 
238       /* Fetch stack pointer from thread structure.  */
239       sp = read_memory_unsigned_integer (sp_addr, 4);
240 
241       /* Adjust the stack pointer such that it looks as if we just
242          returned from _thread_machdep_switch.  */
243       offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
244       store_unsigned_integer (buf, 4, sp + offset);
245       regcache_raw_supply (regcache, I386_ESP_REGNUM, buf);
246     }
247 
248   for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
249     {
250       if (i386obsd_uthread_reg_offset[i] != -1
251 	  && (regnum == -1 || regnum == i))
252 	{
253 	  /* Fetch stack pointer from thread structure (if we didn't
254              do so already).  */
255 	  if (sp == 0)
256 	    sp = read_memory_unsigned_integer (sp_addr, 4);
257 
258 	  /* Read the saved register from the stack frame.  */
259 	  read_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
260 	  regcache_raw_supply (regcache, i, buf);
261 	}
262     }
263 }
264 
265 static void
266 i386obsd_collect_uthread (const struct regcache *regcache,
267 			  int regnum, CORE_ADDR addr)
268 {
269   CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
270   CORE_ADDR sp = 0;
271   char buf[4];
272   int i;
273 
274   gdb_assert (regnum >= -1);
275 
276   if (regnum == -1 || regnum == I386_ESP_REGNUM)
277     {
278       int offset;
279 
280       /* Calculate the stack pointer (frame pointer) that will be
281          stored into the thread structure.  */
282       offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
283       regcache_raw_collect (regcache, I386_ESP_REGNUM, buf);
284       sp = extract_unsigned_integer (buf, 4) - offset;
285 
286       /* Store the stack pointer.  */
287       write_memory_unsigned_integer (sp_addr, 4, sp);
288 
289       /* The stack pointer was (potentially) modified.  Make sure we
290          build a proper stack frame.  */
291       regnum = -1;
292     }
293 
294   for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
295     {
296       if (i386obsd_uthread_reg_offset[i] != -1
297 	  && (regnum == -1 || regnum == i))
298 	{
299 	  /* Fetch stack pointer from thread structure (if we didn't
300              calculate it already).  */
301 	  if (sp == 0)
302 	    sp = read_memory_unsigned_integer (sp_addr, 4);
303 
304 	  /* Write the register into the stack frame.  */
305 	  regcache_raw_collect (regcache, i, buf);
306 	  write_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
307 	}
308     }
309 }
310 
311 /* Kernel debugging support.  */
312 
313 /* From <machine/frame.h>.  Note that %esp and %ess are only saved in
314    a trap frame when entering the kernel from user space.  */
315 static int i386obsd_tf_reg_offset[] =
316 {
317   10 * 4,			/* %eax */
318   9 * 4,			/* %ecx */
319   8 * 4,			/* %edx */
320   7 * 4,			/* %ebx */
321   -1,				/* %esp */
322   6 * 4,			/* %ebp */
323   5 * 4,			/* %esi */
324   4 * 4,			/* %edi */
325   13 * 4,			/* %eip */
326   15 * 4,			/* %eflags */
327   14 * 4,			/* %cs */
328   -1,				/* %ss */
329   3 * 4,			/* %ds */
330   2 * 4,			/* %es */
331   0 * 4,			/* %fs */
332   1 * 4				/* %gs */
333 };
334 
335 static struct trad_frame_cache *
336 i386obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache)
337 {
338   struct trad_frame_cache *cache;
339   CORE_ADDR func, sp, addr;
340   ULONGEST cs;
341   char *name;
342   int i;
343 
344   if (*this_cache)
345     return *this_cache;
346 
347   cache = trad_frame_cache_zalloc (next_frame);
348   *this_cache = cache;
349 
350   func = frame_func_unwind (next_frame);
351   sp = frame_unwind_register_unsigned (next_frame, I386_ESP_REGNUM);
352 
353   find_pc_partial_function (func, &name, NULL, NULL);
354   if (name && strncmp (name, "Xintr", 5) == 0)
355     addr = sp + 8;		/* It's an interrupt frame.  */
356   else
357     addr = sp;
358 
359   for (i = 0; i < ARRAY_SIZE (i386obsd_tf_reg_offset); i++)
360     if (i386obsd_tf_reg_offset[i] != -1)
361       trad_frame_set_reg_addr (cache, i, addr + i386obsd_tf_reg_offset[i]);
362 
363   /* Read %cs from trap frame.  */
364   addr += i386obsd_tf_reg_offset[I386_CS_REGNUM];
365   cs = read_memory_unsigned_integer (addr, 4);
366   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
367     {
368       /* Trap from user space; terminate backtrace.  */
369       trad_frame_set_id (cache, null_frame_id);
370     }
371   else
372     {
373       /* Construct the frame ID using the function start.  */
374       trad_frame_set_id (cache, frame_id_build (sp + 8, func));
375     }
376 
377   return cache;
378 }
379 
380 static void
381 i386obsd_trapframe_this_id (struct frame_info *next_frame,
382 			    void **this_cache, struct frame_id *this_id)
383 {
384   struct trad_frame_cache *cache =
385     i386obsd_trapframe_cache (next_frame, this_cache);
386 
387   trad_frame_get_id (cache, this_id);
388 }
389 
390 static void
391 i386obsd_trapframe_prev_register (struct frame_info *next_frame,
392 				  void **this_cache, int regnum,
393 				  int *optimizedp, enum lval_type *lvalp,
394 				  CORE_ADDR *addrp, int *realnump,
395 				  void *valuep)
396 {
397   struct trad_frame_cache *cache =
398     i386obsd_trapframe_cache (next_frame, this_cache);
399 
400   trad_frame_get_register (cache, next_frame, regnum,
401 			   optimizedp, lvalp, addrp, realnump, valuep);
402 }
403 
404 static int
405 i386obsd_trapframe_sniffer (const struct frame_unwind *self,
406 			    struct frame_info *next_frame,
407 			    void **this_prologue_cache)
408 {
409   ULONGEST cs;
410   char *name;
411 
412   /* Check Current Privilege Level and bail out if we're not executing
413      in kernel space.  */
414   cs = frame_unwind_register_unsigned (next_frame, I386_CS_REGNUM);
415   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
416     return 0;
417 
418   find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
419   return (name && (strcmp (name, "calltrap") == 0
420 		   || strcmp (name, "syscall1") == 0
421 		   || strncmp (name, "Xintr", 5) == 0
422 		   || strncmp (name, "Xsoft", 5) == 0));
423 }
424 
425 static const struct frame_unwind i386obsd_trapframe_unwind = {
426   /* FIXME: kettenis/20051219: This really is more like an interrupt
427      frame, but SIGTRAMP_FRAME would print <signal handler called>,
428      which really is not what we want here.  */
429   NORMAL_FRAME,
430   i386obsd_trapframe_this_id,
431   i386obsd_trapframe_prev_register,
432   NULL,
433   i386obsd_trapframe_sniffer
434 };
435 
436 
437 static void
438 i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
439 {
440   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
441 
442   /* Obviously OpenBSD is BSD-based.  */
443   i386bsd_init_abi (info, gdbarch);
444 
445   /* OpenBSD has a different `struct reg'.  */
446   tdep->gregset_reg_offset = i386obsd_r_reg_offset;
447   tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset);
448   tdep->sizeof_gregset = 16 * 4;
449 
450   /* OpenBSD uses -freg-struct-return by default.  */
451   tdep->struct_return = reg_struct_return;
452 
453   /* OpenBSD uses a different memory layout.  */
454   tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
455   tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
456   tdep->sigtramp_p = i386obsd_sigtramp_p;
457 
458   /* OpenBSD has a `struct sigcontext' that's different from the
459      original 4.3 BSD.  */
460   tdep->sc_reg_offset = i386obsd_sc_reg_offset;
461   tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
462 
463   /* OpenBSD provides a user-level threads implementation.  */
464   bsd_uthread_set_supply_uthread (gdbarch, i386obsd_supply_uthread);
465   bsd_uthread_set_collect_uthread (gdbarch, i386obsd_collect_uthread);
466 
467   /* Unwind kernel trap frames correctly.  */
468   frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind);
469 }
470 
471 /* OpenBSD a.out.  */
472 
473 static void
474 i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
475 {
476   i386obsd_init_abi (info, gdbarch);
477 
478   /* OpenBSD a.out has a single register set.  */
479   set_gdbarch_regset_from_core_section
480     (gdbarch, i386obsd_aout_regset_from_core_section);
481 }
482 
483 /* OpenBSD ELF.  */
484 
485 static void
486 i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
487 {
488   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
489 
490   /* It's still OpenBSD.  */
491   i386obsd_init_abi (info, gdbarch);
492 
493   /* But ELF-based.  */
494   i386_elf_init_abi (info, gdbarch);
495 
496   /* OpenBSD ELF uses SVR4-style shared libraries.  */
497   set_gdbarch_in_solib_call_trampoline
498     (gdbarch, generic_in_solib_call_trampoline);
499   set_solib_svr4_fetch_link_map_offsets
500     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
501 }
502 
503 
504 /* Provide a prototype to silence -Wmissing-prototypes.  */
505 void _initialize_i386obsd_tdep (void);
506 
507 void
508 _initialize_i386obsd_tdep (void)
509 {
510   /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are
511      indistingushable from NetBSD/i386 a.out binaries, building a GDB
512      that should support both these targets will probably not work as
513      expected.  */
514 #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
515 
516   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT,
517 			  i386obsd_aout_init_abi);
518   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF,
519 			  i386obsd_elf_init_abi);
520 }
521