1 /* Target-dependent code for OpenBSD/sparc64. 2 3 Copyright 2004, 2005, 2006 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22 #include "defs.h" 23 #include "frame.h" 24 #include "frame-unwind.h" 25 #include "osabi.h" 26 #include "regset.h" 27 #include "symtab.h" 28 #include "objfiles.h" 29 #include "solib-svr4.h" 30 #include "trad-frame.h" 31 32 #include "gdb_assert.h" 33 34 #include "obsd-tdep.h" 35 #include "sparc64-tdep.h" 36 37 /* OpenBSD uses the traditional NetBSD core file format, even for 38 ports that use ELF. The core files don't use multiple register 39 sets. Instead, the general-purpose and floating-point registers 40 are lumped together in a single section. Unlike on NetBSD, OpenBSD 41 uses a different layout for its general-purpose registers than the 42 layout used for ptrace(2). */ 43 44 /* From <machine/reg.h>. */ 45 const struct sparc_gregset sparc64obsd_gregset = 46 { 47 0 * 8, /* "tstate" */ 48 1 * 8, /* %pc */ 49 2 * 8, /* %npc */ 50 3 * 8, /* %y */ 51 -1, /* %fprs */ 52 -1, 53 5 * 8, /* %g1 */ 54 20 * 8, /* %l0 */ 55 4 /* sizeof (%y) */ 56 }; 57 58 const struct sparc_gregset sparc64obsd_core_gregset = 59 { 60 0 * 8, /* "tstate" */ 61 1 * 8, /* %pc */ 62 2 * 8, /* %npc */ 63 3 * 8, /* %y */ 64 -1, /* %fprs */ 65 -1, 66 7 * 8, /* %g1 */ 67 22 * 8, /* %l0 */ 68 4 /* sizeof (%y) */ 69 }; 70 71 static void 72 sparc64obsd_supply_gregset (const struct regset *regset, 73 struct regcache *regcache, 74 int regnum, const void *gregs, size_t len) 75 { 76 const char *regs = gregs; 77 78 if (len < 832) 79 { 80 sparc64_supply_gregset (&sparc64obsd_gregset, regcache, regnum, regs); 81 return; 82 } 83 84 sparc64_supply_gregset (&sparc64obsd_core_gregset, regcache, regnum, regs); 85 sparc64_supply_fpregset (regcache, regnum, regs + 288); 86 } 87 88 static void 89 sparc64obsd_supply_fpregset (const struct regset *regset, 90 struct regcache *regcache, 91 int regnum, const void *fpregs, size_t len) 92 { 93 sparc64_supply_fpregset (regcache, regnum, fpregs); 94 } 95 96 97 /* Signal trampolines. */ 98 99 /* The OpenBSD kernel maps the signal trampoline at some random 100 location in user space, which means that the traditional BSD way of 101 detecting it won't work. 102 103 The signal trampoline will be mapped at an address that is page 104 aligned. We recognize the signal trampoline by the looking for the 105 sigreturn system call. The offset where we can find the code that 106 makes this system call varies from release to release. For OpenBSD 107 3.6 and later releases we can find the code at offset 0xec. For 108 OpenBSD 3.5 and earlier releases, we find it at offset 0xe8. */ 109 110 static const int sparc64obsd_page_size = 8192; 111 static const int sparc64obsd_sigreturn_offset[] = { 0xf0, 0xec, 0xe8, -1 }; 112 113 static int 114 sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name) 115 { 116 CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1)); 117 unsigned long insn; 118 const int *offset; 119 120 if (name) 121 return 0; 122 123 for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++) 124 { 125 /* Check for "restore %g0, SYS_sigreturn, %g1". */ 126 insn = sparc_fetch_instruction (start_pc + *offset); 127 if (insn != 0x83e82067) 128 continue; 129 130 /* Check for "t ST_SYSCALL". */ 131 insn = sparc_fetch_instruction (start_pc + *offset + 8); 132 if (insn != 0x91d02000) 133 continue; 134 135 return 1; 136 } 137 138 return 0; 139 } 140 141 static struct sparc_frame_cache * 142 sparc64obsd_frame_cache (struct frame_info *next_frame, void **this_cache) 143 { 144 struct sparc_frame_cache *cache; 145 CORE_ADDR addr; 146 147 if (*this_cache) 148 return *this_cache; 149 150 cache = sparc_frame_cache (next_frame, this_cache); 151 gdb_assert (cache == *this_cache); 152 153 /* If we couldn't find the frame's function, we're probably dealing 154 with an on-stack signal trampoline. */ 155 if (cache->pc == 0) 156 { 157 cache->pc = frame_pc_unwind (next_frame); 158 cache->pc &= ~(sparc64obsd_page_size - 1); 159 160 /* Since we couldn't find the frame's function, the cache was 161 initialized under the assumption that we're frameless. */ 162 cache->frameless_p = 0; 163 addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM); 164 cache->base = addr; 165 } 166 167 /* We find the appropriate instance of `struct sigcontext' at a 168 fixed offset in the signal frame. */ 169 addr = cache->base + BIAS + 128 + 16; 170 cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame); 171 172 return cache; 173 } 174 175 static void 176 sparc64obsd_frame_this_id (struct frame_info *next_frame, void **this_cache, 177 struct frame_id *this_id) 178 { 179 struct sparc_frame_cache *cache = 180 sparc64obsd_frame_cache (next_frame, this_cache); 181 182 (*this_id) = frame_id_build (cache->base, cache->pc); 183 } 184 185 static void 186 sparc64obsd_frame_prev_register (struct frame_info *next_frame, 187 void **this_cache, 188 int regnum, int *optimizedp, 189 enum lval_type *lvalp, CORE_ADDR *addrp, 190 int *realnump, void *valuep) 191 { 192 struct sparc_frame_cache *cache = 193 sparc64obsd_frame_cache (next_frame, this_cache); 194 195 trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, 196 optimizedp, lvalp, addrp, realnump, valuep); 197 } 198 199 static const struct frame_unwind sparc64obsd_frame_unwind = 200 { 201 SIGTRAMP_FRAME, 202 sparc64obsd_frame_this_id, 203 sparc64obsd_frame_prev_register 204 }; 205 206 static const struct frame_unwind * 207 sparc64obsd_sigtramp_frame_sniffer (struct frame_info *next_frame) 208 { 209 CORE_ADDR pc = frame_pc_unwind (next_frame); 210 char *name; 211 212 find_pc_partial_function (pc, &name, NULL, NULL); 213 if (sparc64obsd_pc_in_sigtramp (pc, name)) 214 return &sparc64obsd_frame_unwind; 215 216 return NULL; 217 } 218 219 /* Kernel debugging support. */ 220 221 static struct sparc_frame_cache * 222 sparc64obsd_trapframe_cache(struct frame_info *next_frame, void **this_cache) 223 { 224 struct sparc_frame_cache *cache; 225 CORE_ADDR sp, trapframe_addr; 226 int regnum; 227 228 if (*this_cache) 229 return *this_cache; 230 231 cache = sparc_frame_cache (next_frame, this_cache); 232 gdb_assert (cache == *this_cache); 233 234 sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM); 235 trapframe_addr = sp + BIAS + 176; 236 237 cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); 238 239 cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr; 240 cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8; 241 cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16; 242 243 for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++) 244 cache->saved_regs[regnum].addr = 245 trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8; 246 247 return cache; 248 } 249 250 static void 251 sparc64obsd_trapframe_this_id (struct frame_info *next_frame, 252 void **this_cache, struct frame_id *this_id) 253 { 254 struct sparc_frame_cache *cache = 255 sparc64obsd_trapframe_cache (next_frame, this_cache); 256 257 (*this_id) = frame_id_build (cache->base, cache->pc); 258 } 259 260 static void 261 sparc64obsd_trapframe_prev_register (struct frame_info *next_frame, 262 void **this_cache, 263 int regnum, int *optimizedp, 264 enum lval_type *lvalp, CORE_ADDR *addrp, 265 int *realnump, void *valuep) 266 { 267 struct sparc_frame_cache *cache = 268 sparc64obsd_trapframe_cache (next_frame, this_cache); 269 270 trad_frame_get_prev_register (next_frame, cache->saved_regs, regnum, 271 optimizedp, lvalp, addrp, realnump, valuep); 272 } 273 274 static const struct frame_unwind sparc64obsd_trapframe_unwind = 275 { 276 NORMAL_FRAME, 277 sparc64obsd_trapframe_this_id, 278 sparc64obsd_trapframe_prev_register 279 }; 280 281 static const struct frame_unwind * 282 sparc64obsd_trapframe_sniffer (struct frame_info *next_frame) 283 { 284 ULONGEST pstate; 285 char *name; 286 287 /* Check whether we are in privileged mode, and bail out if we're not. */ 288 pstate = frame_unwind_register_unsigned (next_frame, SPARC64_PSTATE_REGNUM); 289 if ((pstate & SPARC64_PSTATE_PRIV) == 0) 290 return NULL; 291 292 find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL); 293 if (name && ((strcmp (name, "Lslowtrap_reenter") == 0) 294 || (strcmp (name, "Ldatafault_internal") == 0))) 295 return &sparc64obsd_trapframe_unwind; 296 297 return NULL; 298 } 299 300 301 static void 302 sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 303 { 304 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 305 306 tdep->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL); 307 tdep->sizeof_gregset = 288; 308 309 tdep->fpregset = regset_alloc (gdbarch, sparc64obsd_supply_fpregset, NULL); 310 tdep->sizeof_fpregset = 272; 311 312 frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer); 313 frame_unwind_append_sniffer (gdbarch, sparc64obsd_trapframe_sniffer); 314 315 sparc64_init_abi (info, gdbarch); 316 317 /* OpenBSD/sparc64 has SVR4-style shared libraries... */ 318 set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section); 319 set_solib_svr4_fetch_link_map_offsets 320 (gdbarch, svr4_lp64_fetch_link_map_offsets); 321 set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); 322 } 323 324 325 /* Provide a prototype to silence -Wmissing-prototypes. */ 326 void _initialize_sparc64obsd_tdep (void); 327 328 void 329 _initialize_sparc64obsd_tdep (void) 330 { 331 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, 332 GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi); 333 } 334