1/* Target-dependent code for OpenBSD/i386. 2 3 Copyright 1988, 1989, 1991, 1992, 1994, 1996, 2000, 2001, 2002, 4 2003, 2004 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 "gdbcore.h" 27#include "regcache.h" 28#include "regset.h" 29#include "osabi.h" 30#include "target.h" 31 32#include "gdb_assert.h" 33#include "gdb_string.h" 34 35#include "i386-tdep.h" 36#include "i387-tdep.h" 37#include "solib-svr4.h" 38 39/* Support for signal handlers. */ 40 41/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page 42 in virtual memory. The randomness makes it somewhat tricky to 43 detect it, but fortunately we can rely on the fact that the start 44 of the sigtramp routine is page-aligned. By the way, the mapping 45 is read-only, so you cannot place a breakpoint in the signal 46 trampoline. */ 47 48/* Default page size. */ 49static const int i386obsd_page_size = 4096; 50 51/* Return whether PC is in an OpenBSD sigtramp routine. */ 52 53static int 54i386obsd_pc_in_sigtramp (CORE_ADDR pc, char *name) 55{ 56 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); 57 const char sigreturn[] = 58 { 59 0xb8, 60 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */ 61 0xcd, 0x80 /* int $0x80 */ 62 }; 63 char *buf; 64 65 /* Avoid reading memory from the target if possible. If we're in a 66 named function, we're certainly not in a sigtramp routine 67 provided by the kernel. Take synthetic function names into 68 account though. */ 69 if (name && name[0] != '<') 70 return 0; 71 72 /* If we can't read the instructions at START_PC, return zero. */ 73 buf = alloca (sizeof sigreturn); 74 if (target_read_memory (start_pc + 0x14, buf, sizeof sigreturn)) 75 return 0; 76 77 /* Check for sigreturn(2). */ 78 if (memcmp (buf, sigreturn, sizeof sigreturn) == 0) 79 return 1; 80 81 /* Check for a traditional BSD sigtramp routine. */ 82 return i386bsd_pc_in_sigtramp (pc, name); 83} 84 85/* Return the start address of the sigtramp routine. */ 86 87static CORE_ADDR 88i386obsd_sigtramp_start (CORE_ADDR pc) 89{ 90 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); 91 92 if (i386bsd_pc_in_sigtramp (pc, NULL)) 93 return i386bsd_sigtramp_start (pc); 94 95 return start_pc; 96} 97 98/* Return the end address of the sigtramp routine. */ 99 100static CORE_ADDR 101i386obsd_sigtramp_end (CORE_ADDR pc) 102{ 103 CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); 104 105 if (i386bsd_pc_in_sigtramp (pc, NULL)) 106 return i386bsd_sigtramp_end (pc); 107 108 return start_pc + 0x22; 109} 110 111/* Mapping between the general-purpose registers in `struct reg' 112 format and GDB's register cache layout. */ 113 114/* From <machine/reg.h>. */ 115static int i386obsd_r_reg_offset[] = 116{ 117 0 * 4, /* %eax */ 118 1 * 4, /* %ecx */ 119 2 * 4, /* %edx */ 120 3 * 4, /* %ebx */ 121 4 * 4, /* %esp */ 122 5 * 4, /* %ebp */ 123 6 * 4, /* %esi */ 124 7 * 4, /* %edi */ 125 8 * 4, /* %eip */ 126 9 * 4, /* %eflags */ 127 10 * 4, /* %cs */ 128 11 * 4, /* %ss */ 129 12 * 4, /* %ds */ 130 13 * 4, /* %es */ 131 14 * 4, /* %fs */ 132 15 * 4 /* %gs */ 133}; 134 135static void 136i386obsd_aout_supply_regset (const struct regset *regset, 137 struct regcache *regcache, int regnum, 138 const void *regs, size_t len) 139{ 140 const struct gdbarch_tdep *tdep = regset->descr; 141 142 gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE); 143 144 i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset); 145 i387_supply_fsave (regcache, regnum, (char *) regs + tdep->sizeof_gregset); 146} 147 148static const struct regset * 149i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch, 150 const char *sect_name, 151 size_t sect_size) 152{ 153 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 154 155 /* OpenBSD a.out core dumps don't use seperate register sets for the 156 general-purpose and floating-point registers. */ 157 158 if (strcmp (sect_name, ".reg") == 0 159 && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE) 160 { 161 if (tdep->gregset == NULL) 162 { 163 tdep->gregset = XMALLOC (struct regset); 164 tdep->gregset->descr = tdep; 165 tdep->gregset->supply_regset = i386obsd_aout_supply_regset; 166 } 167 return tdep->gregset; 168 } 169 170 return NULL; 171} 172 173 174/* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */ 175CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20; 176CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0; 177 178/* From <machine/signal.h>. */ 179int i386obsd_sc_reg_offset[I386_NUM_GREGS] = 180{ 181 10 * 4, /* %eax */ 182 9 * 4, /* %ecx */ 183 8 * 4, /* %edx */ 184 7 * 4, /* %ebx */ 185 14 * 4, /* %esp */ 186 6 * 4, /* %ebp */ 187 5 * 4, /* %esi */ 188 4 * 4, /* %edi */ 189 11 * 4, /* %eip */ 190 13 * 4, /* %eflags */ 191 12 * 4, /* %cs */ 192 15 * 4, /* %ss */ 193 3 * 4, /* %ds */ 194 2 * 4, /* %es */ 195 1 * 4, /* %fs */ 196 0 * 4 /* %gs */ 197}; 198 199static void 200i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 201{ 202 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 203 204 /* Obviously OpenBSD is BSD-based. */ 205 i386bsd_init_abi (info, gdbarch); 206 207 /* OpenBSD has a different `struct reg'. */ 208 tdep->gregset_reg_offset = i386obsd_r_reg_offset; 209 tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset); 210 tdep->sizeof_gregset = 16 * 4; 211 212 /* OpenBSD uses -freg-struct-return by default. */ 213 tdep->struct_return = reg_struct_return; 214 215 /* OpenBSD uses a different memory layout. */ 216 tdep->sigtramp_start = i386obsd_sigtramp_start_addr; 217 tdep->sigtramp_end = i386obsd_sigtramp_end_addr; 218 set_gdbarch_pc_in_sigtramp (gdbarch, i386obsd_pc_in_sigtramp); 219 set_gdbarch_sigtramp_start (gdbarch, i386obsd_sigtramp_start); 220 set_gdbarch_sigtramp_end (gdbarch, i386obsd_sigtramp_end); 221 222 /* OpenBSD has a `struct sigcontext' that's different from the 223 origional 4.3 BSD. */ 224 tdep->sc_reg_offset = i386obsd_sc_reg_offset; 225 tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset); 226} 227 228/* OpenBSD a.out. */ 229 230static void 231i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 232{ 233 i386obsd_init_abi (info, gdbarch); 234 235 /* OpenBSD a.out has a single register set. */ 236 set_gdbarch_regset_from_core_section 237 (gdbarch, i386obsd_aout_regset_from_core_section); 238} 239 240/* OpenBSD ELF. */ 241 242static void 243i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 244{ 245 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 246 247 /* It's still OpenBSD. */ 248 i386obsd_init_abi (info, gdbarch); 249 250 /* But ELF-based. */ 251 i386_elf_init_abi (info, gdbarch); 252 253 /* OpenBSD ELF uses SVR4-style shared libraries. */ 254 set_gdbarch_in_solib_call_trampoline 255 (gdbarch, generic_in_solib_call_trampoline); 256 set_solib_svr4_fetch_link_map_offsets 257 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 258} 259 260 261/* Provide a prototype to silence -Wmissing-prototypes. */ 262void _initialize_i386obsd_tdep (void); 263 264void 265_initialize_i386obsd_tdep (void) 266{ 267 /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are 268 indistingushable from NetBSD/i386 a.out binaries, building a GDB 269 that should support both these targets will probably not work as 270 expected. */ 271#define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT 272 273 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT, 274 i386obsd_aout_init_abi); 275 gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF, 276 i386obsd_elf_init_abi); 277} 278