xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/i386-obsd-tdep.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1699b0f92Schristos /* Target-dependent code for OpenBSD/i386.
2699b0f92Schristos 
3*6881a400Schristos    Copyright (C) 1988-2023 Free Software Foundation, Inc.
4699b0f92Schristos 
5699b0f92Schristos    This file is part of GDB.
6699b0f92Schristos 
7699b0f92Schristos    This program is free software; you can redistribute it and/or modify
8699b0f92Schristos    it under the terms of the GNU General Public License as published by
9699b0f92Schristos    the Free Software Foundation; either version 3 of the License, or
10699b0f92Schristos    (at your option) any later version.
11699b0f92Schristos 
12699b0f92Schristos    This program is distributed in the hope that it will be useful,
13699b0f92Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14699b0f92Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15699b0f92Schristos    GNU General Public License for more details.
16699b0f92Schristos 
17699b0f92Schristos    You should have received a copy of the GNU General Public License
18699b0f92Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19699b0f92Schristos 
20699b0f92Schristos #include "defs.h"
21699b0f92Schristos #include "arch-utils.h"
22699b0f92Schristos #include "frame.h"
23699b0f92Schristos #include "frame-unwind.h"
24699b0f92Schristos #include "gdbcore.h"
25699b0f92Schristos #include "regcache.h"
26699b0f92Schristos #include "regset.h"
27699b0f92Schristos #include "symtab.h"
28699b0f92Schristos #include "objfiles.h"
29699b0f92Schristos #include "osabi.h"
30699b0f92Schristos #include "target.h"
31699b0f92Schristos #include "trad-frame.h"
32699b0f92Schristos 
33699b0f92Schristos #include "obsd-tdep.h"
34699b0f92Schristos #include "i386-tdep.h"
35699b0f92Schristos #include "i387-tdep.h"
36699b0f92Schristos #include "solib-svr4.h"
37699b0f92Schristos #include "bsd-uthread.h"
38699b0f92Schristos 
39699b0f92Schristos /* Support for signal handlers.  */
40699b0f92Schristos 
41699b0f92Schristos /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
42699b0f92Schristos    in virtual memory.  The randomness makes it somewhat tricky to
43699b0f92Schristos    detect it, but fortunately we can rely on the fact that the start
44699b0f92Schristos    of the sigtramp routine is page-aligned.  We recognize the
45699b0f92Schristos    trampoline by looking for the code that invokes the sigreturn
46699b0f92Schristos    system call.  The offset where we can find that code varies from
47699b0f92Schristos    release to release.
48699b0f92Schristos 
49699b0f92Schristos    By the way, the mapping mentioned above is read-only, so you cannot
50699b0f92Schristos    place a breakpoint in the signal trampoline.  */
51699b0f92Schristos 
52699b0f92Schristos /* Default page size.  */
53699b0f92Schristos static const int i386obsd_page_size = 4096;
54699b0f92Schristos 
55699b0f92Schristos /* Offset for sigreturn(2).  */
56699b0f92Schristos static const int i386obsd_sigreturn_offset[] = {
57699b0f92Schristos   0x0a,				/* OpenBSD 3.2 */
58699b0f92Schristos   0x14,				/* OpenBSD 3.6 */
59699b0f92Schristos   0x3a,				/* OpenBSD 3.8 */
60699b0f92Schristos   -1
61699b0f92Schristos };
62699b0f92Schristos 
63699b0f92Schristos /* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp
64699b0f92Schristos    routine.  */
65699b0f92Schristos 
66699b0f92Schristos static int
67*6881a400Schristos i386obsd_sigtramp_p (frame_info_ptr this_frame)
68699b0f92Schristos {
69699b0f92Schristos   CORE_ADDR pc = get_frame_pc (this_frame);
70699b0f92Schristos   CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
71699b0f92Schristos   /* The call sequence invoking sigreturn(2).  */
72699b0f92Schristos   const gdb_byte sigreturn[] =
73699b0f92Schristos   {
74699b0f92Schristos     0xb8,
75699b0f92Schristos     0x67, 0x00, 0x00, 0x00,	/* movl $SYS_sigreturn, %eax */
76699b0f92Schristos     0xcd, 0x80			/* int $0x80 */
77699b0f92Schristos   };
78699b0f92Schristos   size_t buflen = sizeof sigreturn;
79699b0f92Schristos   const int *offset;
80699b0f92Schristos   gdb_byte *buf;
81699b0f92Schristos   const char *name;
82699b0f92Schristos 
83699b0f92Schristos   /* If the function has a valid symbol name, it isn't a
84699b0f92Schristos      trampoline.  */
85699b0f92Schristos   find_pc_partial_function (pc, &name, NULL, NULL);
86699b0f92Schristos   if (name != NULL)
87699b0f92Schristos     return 0;
88699b0f92Schristos 
89699b0f92Schristos   /* If the function lives in a valid section (even without a starting
90699b0f92Schristos      point) it isn't a trampoline.  */
91699b0f92Schristos   if (find_pc_section (pc) != NULL)
92699b0f92Schristos     return 0;
93699b0f92Schristos 
94699b0f92Schristos   /* Allocate buffer.  */
95699b0f92Schristos   buf = (gdb_byte *) alloca (buflen);
96699b0f92Schristos 
97699b0f92Schristos   /* Loop over all offsets.  */
98699b0f92Schristos   for (offset = i386obsd_sigreturn_offset; *offset != -1; offset++)
99699b0f92Schristos     {
100699b0f92Schristos       /* If we can't read the instructions, return zero.  */
101699b0f92Schristos       if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
102*6881a400Schristos 				     {buf, buflen}))
103699b0f92Schristos 	return 0;
104699b0f92Schristos 
105699b0f92Schristos       /* Check for sigreturn(2).  */
106699b0f92Schristos       if (memcmp (buf, sigreturn, buflen) == 0)
107699b0f92Schristos 	return 1;
108699b0f92Schristos     }
109699b0f92Schristos 
110699b0f92Schristos   return 0;
111699b0f92Schristos }
112699b0f92Schristos 
113699b0f92Schristos /* Mapping between the general-purpose registers in `struct reg'
114699b0f92Schristos    format and GDB's register cache layout.  */
115699b0f92Schristos 
116699b0f92Schristos /* From <machine/reg.h>.  */
117699b0f92Schristos static int i386obsd_r_reg_offset[] =
118699b0f92Schristos {
119699b0f92Schristos   0 * 4,			/* %eax */
120699b0f92Schristos   1 * 4,			/* %ecx */
121699b0f92Schristos   2 * 4,			/* %edx */
122699b0f92Schristos   3 * 4,			/* %ebx */
123699b0f92Schristos   4 * 4,			/* %esp */
124699b0f92Schristos   5 * 4,			/* %ebp */
125699b0f92Schristos   6 * 4,			/* %esi */
126699b0f92Schristos   7 * 4,			/* %edi */
127699b0f92Schristos   8 * 4,			/* %eip */
128699b0f92Schristos   9 * 4,			/* %eflags */
129699b0f92Schristos   10 * 4,			/* %cs */
130699b0f92Schristos   11 * 4,			/* %ss */
131699b0f92Schristos   12 * 4,			/* %ds */
132699b0f92Schristos   13 * 4,			/* %es */
133699b0f92Schristos   14 * 4,			/* %fs */
134699b0f92Schristos   15 * 4			/* %gs */
135699b0f92Schristos };
136699b0f92Schristos 
137699b0f92Schristos 
138699b0f92Schristos 
139699b0f92Schristos /* Sigtramp routine location for OpenBSD 3.1 and earlier releases.  */
140699b0f92Schristos CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
141699b0f92Schristos CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
142699b0f92Schristos 
143699b0f92Schristos /* From <machine/signal.h>.  */
144699b0f92Schristos int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
145699b0f92Schristos {
146699b0f92Schristos   10 * 4,			/* %eax */
147699b0f92Schristos   9 * 4,			/* %ecx */
148699b0f92Schristos   8 * 4,			/* %edx */
149699b0f92Schristos   7 * 4,			/* %ebx */
150699b0f92Schristos   14 * 4,			/* %esp */
151699b0f92Schristos   6 * 4,			/* %ebp */
152699b0f92Schristos   5 * 4,			/* %esi */
153699b0f92Schristos   4 * 4,			/* %edi */
154699b0f92Schristos   11 * 4,			/* %eip */
155699b0f92Schristos   13 * 4,			/* %eflags */
156699b0f92Schristos   12 * 4,			/* %cs */
157699b0f92Schristos   15 * 4,			/* %ss */
158699b0f92Schristos   3 * 4,			/* %ds */
159699b0f92Schristos   2 * 4,			/* %es */
160699b0f92Schristos   1 * 4,			/* %fs */
161699b0f92Schristos   0 * 4				/* %gs */
162699b0f92Schristos };
163699b0f92Schristos 
164699b0f92Schristos /* From /usr/src/lib/libpthread/arch/i386/uthread_machdep.c.  */
165699b0f92Schristos static int i386obsd_uthread_reg_offset[] =
166699b0f92Schristos {
167699b0f92Schristos   11 * 4,			/* %eax */
168699b0f92Schristos   10 * 4,			/* %ecx */
169699b0f92Schristos   9 * 4,			/* %edx */
170699b0f92Schristos   8 * 4,			/* %ebx */
171699b0f92Schristos   -1,				/* %esp */
172699b0f92Schristos   6 * 4,			/* %ebp */
173699b0f92Schristos   5 * 4,			/* %esi */
174699b0f92Schristos   4 * 4,			/* %edi */
175699b0f92Schristos   12 * 4,			/* %eip */
176699b0f92Schristos   -1,				/* %eflags */
177699b0f92Schristos   13 * 4,			/* %cs */
178699b0f92Schristos   -1,				/* %ss */
179699b0f92Schristos   3 * 4,			/* %ds */
180699b0f92Schristos   2 * 4,			/* %es */
181699b0f92Schristos   1 * 4,			/* %fs */
182699b0f92Schristos   0 * 4				/* %gs */
183699b0f92Schristos };
184699b0f92Schristos 
185699b0f92Schristos /* Offset within the thread structure where we can find the saved
186699b0f92Schristos    stack pointer (%esp).  */
187699b0f92Schristos #define I386OBSD_UTHREAD_ESP_OFFSET	176
188699b0f92Schristos 
189699b0f92Schristos static void
190699b0f92Schristos i386obsd_supply_uthread (struct regcache *regcache,
191699b0f92Schristos 			 int regnum, CORE_ADDR addr)
192699b0f92Schristos {
1937f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
194699b0f92Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
195699b0f92Schristos   CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
196699b0f92Schristos   CORE_ADDR sp = 0;
197699b0f92Schristos   gdb_byte buf[4];
198699b0f92Schristos   int i;
199699b0f92Schristos 
200699b0f92Schristos   gdb_assert (regnum >= -1);
201699b0f92Schristos 
202699b0f92Schristos   if (regnum == -1 || regnum == I386_ESP_REGNUM)
203699b0f92Schristos     {
204699b0f92Schristos       int offset;
205699b0f92Schristos 
206699b0f92Schristos       /* Fetch stack pointer from thread structure.  */
207699b0f92Schristos       sp = read_memory_unsigned_integer (sp_addr, 4, byte_order);
208699b0f92Schristos 
209699b0f92Schristos       /* Adjust the stack pointer such that it looks as if we just
210699b0f92Schristos 	 returned from _thread_machdep_switch.  */
211699b0f92Schristos       offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
212699b0f92Schristos       store_unsigned_integer (buf, 4, byte_order, sp + offset);
2137f2ac410Schristos       regcache->raw_supply (I386_ESP_REGNUM, buf);
214699b0f92Schristos     }
215699b0f92Schristos 
216699b0f92Schristos   for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
217699b0f92Schristos     {
218699b0f92Schristos       if (i386obsd_uthread_reg_offset[i] != -1
219699b0f92Schristos 	  && (regnum == -1 || regnum == i))
220699b0f92Schristos 	{
221699b0f92Schristos 	  /* Fetch stack pointer from thread structure (if we didn't
222699b0f92Schristos 	     do so already).  */
223699b0f92Schristos 	  if (sp == 0)
224699b0f92Schristos 	    sp = read_memory_unsigned_integer (sp_addr, 4, byte_order);
225699b0f92Schristos 
226699b0f92Schristos 	  /* Read the saved register from the stack frame.  */
227699b0f92Schristos 	  read_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
2287f2ac410Schristos 	  regcache->raw_supply (i, buf);
229699b0f92Schristos 	}
230699b0f92Schristos     }
231699b0f92Schristos }
232699b0f92Schristos 
233699b0f92Schristos static void
234699b0f92Schristos i386obsd_collect_uthread (const struct regcache *regcache,
235699b0f92Schristos 			  int regnum, CORE_ADDR addr)
236699b0f92Schristos {
2377f2ac410Schristos   struct gdbarch *gdbarch = regcache->arch ();
238699b0f92Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
239699b0f92Schristos   CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
240699b0f92Schristos   CORE_ADDR sp = 0;
241699b0f92Schristos   gdb_byte buf[4];
242699b0f92Schristos   int i;
243699b0f92Schristos 
244699b0f92Schristos   gdb_assert (regnum >= -1);
245699b0f92Schristos 
246699b0f92Schristos   if (regnum == -1 || regnum == I386_ESP_REGNUM)
247699b0f92Schristos     {
248699b0f92Schristos       int offset;
249699b0f92Schristos 
250699b0f92Schristos       /* Calculate the stack pointer (frame pointer) that will be
251699b0f92Schristos 	 stored into the thread structure.  */
252699b0f92Schristos       offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
2537f2ac410Schristos       regcache->raw_collect (I386_ESP_REGNUM, buf);
254699b0f92Schristos       sp = extract_unsigned_integer (buf, 4, byte_order) - offset;
255699b0f92Schristos 
256699b0f92Schristos       /* Store the stack pointer.  */
257699b0f92Schristos       write_memory_unsigned_integer (sp_addr, 4, byte_order, sp);
258699b0f92Schristos 
259699b0f92Schristos       /* The stack pointer was (potentially) modified.  Make sure we
260699b0f92Schristos 	 build a proper stack frame.  */
261699b0f92Schristos       regnum = -1;
262699b0f92Schristos     }
263699b0f92Schristos 
264699b0f92Schristos   for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
265699b0f92Schristos     {
266699b0f92Schristos       if (i386obsd_uthread_reg_offset[i] != -1
267699b0f92Schristos 	  && (regnum == -1 || regnum == i))
268699b0f92Schristos 	{
269699b0f92Schristos 	  /* Fetch stack pointer from thread structure (if we didn't
270699b0f92Schristos 	     calculate it already).  */
271699b0f92Schristos 	  if (sp == 0)
272699b0f92Schristos 	    sp = read_memory_unsigned_integer (sp_addr, 4, byte_order);
273699b0f92Schristos 
274699b0f92Schristos 	  /* Write the register into the stack frame.  */
2757f2ac410Schristos 	  regcache->raw_collect (i, buf);
276699b0f92Schristos 	  write_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
277699b0f92Schristos 	}
278699b0f92Schristos     }
279699b0f92Schristos }
280699b0f92Schristos 
281699b0f92Schristos /* Kernel debugging support.  */
282699b0f92Schristos 
283699b0f92Schristos /* From <machine/frame.h>.  Note that %esp and %ess are only saved in
284699b0f92Schristos    a trap frame when entering the kernel from user space.  */
285699b0f92Schristos static int i386obsd_tf_reg_offset[] =
286699b0f92Schristos {
287699b0f92Schristos   10 * 4,			/* %eax */
288699b0f92Schristos   9 * 4,			/* %ecx */
289699b0f92Schristos   8 * 4,			/* %edx */
290699b0f92Schristos   7 * 4,			/* %ebx */
291699b0f92Schristos   -1,				/* %esp */
292699b0f92Schristos   6 * 4,			/* %ebp */
293699b0f92Schristos   5 * 4,			/* %esi */
294699b0f92Schristos   4 * 4,			/* %edi */
295699b0f92Schristos   13 * 4,			/* %eip */
296699b0f92Schristos   15 * 4,			/* %eflags */
297699b0f92Schristos   14 * 4,			/* %cs */
298699b0f92Schristos   -1,				/* %ss */
299699b0f92Schristos   3 * 4,			/* %ds */
300699b0f92Schristos   2 * 4,			/* %es */
301699b0f92Schristos   0 * 4,			/* %fs */
302699b0f92Schristos   1 * 4				/* %gs */
303699b0f92Schristos };
304699b0f92Schristos 
305699b0f92Schristos static struct trad_frame_cache *
306*6881a400Schristos i386obsd_trapframe_cache (frame_info_ptr this_frame, void **this_cache)
307699b0f92Schristos {
308699b0f92Schristos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
309699b0f92Schristos   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
310699b0f92Schristos   struct trad_frame_cache *cache;
311699b0f92Schristos   CORE_ADDR func, sp, addr;
312699b0f92Schristos   ULONGEST cs;
313699b0f92Schristos   const char *name;
314699b0f92Schristos   int i;
315699b0f92Schristos 
316699b0f92Schristos   if (*this_cache)
317699b0f92Schristos     return (struct trad_frame_cache *) *this_cache;
318699b0f92Schristos 
319699b0f92Schristos   cache = trad_frame_cache_zalloc (this_frame);
320699b0f92Schristos   *this_cache = cache;
321699b0f92Schristos 
322699b0f92Schristos   func = get_frame_func (this_frame);
323699b0f92Schristos   sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
324699b0f92Schristos 
325699b0f92Schristos   find_pc_partial_function (func, &name, NULL, NULL);
326699b0f92Schristos   if (name && startswith (name, "Xintr"))
327699b0f92Schristos     addr = sp + 8;		/* It's an interrupt frame.  */
328699b0f92Schristos   else
329699b0f92Schristos     addr = sp;
330699b0f92Schristos 
331699b0f92Schristos   for (i = 0; i < ARRAY_SIZE (i386obsd_tf_reg_offset); i++)
332699b0f92Schristos     if (i386obsd_tf_reg_offset[i] != -1)
333699b0f92Schristos       trad_frame_set_reg_addr (cache, i, addr + i386obsd_tf_reg_offset[i]);
334699b0f92Schristos 
335699b0f92Schristos   /* Read %cs from trap frame.  */
336699b0f92Schristos   addr += i386obsd_tf_reg_offset[I386_CS_REGNUM];
337699b0f92Schristos   cs = read_memory_unsigned_integer (addr, 4, byte_order);
338699b0f92Schristos   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
339699b0f92Schristos     {
340699b0f92Schristos       /* Trap from user space; terminate backtrace.  */
341699b0f92Schristos       trad_frame_set_id (cache, outer_frame_id);
342699b0f92Schristos     }
343699b0f92Schristos   else
344699b0f92Schristos     {
345699b0f92Schristos       /* Construct the frame ID using the function start.  */
346699b0f92Schristos       trad_frame_set_id (cache, frame_id_build (sp + 8, func));
347699b0f92Schristos     }
348699b0f92Schristos 
349699b0f92Schristos   return cache;
350699b0f92Schristos }
351699b0f92Schristos 
352699b0f92Schristos static void
353*6881a400Schristos i386obsd_trapframe_this_id (frame_info_ptr this_frame,
354699b0f92Schristos 			    void **this_cache, struct frame_id *this_id)
355699b0f92Schristos {
356699b0f92Schristos   struct trad_frame_cache *cache =
357699b0f92Schristos     i386obsd_trapframe_cache (this_frame, this_cache);
358699b0f92Schristos 
359699b0f92Schristos   trad_frame_get_id (cache, this_id);
360699b0f92Schristos }
361699b0f92Schristos 
362699b0f92Schristos static struct value *
363*6881a400Schristos i386obsd_trapframe_prev_register (frame_info_ptr this_frame,
364699b0f92Schristos 				  void **this_cache, int regnum)
365699b0f92Schristos {
366699b0f92Schristos   struct trad_frame_cache *cache =
367699b0f92Schristos     i386obsd_trapframe_cache (this_frame, this_cache);
368699b0f92Schristos 
369699b0f92Schristos   return trad_frame_get_register (cache, this_frame, regnum);
370699b0f92Schristos }
371699b0f92Schristos 
372699b0f92Schristos static int
373699b0f92Schristos i386obsd_trapframe_sniffer (const struct frame_unwind *self,
374*6881a400Schristos 			    frame_info_ptr this_frame,
375699b0f92Schristos 			    void **this_prologue_cache)
376699b0f92Schristos {
377699b0f92Schristos   ULONGEST cs;
378699b0f92Schristos   const char *name;
379699b0f92Schristos 
380699b0f92Schristos   /* Check Current Privilege Level and bail out if we're not executing
381699b0f92Schristos      in kernel space.  */
382699b0f92Schristos   cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM);
383699b0f92Schristos   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
384699b0f92Schristos     return 0;
385699b0f92Schristos 
386699b0f92Schristos   find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL);
387699b0f92Schristos   return (name && (strcmp (name, "calltrap") == 0
388699b0f92Schristos 		   || strcmp (name, "syscall1") == 0
389699b0f92Schristos 		   || startswith (name, "Xintr")
390699b0f92Schristos 		   || startswith (name, "Xsoft")));
391699b0f92Schristos }
392699b0f92Schristos 
393699b0f92Schristos static const struct frame_unwind i386obsd_trapframe_unwind = {
394*6881a400Schristos   "i386 openbsd trap",
395699b0f92Schristos   /* FIXME: kettenis/20051219: This really is more like an interrupt
396699b0f92Schristos      frame, but SIGTRAMP_FRAME would print <signal handler called>,
397699b0f92Schristos      which really is not what we want here.  */
398699b0f92Schristos   NORMAL_FRAME,
399699b0f92Schristos   default_frame_unwind_stop_reason,
400699b0f92Schristos   i386obsd_trapframe_this_id,
401699b0f92Schristos   i386obsd_trapframe_prev_register,
402699b0f92Schristos   NULL,
403699b0f92Schristos   i386obsd_trapframe_sniffer
404699b0f92Schristos };
405699b0f92Schristos 
406699b0f92Schristos 
407699b0f92Schristos static void
408699b0f92Schristos i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
409699b0f92Schristos {
410*6881a400Schristos   i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
411699b0f92Schristos 
412699b0f92Schristos   /* Obviously OpenBSD is BSD-based.  */
413699b0f92Schristos   i386bsd_init_abi (info, gdbarch);
414699b0f92Schristos   obsd_init_abi (info, gdbarch);
415699b0f92Schristos   i386_elf_init_abi (info, gdbarch);
416699b0f92Schristos 
417699b0f92Schristos   /* OpenBSD has a different `struct reg'.  */
418699b0f92Schristos   tdep->gregset_reg_offset = i386obsd_r_reg_offset;
419699b0f92Schristos   tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset);
420699b0f92Schristos   tdep->sizeof_gregset = 16 * 4;
421699b0f92Schristos 
422699b0f92Schristos   /* OpenBSD uses -freg-struct-return by default.  */
423699b0f92Schristos   tdep->struct_return = reg_struct_return;
424699b0f92Schristos 
425699b0f92Schristos   /* OpenBSD uses a different memory layout.  */
426699b0f92Schristos   tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
427699b0f92Schristos   tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
428699b0f92Schristos   tdep->sigtramp_p = i386obsd_sigtramp_p;
429699b0f92Schristos 
430699b0f92Schristos   /* OpenBSD has a `struct sigcontext' that's different from the
431699b0f92Schristos      original 4.3 BSD.  */
432699b0f92Schristos   tdep->sc_reg_offset = i386obsd_sc_reg_offset;
433699b0f92Schristos   tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
434699b0f92Schristos 
435699b0f92Schristos   /* OpenBSD provides a user-level threads implementation.  */
436699b0f92Schristos   bsd_uthread_set_supply_uthread (gdbarch, i386obsd_supply_uthread);
437699b0f92Schristos   bsd_uthread_set_collect_uthread (gdbarch, i386obsd_collect_uthread);
438699b0f92Schristos 
439699b0f92Schristos   /* Unwind kernel trap frames correctly.  */
440699b0f92Schristos   frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind);
441699b0f92Schristos 
442699b0f92Schristos   /* OpenBSD ELF uses SVR4-style shared libraries.  */
443699b0f92Schristos   set_solib_svr4_fetch_link_map_offsets
444699b0f92Schristos     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
445699b0f92Schristos }
446699b0f92Schristos 
4477d62b00eSchristos void _initialize_i386obsd_tdep ();
448699b0f92Schristos void
4497d62b00eSchristos _initialize_i386obsd_tdep ()
450699b0f92Schristos {
451699b0f92Schristos   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD,
452699b0f92Schristos 			  i386obsd_init_abi);
453699b0f92Schristos }
454