GDB (API)
|
00001 /* Target-dependent code for OpenBSD/sparc64. 00002 00003 Copyright (C) 2004-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "frame.h" 00022 #include "frame-unwind.h" 00023 #include "gdbcore.h" 00024 #include "osabi.h" 00025 #include "regcache.h" 00026 #include "regset.h" 00027 #include "symtab.h" 00028 #include "objfiles.h" 00029 #include "trad-frame.h" 00030 00031 #include "gdb_assert.h" 00032 00033 #include "obsd-tdep.h" 00034 #include "sparc64-tdep.h" 00035 #include "solib-svr4.h" 00036 #include "bsd-uthread.h" 00037 00038 /* OpenBSD uses the traditional NetBSD core file format, even for 00039 ports that use ELF. The core files don't use multiple register 00040 sets. Instead, the general-purpose and floating-point registers 00041 are lumped together in a single section. Unlike on NetBSD, OpenBSD 00042 uses a different layout for its general-purpose registers than the 00043 layout used for ptrace(2). */ 00044 00045 /* From <machine/reg.h>. */ 00046 const struct sparc_gregset sparc64obsd_core_gregset = 00047 { 00048 0 * 8, /* "tstate" */ 00049 1 * 8, /* %pc */ 00050 2 * 8, /* %npc */ 00051 3 * 8, /* %y */ 00052 -1, /* %fprs */ 00053 -1, 00054 7 * 8, /* %g1 */ 00055 22 * 8, /* %l0 */ 00056 4 /* sizeof (%y) */ 00057 }; 00058 00059 static void 00060 sparc64obsd_supply_gregset (const struct regset *regset, 00061 struct regcache *regcache, 00062 int regnum, const void *gregs, size_t len) 00063 { 00064 const char *regs = gregs; 00065 00066 sparc64_supply_gregset (&sparc64obsd_core_gregset, regcache, regnum, regs); 00067 sparc64_supply_fpregset (&sparc64_bsd_fpregset, regcache, regnum, regs + 288); 00068 } 00069 00070 00071 /* Signal trampolines. */ 00072 00073 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page 00074 in virtual memory. The randomness makes it somewhat tricky to 00075 detect it, but fortunately we can rely on the fact that the start 00076 of the sigtramp routine is page-aligned. We recognize the 00077 trampoline by looking for the code that invokes the sigreturn 00078 system call. The offset where we can find that code varies from 00079 release to release. 00080 00081 By the way, the mapping mentioned above is read-only, so you cannot 00082 place a breakpoint in the signal trampoline. */ 00083 00084 /* Default page size. */ 00085 static const int sparc64obsd_page_size = 8192; 00086 00087 /* Offset for sigreturn(2). */ 00088 static const int sparc64obsd_sigreturn_offset[] = { 00089 0xf0, /* OpenBSD 3.8 */ 00090 0xec, /* OpenBSD 3.6 */ 00091 0xe8, /* OpenBSD 3.2 */ 00092 -1 00093 }; 00094 00095 static int 00096 sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) 00097 { 00098 CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1)); 00099 unsigned long insn; 00100 const int *offset; 00101 00102 if (name) 00103 return 0; 00104 00105 for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++) 00106 { 00107 /* Check for "restore %g0, SYS_sigreturn, %g1". */ 00108 insn = sparc_fetch_instruction (start_pc + *offset); 00109 if (insn != 0x83e82067) 00110 continue; 00111 00112 /* Check for "t ST_SYSCALL". */ 00113 insn = sparc_fetch_instruction (start_pc + *offset + 8); 00114 if (insn != 0x91d02000) 00115 continue; 00116 00117 return 1; 00118 } 00119 00120 return 0; 00121 } 00122 00123 static struct sparc_frame_cache * 00124 sparc64obsd_frame_cache (struct frame_info *this_frame, void **this_cache) 00125 { 00126 struct sparc_frame_cache *cache; 00127 CORE_ADDR addr; 00128 00129 if (*this_cache) 00130 return *this_cache; 00131 00132 cache = sparc_frame_cache (this_frame, this_cache); 00133 gdb_assert (cache == *this_cache); 00134 00135 /* If we couldn't find the frame's function, we're probably dealing 00136 with an on-stack signal trampoline. */ 00137 if (cache->pc == 0) 00138 { 00139 cache->pc = get_frame_pc (this_frame); 00140 cache->pc &= ~(sparc64obsd_page_size - 1); 00141 00142 /* Since we couldn't find the frame's function, the cache was 00143 initialized under the assumption that we're frameless. */ 00144 sparc_record_save_insn (cache); 00145 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); 00146 if (addr & 1) 00147 addr += BIAS; 00148 cache->base = addr; 00149 } 00150 00151 /* We find the appropriate instance of `struct sigcontext' at a 00152 fixed offset in the signal frame. */ 00153 addr = cache->base + 128 + 16; 00154 cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame); 00155 00156 return cache; 00157 } 00158 00159 static void 00160 sparc64obsd_frame_this_id (struct frame_info *this_frame, void **this_cache, 00161 struct frame_id *this_id) 00162 { 00163 struct sparc_frame_cache *cache = 00164 sparc64obsd_frame_cache (this_frame, this_cache); 00165 00166 (*this_id) = frame_id_build (cache->base, cache->pc); 00167 } 00168 00169 static struct value * 00170 sparc64obsd_frame_prev_register (struct frame_info *this_frame, 00171 void **this_cache, int regnum) 00172 { 00173 struct sparc_frame_cache *cache = 00174 sparc64obsd_frame_cache (this_frame, this_cache); 00175 00176 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); 00177 } 00178 00179 static int 00180 sparc64obsd_sigtramp_frame_sniffer (const struct frame_unwind *self, 00181 struct frame_info *this_frame, 00182 void **this_cache) 00183 { 00184 CORE_ADDR pc = get_frame_pc (this_frame); 00185 const char *name; 00186 00187 find_pc_partial_function (pc, &name, NULL, NULL); 00188 if (sparc64obsd_pc_in_sigtramp (pc, name)) 00189 return 1; 00190 00191 return 0; 00192 } 00193 00194 static const struct frame_unwind sparc64obsd_frame_unwind = 00195 { 00196 SIGTRAMP_FRAME, 00197 default_frame_unwind_stop_reason, 00198 sparc64obsd_frame_this_id, 00199 sparc64obsd_frame_prev_register, 00200 NULL, 00201 sparc64obsd_sigtramp_frame_sniffer 00202 }; 00203 00204 /* Kernel debugging support. */ 00205 00206 static struct sparc_frame_cache * 00207 sparc64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) 00208 { 00209 struct sparc_frame_cache *cache; 00210 CORE_ADDR sp, trapframe_addr; 00211 int regnum; 00212 00213 if (*this_cache) 00214 return *this_cache; 00215 00216 cache = sparc_frame_cache (this_frame, this_cache); 00217 gdb_assert (cache == *this_cache); 00218 00219 sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM); 00220 trapframe_addr = sp + BIAS + 176; 00221 00222 cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); 00223 00224 cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr; 00225 cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8; 00226 cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16; 00227 00228 for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++) 00229 cache->saved_regs[regnum].addr = 00230 trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8; 00231 00232 return cache; 00233 } 00234 00235 static void 00236 sparc64obsd_trapframe_this_id (struct frame_info *this_frame, 00237 void **this_cache, struct frame_id *this_id) 00238 { 00239 struct sparc_frame_cache *cache = 00240 sparc64obsd_trapframe_cache (this_frame, this_cache); 00241 00242 (*this_id) = frame_id_build (cache->base, cache->pc); 00243 } 00244 00245 static struct value * 00246 sparc64obsd_trapframe_prev_register (struct frame_info *this_frame, 00247 void **this_cache, int regnum) 00248 { 00249 struct sparc_frame_cache *cache = 00250 sparc64obsd_trapframe_cache (this_frame, this_cache); 00251 00252 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); 00253 } 00254 00255 static int 00256 sparc64obsd_trapframe_sniffer (const struct frame_unwind *self, 00257 struct frame_info *this_frame, 00258 void **this_cache) 00259 { 00260 CORE_ADDR pc; 00261 ULONGEST pstate; 00262 const char *name; 00263 00264 /* Check whether we are in privileged mode, and bail out if we're not. */ 00265 pstate = get_frame_register_unsigned (this_frame, SPARC64_PSTATE_REGNUM); 00266 if ((pstate & SPARC64_PSTATE_PRIV) == 0) 00267 return 0; 00268 00269 pc = get_frame_address_in_block (this_frame); 00270 find_pc_partial_function (pc, &name, NULL, NULL); 00271 if (name && strcmp (name, "Lslowtrap_reenter") == 0) 00272 return 1; 00273 00274 return 0; 00275 } 00276 00277 static const struct frame_unwind sparc64obsd_trapframe_unwind = 00278 { 00279 NORMAL_FRAME, 00280 default_frame_unwind_stop_reason, 00281 sparc64obsd_trapframe_this_id, 00282 sparc64obsd_trapframe_prev_register, 00283 NULL, 00284 sparc64obsd_trapframe_sniffer 00285 }; 00286 00287 00288 /* Threads support. */ 00289 00290 /* Offset wthin the thread structure where we can find %fp and %i7. */ 00291 #define SPARC64OBSD_UTHREAD_FP_OFFSET 232 00292 #define SPARC64OBSD_UTHREAD_PC_OFFSET 240 00293 00294 static void 00295 sparc64obsd_supply_uthread (struct regcache *regcache, 00296 int regnum, CORE_ADDR addr) 00297 { 00298 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00299 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00300 CORE_ADDR fp, fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET; 00301 gdb_byte buf[8]; 00302 00303 gdb_assert (regnum >= -1); 00304 00305 fp = read_memory_unsigned_integer (fp_addr, 8, byte_order); 00306 if (regnum == SPARC_SP_REGNUM || regnum == -1) 00307 { 00308 store_unsigned_integer (buf, 8, byte_order, fp); 00309 regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf); 00310 00311 if (regnum == SPARC_SP_REGNUM) 00312 return; 00313 } 00314 00315 if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM 00316 || regnum == -1) 00317 { 00318 CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET; 00319 00320 i7 = read_memory_unsigned_integer (i7_addr, 8, byte_order); 00321 if (regnum == SPARC64_PC_REGNUM || regnum == -1) 00322 { 00323 store_unsigned_integer (buf, 8, byte_order, i7 + 8); 00324 regcache_raw_supply (regcache, SPARC64_PC_REGNUM, buf); 00325 } 00326 if (regnum == SPARC64_NPC_REGNUM || regnum == -1) 00327 { 00328 store_unsigned_integer (buf, 8, byte_order, i7 + 12); 00329 regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, buf); 00330 } 00331 00332 if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM) 00333 return; 00334 } 00335 00336 sparc_supply_rwindow (regcache, fp, regnum); 00337 } 00338 00339 static void 00340 sparc64obsd_collect_uthread(const struct regcache *regcache, 00341 int regnum, CORE_ADDR addr) 00342 { 00343 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00344 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00345 CORE_ADDR sp; 00346 gdb_byte buf[8]; 00347 00348 gdb_assert (regnum >= -1); 00349 00350 if (regnum == SPARC_SP_REGNUM || regnum == -1) 00351 { 00352 CORE_ADDR fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET; 00353 00354 regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); 00355 write_memory (fp_addr,buf, 8); 00356 } 00357 00358 if (regnum == SPARC64_PC_REGNUM || regnum == -1) 00359 { 00360 CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET; 00361 00362 regcache_raw_collect (regcache, SPARC64_PC_REGNUM, buf); 00363 i7 = extract_unsigned_integer (buf, 8, byte_order) - 8; 00364 write_memory_unsigned_integer (i7_addr, 8, byte_order, i7); 00365 00366 if (regnum == SPARC64_PC_REGNUM) 00367 return; 00368 } 00369 00370 regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); 00371 sp = extract_unsigned_integer (buf, 8, byte_order); 00372 sparc_collect_rwindow (regcache, sp, regnum); 00373 } 00374 00375 00376 static void 00377 sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00378 { 00379 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00380 00381 tdep->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL); 00382 tdep->sizeof_gregset = 832; 00383 00384 /* Make sure we can single-step "new" syscalls. */ 00385 tdep->step_trap = sparcnbsd_step_trap; 00386 00387 frame_unwind_append_unwinder (gdbarch, &sparc64obsd_frame_unwind); 00388 frame_unwind_append_unwinder (gdbarch, &sparc64obsd_trapframe_unwind); 00389 00390 sparc64_init_abi (info, gdbarch); 00391 00392 /* OpenBSD/sparc64 has SVR4-style shared libraries. */ 00393 set_solib_svr4_fetch_link_map_offsets 00394 (gdbarch, svr4_lp64_fetch_link_map_offsets); 00395 set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); 00396 00397 /* OpenBSD provides a user-level threads implementation. */ 00398 bsd_uthread_set_supply_uthread (gdbarch, sparc64obsd_supply_uthread); 00399 bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread); 00400 } 00401 00402 00403 /* Provide a prototype to silence -Wmissing-prototypes. */ 00404 void _initialize_sparc64obsd_tdep (void); 00405 00406 void 00407 _initialize_sparc64obsd_tdep (void) 00408 { 00409 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, 00410 GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi); 00411 }