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