1130803Smarcel/* Target-dependent code for NetBSD/sparc64. 2130803Smarcel 3130803Smarcel Copyright 2002, 2003, 2004 Free Software Foundation, Inc. 4130803Smarcel Based on code contributed by Wasabi Systems, Inc. 5130803Smarcel 6130803Smarcel This file is part of GDB. 7130803Smarcel 8130803Smarcel This program is free software; you can redistribute it and/or modify 9130803Smarcel it under the terms of the GNU General Public License as published by 10130803Smarcel the Free Software Foundation; either version 2 of the License, or 11130803Smarcel (at your option) any later version. 12130803Smarcel 13130803Smarcel This program is distributed in the hope that it will be useful, 14130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 15130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130803Smarcel GNU General Public License for more details. 17130803Smarcel 18130803Smarcel You should have received a copy of the GNU General Public License 19130803Smarcel along with this program; if not, write to the Free Software 20130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 21130803Smarcel Boston, MA 02111-1307, USA. */ 22130803Smarcel 23130803Smarcel#include "defs.h" 24130803Smarcel#include "frame.h" 25130803Smarcel#include "frame-unwind.h" 26130803Smarcel#include "gdbcore.h" 27130803Smarcel#include "osabi.h" 28130803Smarcel#include "regcache.h" 29130803Smarcel#include "regset.h" 30130803Smarcel#include "symtab.h" 31130803Smarcel#include "solib-svr4.h" 32130803Smarcel#include "trad-frame.h" 33130803Smarcel 34130803Smarcel#include "gdb_assert.h" 35130803Smarcel#include "gdb_string.h" 36130803Smarcel 37130803Smarcel#include "sparc64-tdep.h" 38130803Smarcel#include "nbsd-tdep.h" 39130803Smarcel 40130803Smarcel/* From <machine/reg.h>. */ 41130803Smarcelconst struct sparc_gregset sparc64nbsd_gregset = 42130803Smarcel{ 43130803Smarcel 0 * 8, /* "tstate" */ 44130803Smarcel 1 * 8, /* %pc */ 45130803Smarcel 2 * 8, /* %npc */ 46130803Smarcel 3 * 8, /* %y */ 47130803Smarcel -1, /* %fprs */ 48130803Smarcel -1, 49130803Smarcel 5 * 8, /* %g1 */ 50130803Smarcel -1, /* %l0 */ 51130803Smarcel 4 /* sizeof (%y) */ 52130803Smarcel}; 53130803Smarcel 54130803Smarcel 55130803Smarcelstatic void 56130803Smarcelsparc64nbsd_supply_gregset (const struct regset *regset, 57130803Smarcel struct regcache *regcache, 58130803Smarcel int regnum, const void *gregs, size_t len) 59130803Smarcel{ 60130803Smarcel sparc64_supply_gregset (regset->descr, regcache, regnum, gregs); 61130803Smarcel} 62130803Smarcel 63130803Smarcelstatic void 64130803Smarcelsparc64nbsd_supply_fpregset (const struct regset *regset, 65130803Smarcel struct regcache *regcache, 66130803Smarcel int regnum, const void *fpregs, size_t len) 67130803Smarcel{ 68130803Smarcel sparc64_supply_fpregset (regcache, regnum, fpregs); 69130803Smarcel} 70130803Smarcel 71130803Smarcel 72130803Smarcel/* Signal trampolines. */ 73130803Smarcel 74130803Smarcel/* The following variables describe the location of an on-stack signal 75130803Smarcel trampoline. The current values correspond to the memory layout for 76130803Smarcel NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and 77130803Smarcel up, since NetBSD uses signal trampolines provided by libc now. */ 78130803Smarcel 79130803Smarcelstatic const CORE_ADDR sparc64nbsd_sigtramp_start = 0xffffffffffffdee4ULL; 80130803Smarcelstatic const CORE_ADDR sparc64nbsd_sigtramp_end = 0xffffffffffffe000ULL; 81130803Smarcel 82130803Smarcelstatic int 83130803Smarcelsparc64nbsd_pc_in_sigtramp (CORE_ADDR pc, char *name) 84130803Smarcel{ 85130803Smarcel if (pc >= sparc64nbsd_sigtramp_start && pc < sparc64nbsd_sigtramp_end) 86130803Smarcel return 1; 87130803Smarcel 88130803Smarcel return nbsd_pc_in_sigtramp (pc, name); 89130803Smarcel} 90130803Smarcel 91130803Smarcelstruct trad_frame_saved_reg * 92130803Smarcelsparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr, 93130803Smarcel struct frame_info *next_frame) 94130803Smarcel{ 95130803Smarcel struct trad_frame_saved_reg *saved_regs; 96130803Smarcel CORE_ADDR addr, sp; 97130803Smarcel int regnum, delta; 98130803Smarcel 99130803Smarcel saved_regs = trad_frame_alloc_saved_regs (next_frame); 100130803Smarcel 101130803Smarcel /* The registers are saved in bits and pieces scattered all over the 102130803Smarcel place. The code below records their location on the assumption 103130803Smarcel that the part of the signal trampoline that saves the state has 104130803Smarcel been executed. */ 105130803Smarcel 106130803Smarcel saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; 107130803Smarcel saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16; 108130803Smarcel saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24; 109130803Smarcel saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32; 110130803Smarcel saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40; 111130803Smarcel saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48; 112130803Smarcel 113130803Smarcel /* The remaining `global' registers and %y are saved in the `local' 114130803Smarcel registers. */ 115130803Smarcel delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; 116130803Smarcel for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) 117130803Smarcel saved_regs[regnum].realreg = regnum + delta; 118130803Smarcel saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM; 119130803Smarcel 120130803Smarcel /* The remaining `out' registers can be found in the current frame's 121130803Smarcel `in' registers. */ 122130803Smarcel delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; 123130803Smarcel for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) 124130803Smarcel saved_regs[regnum].realreg = regnum + delta; 125130803Smarcel saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; 126130803Smarcel 127130803Smarcel /* The `local' and `in' registers have been saved in the register 128130803Smarcel save area. */ 129130803Smarcel addr = saved_regs[SPARC_SP_REGNUM].addr; 130130803Smarcel sp = get_frame_memory_unsigned (next_frame, addr, 8); 131130803Smarcel for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; 132130803Smarcel regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) 133130803Smarcel saved_regs[regnum].addr = addr; 134130803Smarcel 135130803Smarcel /* TODO: Handle the floating-point registers. */ 136130803Smarcel 137130803Smarcel return saved_regs; 138130803Smarcel} 139130803Smarcel 140130803Smarcelstatic struct sparc_frame_cache * 141130803Smarcelsparc64nbsd_sigcontext_frame_cache (struct frame_info *next_frame, 142130803Smarcel void **this_cache) 143130803Smarcel{ 144130803Smarcel struct sparc_frame_cache *cache; 145130803Smarcel CORE_ADDR addr; 146130803Smarcel 147130803Smarcel if (*this_cache) 148130803Smarcel return *this_cache; 149130803Smarcel 150130803Smarcel cache = sparc_frame_cache (next_frame, this_cache); 151130803Smarcel gdb_assert (cache == *this_cache); 152130803Smarcel 153130803Smarcel /* If we couldn't find the frame's function, we're probably dealing 154130803Smarcel with an on-stack signal trampoline. */ 155130803Smarcel if (cache->pc == 0) 156130803Smarcel { 157130803Smarcel cache->pc = sparc64nbsd_sigtramp_start; 158130803Smarcel 159130803Smarcel /* Since we couldn't find the frame's function, the cache was 160130803Smarcel initialized under the assumption that we're frameless. */ 161130803Smarcel cache->frameless_p = 0; 162130803Smarcel addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM); 163130803Smarcel cache->base = addr; 164130803Smarcel } 165130803Smarcel 166130803Smarcel /* We find the appropriate instance of `struct sigcontext' at a 167130803Smarcel fixed offset in the signal frame. */ 168130803Smarcel addr = cache->base + BIAS + 128 + 8; 169130803Smarcel cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame); 170130803Smarcel 171130803Smarcel return cache; 172130803Smarcel} 173130803Smarcel 174130803Smarcelstatic void 175130803Smarcelsparc64nbsd_sigcontext_frame_this_id (struct frame_info *next_frame, 176130803Smarcel void **this_cache, 177130803Smarcel struct frame_id *this_id) 178130803Smarcel{ 179130803Smarcel struct sparc_frame_cache *cache = 180130803Smarcel sparc64nbsd_sigcontext_frame_cache (next_frame, this_cache); 181130803Smarcel 182130803Smarcel (*this_id) = frame_id_build (cache->base, cache->pc); 183130803Smarcel} 184130803Smarcel 185130803Smarcelstatic void 186130803Smarcelsparc64nbsd_sigcontext_frame_prev_register (struct frame_info *next_frame, 187130803Smarcel void **this_cache, 188130803Smarcel int regnum, int *optimizedp, 189130803Smarcel enum lval_type *lvalp, 190130803Smarcel CORE_ADDR *addrp, 191130803Smarcel int *realnump, void *valuep) 192130803Smarcel{ 193130803Smarcel struct sparc_frame_cache *cache = 194130803Smarcel sparc64nbsd_sigcontext_frame_cache (next_frame, this_cache); 195130803Smarcel 196130803Smarcel trad_frame_prev_register (next_frame, cache->saved_regs, regnum, 197130803Smarcel optimizedp, lvalp, addrp, realnump, valuep); 198130803Smarcel} 199130803Smarcel 200130803Smarcelstatic const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind = 201130803Smarcel{ 202130803Smarcel SIGTRAMP_FRAME, 203130803Smarcel sparc64nbsd_sigcontext_frame_this_id, 204130803Smarcel sparc64nbsd_sigcontext_frame_prev_register 205130803Smarcel}; 206130803Smarcel 207130803Smarcelstatic const struct frame_unwind * 208130803Smarcelsparc64nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame) 209130803Smarcel{ 210130803Smarcel CORE_ADDR pc = frame_pc_unwind (next_frame); 211130803Smarcel char *name; 212130803Smarcel 213130803Smarcel find_pc_partial_function (pc, &name, NULL, NULL); 214130803Smarcel if (sparc64nbsd_pc_in_sigtramp (pc, name)) 215130803Smarcel { 216130803Smarcel if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21)) 217130803Smarcel return &sparc64nbsd_sigcontext_frame_unwind; 218130803Smarcel } 219130803Smarcel 220130803Smarcel return NULL; 221130803Smarcel} 222130803Smarcel 223130803Smarcel 224130803Smarcelstatic void 225130803Smarcelsparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 226130803Smarcel{ 227130803Smarcel struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 228130803Smarcel 229130803Smarcel tdep->gregset = XMALLOC (struct regset); 230130803Smarcel tdep->gregset->descr = &sparc64nbsd_gregset; 231130803Smarcel tdep->gregset->supply_regset = sparc64nbsd_supply_gregset; 232130803Smarcel tdep->sizeof_gregset = 160; 233130803Smarcel 234130803Smarcel tdep->fpregset = XMALLOC (struct regset); 235130803Smarcel tdep->fpregset->supply_regset = sparc64nbsd_supply_fpregset; 236130803Smarcel tdep->sizeof_fpregset = 272; 237130803Smarcel 238130803Smarcel set_gdbarch_pc_in_sigtramp (gdbarch, sparc64nbsd_pc_in_sigtramp); 239130803Smarcel frame_unwind_append_sniffer (gdbarch, sparc64nbsd_sigtramp_frame_sniffer); 240130803Smarcel 241130803Smarcel sparc64_init_abi (info, gdbarch); 242130803Smarcel 243130803Smarcel set_solib_svr4_fetch_link_map_offsets 244130803Smarcel (gdbarch, nbsd_lp64_solib_svr4_fetch_link_map_offsets); 245130803Smarcel} 246130803Smarcel 247130803Smarcel 248130803Smarcel/* Provide a prototype to silence -Wmissing-prototypes. */ 249130803Smarcelvoid _initialize_sparc64nbsd_tdep (void); 250130803Smarcel 251130803Smarcelvoid 252130803Smarcel_initialize_sparc64nbsd_tdep (void) 253130803Smarcel{ 254130803Smarcel gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, 255130803Smarcel GDB_OSABI_NETBSD_ELF, sparc64nbsd_init_abi); 256130803Smarcel} 257