GDB (API)
|
00001 /* Target-dependent code for NetBSD/sparc64. 00002 00003 Copyright (C) 2002-2013 Free Software Foundation, Inc. 00004 Based on code contributed by Wasabi Systems, Inc. 00005 00006 This file is part of GDB. 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00020 00021 #include "defs.h" 00022 #include "frame.h" 00023 #include "frame-unwind.h" 00024 #include "gdbcore.h" 00025 #include "osabi.h" 00026 #include "regcache.h" 00027 #include "regset.h" 00028 #include "symtab.h" 00029 #include "objfiles.h" 00030 #include "solib-svr4.h" 00031 #include "trad-frame.h" 00032 00033 #include "gdb_assert.h" 00034 #include "gdb_string.h" 00035 00036 #include "sparc64-tdep.h" 00037 #include "nbsd-tdep.h" 00038 00039 /* From <machine/reg.h>. */ 00040 const struct sparc_gregset sparc64nbsd_gregset = 00041 { 00042 0 * 8, /* "tstate" */ 00043 1 * 8, /* %pc */ 00044 2 * 8, /* %npc */ 00045 3 * 8, /* %y */ 00046 -1, /* %fprs */ 00047 -1, 00048 5 * 8, /* %g1 */ 00049 -1, /* %l0 */ 00050 4 /* sizeof (%y) */ 00051 }; 00052 00053 00054 static void 00055 sparc64nbsd_supply_gregset (const struct regset *regset, 00056 struct regcache *regcache, 00057 int regnum, const void *gregs, size_t len) 00058 { 00059 sparc64_supply_gregset (&sparc64nbsd_gregset, regcache, regnum, gregs); 00060 } 00061 00062 static void 00063 sparc64nbsd_supply_fpregset (const struct regset *regset, 00064 struct regcache *regcache, 00065 int regnum, const void *fpregs, size_t len) 00066 { 00067 sparc64_supply_fpregset (&sparc64_bsd_fpregset, regcache, regnum, fpregs); 00068 } 00069 00070 00071 /* Signal trampolines. */ 00072 00073 /* The following variables describe the location of an on-stack signal 00074 trampoline. The current values correspond to the memory layout for 00075 NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and 00076 up, since NetBSD uses signal trampolines provided by libc now. */ 00077 00078 static const CORE_ADDR sparc64nbsd_sigtramp_start = 0xffffffffffffdee4ULL; 00079 static const CORE_ADDR sparc64nbsd_sigtramp_end = 0xffffffffffffe000ULL; 00080 00081 static int 00082 sparc64nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) 00083 { 00084 if (pc >= sparc64nbsd_sigtramp_start && pc < sparc64nbsd_sigtramp_end) 00085 return 1; 00086 00087 return nbsd_pc_in_sigtramp (pc, name); 00088 } 00089 00090 struct trad_frame_saved_reg * 00091 sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr, 00092 struct frame_info *this_frame) 00093 { 00094 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00095 struct trad_frame_saved_reg *saved_regs; 00096 CORE_ADDR addr, sp; 00097 int regnum, delta; 00098 00099 saved_regs = trad_frame_alloc_saved_regs (this_frame); 00100 00101 /* The registers are saved in bits and pieces scattered all over the 00102 place. The code below records their location on the assumption 00103 that the part of the signal trampoline that saves the state has 00104 been executed. */ 00105 00106 saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; 00107 saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16; 00108 saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24; 00109 saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32; 00110 saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40; 00111 saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48; 00112 00113 /* The remaining `global' registers and %y are saved in the `local' 00114 registers. */ 00115 delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; 00116 for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) 00117 saved_regs[regnum].realreg = regnum + delta; 00118 saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM; 00119 00120 /* The remaining `out' registers can be found in the current frame's 00121 `in' registers. */ 00122 delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; 00123 for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) 00124 saved_regs[regnum].realreg = regnum + delta; 00125 saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; 00126 00127 /* The `local' and `in' registers have been saved in the register 00128 save area. */ 00129 addr = saved_regs[SPARC_SP_REGNUM].addr; 00130 sp = get_frame_memory_unsigned (this_frame, addr, 8); 00131 for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; 00132 regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) 00133 saved_regs[regnum].addr = addr; 00134 00135 /* Handle StackGhost. */ 00136 { 00137 ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); 00138 00139 if (wcookie != 0) 00140 { 00141 ULONGEST i7; 00142 00143 addr = saved_regs[SPARC_I7_REGNUM].addr; 00144 i7 = get_frame_memory_unsigned (this_frame, addr, 8); 00145 trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie); 00146 } 00147 } 00148 00149 /* TODO: Handle the floating-point registers. */ 00150 00151 return saved_regs; 00152 } 00153 00154 static struct sparc_frame_cache * 00155 sparc64nbsd_sigcontext_frame_cache (struct frame_info *this_frame, 00156 void **this_cache) 00157 { 00158 struct sparc_frame_cache *cache; 00159 CORE_ADDR addr; 00160 00161 if (*this_cache) 00162 return *this_cache; 00163 00164 cache = sparc_frame_cache (this_frame, this_cache); 00165 gdb_assert (cache == *this_cache); 00166 00167 /* If we couldn't find the frame's function, we're probably dealing 00168 with an on-stack signal trampoline. */ 00169 if (cache->pc == 0) 00170 { 00171 cache->pc = sparc64nbsd_sigtramp_start; 00172 00173 /* Since we couldn't find the frame's function, the cache was 00174 initialized under the assumption that we're frameless. */ 00175 sparc_record_save_insn (cache); 00176 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); 00177 if (addr & 1) 00178 addr += BIAS; 00179 cache->base = addr; 00180 } 00181 00182 /* We find the appropriate instance of `struct sigcontext' at a 00183 fixed offset in the signal frame. */ 00184 addr = cache->base + 128 + 8; 00185 cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame); 00186 00187 return cache; 00188 } 00189 00190 static void 00191 sparc64nbsd_sigcontext_frame_this_id (struct frame_info *this_frame, 00192 void **this_cache, 00193 struct frame_id *this_id) 00194 { 00195 struct sparc_frame_cache *cache = 00196 sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache); 00197 00198 (*this_id) = frame_id_build (cache->base, cache->pc); 00199 } 00200 00201 static struct value * 00202 sparc64nbsd_sigcontext_frame_prev_register (struct frame_info *this_frame, 00203 void **this_cache, int regnum) 00204 { 00205 struct sparc_frame_cache *cache = 00206 sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache); 00207 00208 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); 00209 } 00210 00211 static int 00212 sparc64nbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, 00213 struct frame_info *this_frame, 00214 void **this_cache) 00215 { 00216 CORE_ADDR pc = get_frame_pc (this_frame); 00217 const char *name; 00218 00219 find_pc_partial_function (pc, &name, NULL, NULL); 00220 if (sparc64nbsd_pc_in_sigtramp (pc, name)) 00221 { 00222 if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21)) 00223 return 1; 00224 } 00225 00226 return 0; 00227 } 00228 00229 static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind = 00230 { 00231 SIGTRAMP_FRAME, 00232 default_frame_unwind_stop_reason, 00233 sparc64nbsd_sigcontext_frame_this_id, 00234 sparc64nbsd_sigcontext_frame_prev_register, 00235 NULL, 00236 sparc64nbsd_sigtramp_frame_sniffer 00237 }; 00238 00239 00240 static void 00241 sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00242 { 00243 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00244 00245 tdep->gregset = regset_alloc (gdbarch, sparc64nbsd_supply_gregset, NULL); 00246 tdep->sizeof_gregset = 160; 00247 00248 tdep->fpregset = regset_alloc (gdbarch, sparc64nbsd_supply_fpregset, NULL); 00249 tdep->sizeof_fpregset = 272; 00250 00251 /* Make sure we can single-step "new" syscalls. */ 00252 tdep->step_trap = sparcnbsd_step_trap; 00253 00254 frame_unwind_append_unwinder (gdbarch, &sparc64nbsd_sigcontext_frame_unwind); 00255 00256 sparc64_init_abi (info, gdbarch); 00257 00258 /* NetBSD/sparc64 has SVR4-style shared libraries. */ 00259 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 00260 set_solib_svr4_fetch_link_map_offsets 00261 (gdbarch, svr4_lp64_fetch_link_map_offsets); 00262 } 00263 00264 00265 /* Provide a prototype to silence -Wmissing-prototypes. */ 00266 void _initialize_sparc64nbsd_tdep (void); 00267 00268 void 00269 _initialize_sparc64nbsd_tdep (void) 00270 { 00271 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, 00272 GDB_OSABI_NETBSD_ELF, sparc64nbsd_init_abi); 00273 }