1130803Smarcel/* Target-dependent code for OpenBSD/i386. 2130803Smarcel 3130803Smarcel Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002, 4130803Smarcel 2003, 2004 5130803Smarcel Free Software Foundation, Inc. 6130803Smarcel 7130803Smarcel This file is part of GDB. 8130803Smarcel 9130803Smarcel This program is free software; you can redistribute it and/or modify 10130803Smarcel it under the terms of the GNU General Public License as published by 11130803Smarcel the Free Software Foundation; either version 2 of the License, or 12130803Smarcel (at your option) any later version. 13130803Smarcel 14130803Smarcel This program is distributed in the hope that it will be useful, 15130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 16130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17130803Smarcel GNU General Public License for more details. 18130803Smarcel 19130803Smarcel You should have received a copy of the GNU General Public License 20130803Smarcel along with this program; if not, write to the Free Software 21130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 22130803Smarcel Boston, MA 02111-1307, USA. */ 23130803Smarcel 24130803Smarcel#include "defs.h" 25130803Smarcel#include "arch-utils.h" 26130803Smarcel#include "gdbcore.h" 27130803Smarcel#include "regcache.h" 28130803Smarcel#include "regset.h" 29130803Smarcel#include "osabi.h" 30130803Smarcel#include "target.h" 31130803Smarcel 32130803Smarcel#include "gdb_assert.h" 33130803Smarcel#include "gdb_string.h" 34130803Smarcel 35130803Smarcel#include "i386-tdep.h" 36130803Smarcel#include "i387-tdep.h" 37130803Smarcel#include "solib-svr4.h" 38130803Smarcel 39130803Smarcel/* Support for signal handlers. */ 40130803Smarcel 41130803Smarcel/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page 42130803Smarcel in virtual memory. The randomness makes it somewhat tricky to 43130803Smarcel detect it, but fortunately we can rely on the fact that the start 44130803Smarcel of the sigtramp routine is page-aligned. By the way, the mapping 45130803Smarcel is read-only, so you cannot place a breakpoint in the signal 46130803Smarcel trampoline. */ 47130803Smarcel 48130803Smarcel/* Default page size. */ 49130803Smarcelstatic const int i386obsd_page_size = 4096; 50130803Smarcel 51130803Smarcel/* Return whether PC is in an OpenBSD sigtramp routine. */ 52130803Smarcel 53130803Smarcelstatic int 54130803Smarceli386obsd_pc_in_sigtramp (CORE_ADDR pc, char *name) 55130803Smarcel{ 56130803Smarcel CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); 57130803Smarcel const char sigreturn[] = 58130803Smarcel { 59130803Smarcel 0xb8, 60130803Smarcel 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */ 61130803Smarcel 0xcd, 0x80 /* int $0x80 */ 62130803Smarcel }; 63130803Smarcel char *buf; 64130803Smarcel 65130803Smarcel /* Avoid reading memory from the target if possible. If we're in a 66130803Smarcel named function, we're certainly not in a sigtramp routine 67130803Smarcel provided by the kernel. Take synthetic function names into 68130803Smarcel account though. */ 69130803Smarcel if (name && name[0] != '<') 70130803Smarcel return 0; 71130803Smarcel 72130803Smarcel /* If we can't read the instructions at START_PC, return zero. */ 73130803Smarcel buf = alloca (sizeof sigreturn); 74130803Smarcel if (target_read_memory (start_pc + 0x14, buf, sizeof sigreturn)) 75130803Smarcel return 0; 76130803Smarcel 77130803Smarcel /* Check for sigreturn(2). */ 78130803Smarcel if (memcmp (buf, sigreturn, sizeof sigreturn) == 0) 79130803Smarcel return 1; 80130803Smarcel 81130803Smarcel /* Check for a traditional BSD sigtramp routine. */ 82130803Smarcel return i386bsd_pc_in_sigtramp (pc, name); 83130803Smarcel} 84130803Smarcel 85130803Smarcel/* Return the start address of the sigtramp routine. */ 86130803Smarcel 87130803Smarcelstatic CORE_ADDR 88130803Smarceli386obsd_sigtramp_start (CORE_ADDR pc) 89130803Smarcel{ 90130803Smarcel CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); 91130803Smarcel 92130803Smarcel if (i386bsd_pc_in_sigtramp (pc, NULL)) 93130803Smarcel return i386bsd_sigtramp_start (pc); 94130803Smarcel 95130803Smarcel return start_pc; 96130803Smarcel} 97130803Smarcel 98130803Smarcel/* Return the end address of the sigtramp routine. */ 99130803Smarcel 100130803Smarcelstatic CORE_ADDR 101130803Smarceli386obsd_sigtramp_end (CORE_ADDR pc) 102130803Smarcel{ 103130803Smarcel CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); 104130803Smarcel 105130803Smarcel if (i386bsd_pc_in_sigtramp (pc, NULL)) 106130803Smarcel return i386bsd_sigtramp_end (pc); 107130803Smarcel 108130803Smarcel return start_pc + 0x22; 109130803Smarcel} 110130803Smarcel 111130803Smarcel/* Mapping between the general-purpose registers in `struct reg' 112130803Smarcel format and GDB's register cache layout. */ 113130803Smarcel 114130803Smarcel/* From <machine/reg.h>. */ 115130803Smarcelstatic int i386obsd_r_reg_offset[] = 116130803Smarcel{ 117130803Smarcel 0 * 4, /* %eax */ 118130803Smarcel 1 * 4, /* %ecx */ 119130803Smarcel 2 * 4, /* %edx */ 120130803Smarcel 3 * 4, /* %ebx */ 121130803Smarcel 4 * 4, /* %esp */ 122130803Smarcel 5 * 4, /* %ebp */ 123130803Smarcel 6 * 4, /* %esi */ 124130803Smarcel 7 * 4, /* %edi */ 125130803Smarcel 8 * 4, /* %eip */ 126130803Smarcel 9 * 4, /* %eflags */ 127130803Smarcel 10 * 4, /* %cs */ 128130803Smarcel 11 * 4, /* %ss */ 129130803Smarcel 12 * 4, /* %ds */ 130130803Smarcel 13 * 4, /* %es */ 131130803Smarcel 14 * 4, /* %fs */ 132130803Smarcel 15 * 4 /* %gs */ 133130803Smarcel}; 134130803Smarcel 135130803Smarcelstatic void 136130803Smarceli386obsd_aout_supply_regset (const struct regset *regset, 137130803Smarcel struct regcache *regcache, int regnum, 138130803Smarcel const void *regs, size_t len) 139130803Smarcel{ 140130803Smarcel const struct gdbarch_tdep *tdep = regset->descr; 141130803Smarcel 142130803Smarcel gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE); 143130803Smarcel 144130803Smarcel i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset); 145130803Smarcel i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset); 146130803Smarcel} 147130803Smarcel 148130803Smarcelstatic const struct regset * 149130803Smarceli386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch, 150130803Smarcel const char *sect_name, 151130803Smarcel size_t sect_size) 152130803Smarcel{ 153130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 154130803Smarcel 155130803Smarcel /* OpenBSD a.out core dumps don't use seperate register sets for the 156130803Smarcel general-purpose and floating-point registers. */ 157130803Smarcel 158130803Smarcel if (strcmp (sect_name, ".reg") == 0 159130803Smarcel && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE) 160130803Smarcel { 161130803Smarcel if (tdep->gregset == NULL) 162130803Smarcel { 163130803Smarcel tdep->gregset = XMALLOC (struct regset); 164130803Smarcel tdep->gregset->descr = tdep; 165130803Smarcel tdep->gregset->supply_regset = i386obsd_aout_supply_regset; 166130803Smarcel } 167130803Smarcel return tdep->gregset; 168130803Smarcel } 169130803Smarcel 170130803Smarcel return NULL; 171130803Smarcel} 172130803Smarcel 173130803Smarcel 174130803Smarcel/* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */ 175130803SmarcelCORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20; 176130803SmarcelCORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0; 177130803Smarcel 178130803Smarcel/* From <machine/signal.h>. */ 179130803Smarcelint i386obsd_sc_reg_offset[I386_NUM_GREGS] = 180130803Smarcel{ 181130803Smarcel 10 * 4, /* %eax */ 182130803Smarcel 9 * 4, /* %ecx */ 183130803Smarcel 8 * 4, /* %edx */ 184130803Smarcel 7 * 4, /* %ebx */ 185130803Smarcel 14 * 4, /* %esp */ 186130803Smarcel 6 * 4, /* %ebp */ 187130803Smarcel 5 * 4, /* %esi */ 188130803Smarcel 4 * 4, /* %edi */ 189130803Smarcel 11 * 4, /* %eip */ 190130803Smarcel 13 * 4, /* %eflags */ 191130803Smarcel 12 * 4, /* %cs */ 192130803Smarcel 15 * 4, /* %ss */ 193130803Smarcel 3 * 4, /* %ds */ 194130803Smarcel 2 * 4, /* %es */ 195130803Smarcel 1 * 4, /* %fs */ 196130803Smarcel 0 * 4 /* %gs */ 197130803Smarcel}; 198130803Smarcel 199130803Smarcelstatic void 200130803Smarceli386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 201130803Smarcel{ 202130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 203130803Smarcel 204130803Smarcel /* Obviously OpenBSD is BSD-based. */ 205130803Smarcel i386bsd_init_abi (info, gdbarch); 206130803Smarcel 207130803Smarcel /* OpenBSD has a different `struct reg'. */ 208130803Smarcel tdep->gregset_reg_offset = i386obsd_r_reg_offset; 209130803Smarcel tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset); 210130803Smarcel tdep->sizeof_gregset = 16 * 4; 211130803Smarcel 212130803Smarcel /* OpenBSD uses -freg-struct-return by default. */ 213130803Smarcel tdep->struct_return = reg_struct_return; 214130803Smarcel 215130803Smarcel /* OpenBSD uses a different memory layout. */ 216130803Smarcel tdep->sigtramp_start = i386obsd_sigtramp_start_addr; 217130803Smarcel tdep->sigtramp_end = i386obsd_sigtramp_end_addr; 218130803Smarcel set_gdbarch_pc_in_sigtramp (gdbarch, i386obsd_pc_in_sigtramp); 219130803Smarcel set_gdbarch_sigtramp_start (gdbarch, i386obsd_sigtramp_start); 220130803Smarcel set_gdbarch_sigtramp_end (gdbarch, i386obsd_sigtramp_end); 221130803Smarcel 222130803Smarcel /* OpenBSD has a `struct sigcontext' that's different from the 223130803Smarcel origional 4.3 BSD. */ 224130803Smarcel tdep->sc_reg_offset = i386obsd_sc_reg_offset; 225130803Smarcel tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset); 226130803Smarcel} 227130803Smarcel 228130803Smarcel/* OpenBSD a.out. */ 229130803Smarcel 230130803Smarcelstatic void 231130803Smarceli386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 232130803Smarcel{ 233130803Smarcel i386obsd_init_abi (info, gdbarch); 234130803Smarcel 235130803Smarcel /* OpenBSD a.out has a single register set. */ 236130803Smarcel set_gdbarch_regset_from_core_section 237130803Smarcel (gdbarch, i386obsd_aout_regset_from_core_section); 238130803Smarcel} 239130803Smarcel 240130803Smarcel/* OpenBSD ELF. */ 241130803Smarcel 242130803Smarcelstatic void 243130803Smarceli386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 244130803Smarcel{ 245130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 246130803Smarcel 247130803Smarcel /* It's still OpenBSD. */ 248130803Smarcel i386obsd_init_abi (info, gdbarch); 249130803Smarcel 250130803Smarcel /* But ELF-based. */ 251130803Smarcel i386_elf_init_abi (info, gdbarch); 252130803Smarcel 253130803Smarcel /* OpenBSD ELF uses SVR4-style shared libraries. */ 254130803Smarcel set_gdbarch_in_solib_call_trampoline 255130803Smarcel (gdbarch, generic_in_solib_call_trampoline); 256130803Smarcel set_solib_svr4_fetch_link_map_offsets 257130803Smarcel (gdbarch, svr4_ilp32_fetch_link_map_offsets); 258130803Smarcel} 259130803Smarcel 260130803Smarcel 261130803Smarcel/* Provide a prototype to silence -Wmissing-prototypes. */ 262130803Smarcelvoid _initialize_i386obsd_tdep (void); 263130803Smarcel 264130803Smarcelvoid 265130803Smarcel_initialize_i386obsd_tdep (void) 266130803Smarcel{ 267130803Smarcel /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are 268130803Smarcel indistingushable from NetBSD/i386 a.out binaries, building a GDB 269130803Smarcel that should support both these targets will probably not work as 270130803Smarcel expected. */ 271130803Smarcel#define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT 272130803Smarcel 273130803Smarcel gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT, 274130803Smarcel i386obsd_aout_init_abi); 275130803Smarcel gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF, 276130803Smarcel i386obsd_elf_init_abi); 277130803Smarcel} 278