GDB (API)
|
00001 /* Target-dependent code for FreeBSD/sparc64. 00002 00003 Copyright (C) 2003-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 "target.h" 00028 #include "trad-frame.h" 00029 00030 #include "gdb_assert.h" 00031 #include "gdb_string.h" 00032 00033 #include "sparc64-tdep.h" 00034 #include "solib-svr4.h" 00035 00036 /* From <machine/reg.h>. */ 00037 const struct sparc_gregset sparc64fbsd_gregset = 00038 { 00039 26 * 8, /* "tstate" */ 00040 25 * 8, /* %pc */ 00041 24 * 8, /* %npc */ 00042 28 * 8, /* %y */ 00043 16 * 8, /* %fprs */ 00044 -1, 00045 1 * 8, /* %g1 */ 00046 -1, /* %l0 */ 00047 8 /* sizeof (%y) */ 00048 }; 00049 00050 00051 static void 00052 sparc64fbsd_supply_gregset (const struct regset *regset, 00053 struct regcache *regcache, 00054 int regnum, const void *gregs, size_t len) 00055 { 00056 sparc64_supply_gregset (&sparc64fbsd_gregset, regcache, regnum, gregs); 00057 } 00058 00059 static void 00060 sparc64fbsd_collect_gregset (const struct regset *regset, 00061 const struct regcache *regcache, 00062 int regnum, void *gregs, size_t len) 00063 { 00064 sparc64_collect_gregset (&sparc64fbsd_gregset, regcache, regnum, gregs); 00065 } 00066 00067 static void 00068 sparc64fbsd_supply_fpregset (const struct regset *regset, 00069 struct regcache *regcache, 00070 int regnum, const void *fpregs, size_t len) 00071 { 00072 sparc64_supply_fpregset (&sparc64_bsd_fpregset, regcache, regnum, fpregs); 00073 } 00074 00075 static void 00076 sparc64fbsd_collect_fpregset (const struct regset *regset, 00077 const struct regcache *regcache, 00078 int regnum, void *fpregs, size_t len) 00079 { 00080 sparc64_collect_fpregset (&sparc64_bsd_fpregset, regcache, regnum, fpregs); 00081 } 00082 00083 00084 /* Signal trampolines. */ 00085 00086 static int 00087 sparc64fbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) 00088 { 00089 return (name && strcmp (name, "__sigtramp") == 0); 00090 } 00091 00092 static struct sparc_frame_cache * 00093 sparc64fbsd_sigtramp_frame_cache (struct frame_info *this_frame, 00094 void **this_cache) 00095 { 00096 struct sparc_frame_cache *cache; 00097 CORE_ADDR addr, mcontext_addr, sp; 00098 LONGEST fprs; 00099 int regnum; 00100 00101 if (*this_cache) 00102 return *this_cache; 00103 00104 cache = sparc_frame_cache (this_frame, this_cache); 00105 gdb_assert (cache == *this_cache); 00106 00107 cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); 00108 00109 /* The third argument is a pointer to an instance of `ucontext_t', 00110 which has a member `uc_mcontext' that contains the saved 00111 registers. */ 00112 addr = get_frame_register_unsigned (this_frame, SPARC_O2_REGNUM); 00113 mcontext_addr = addr + 64; 00114 00115 /* The following registers travel in the `mc_local' slots of 00116 `mcontext_t'. */ 00117 addr = mcontext_addr + 16 * 8; 00118 cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 0 * 8; 00119 cache->saved_regs[SPARC64_FSR_REGNUM].addr = addr + 1 * 8; 00120 00121 /* The following registers travel in the `mc_in' slots of 00122 `mcontext_t'. */ 00123 addr = mcontext_addr + 24 * 8; 00124 cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 0 * 8; 00125 cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 1 * 8; 00126 cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 2 * 8; 00127 cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 4 * 8; 00128 00129 /* The `global' and `out' registers travel in the `mc_global' and 00130 `mc_out' slots of `mcontext_t', except for %g0. Since %g0 is 00131 always zero, keep the identity encoding. */ 00132 for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 8; 00133 regnum <= SPARC_O7_REGNUM; regnum++, addr += 8) 00134 cache->saved_regs[regnum].addr = addr; 00135 00136 /* The `local' and `in' registers have been saved in the register 00137 save area. */ 00138 addr = cache->saved_regs[SPARC_SP_REGNUM].addr; 00139 sp = get_frame_memory_unsigned (this_frame, addr, 8); 00140 for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; 00141 regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) 00142 cache->saved_regs[regnum].addr = addr; 00143 00144 /* The floating-point registers are only saved if the FEF bit in 00145 %fprs has been set. */ 00146 00147 #define FPRS_FEF (1 << 2) 00148 00149 addr = cache->saved_regs[SPARC64_FPRS_REGNUM].addr; 00150 fprs = get_frame_memory_unsigned (this_frame, addr, 8); 00151 if (fprs & FPRS_FEF) 00152 { 00153 for (regnum = SPARC_F0_REGNUM, addr = mcontext_addr + 32 * 8; 00154 regnum <= SPARC_F31_REGNUM; regnum++, addr += 4) 00155 cache->saved_regs[regnum].addr = addr; 00156 00157 for (regnum = SPARC64_F32_REGNUM; 00158 regnum <= SPARC64_F62_REGNUM; regnum++, addr += 8) 00159 cache->saved_regs[regnum].addr = addr; 00160 } 00161 00162 return cache; 00163 } 00164 00165 static void 00166 sparc64fbsd_sigtramp_frame_this_id (struct frame_info *this_frame, 00167 void **this_cache, 00168 struct frame_id *this_id) 00169 { 00170 struct sparc_frame_cache *cache = 00171 sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache); 00172 00173 (*this_id) = frame_id_build (cache->base, cache->pc); 00174 } 00175 00176 static struct value * 00177 sparc64fbsd_sigtramp_frame_prev_register (struct frame_info *this_frame, 00178 void **this_cache, int regnum) 00179 { 00180 struct sparc_frame_cache *cache = 00181 sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache); 00182 00183 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); 00184 } 00185 00186 static int 00187 sparc64fbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, 00188 struct frame_info *this_frame, 00189 void **this_cache) 00190 { 00191 CORE_ADDR pc = get_frame_pc (this_frame); 00192 const char *name; 00193 00194 find_pc_partial_function (pc, &name, NULL, NULL); 00195 if (sparc64fbsd_pc_in_sigtramp (pc, name)) 00196 return 1; 00197 00198 return 0; 00199 } 00200 00201 static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind = 00202 { 00203 SIGTRAMP_FRAME, 00204 default_frame_unwind_stop_reason, 00205 sparc64fbsd_sigtramp_frame_this_id, 00206 sparc64fbsd_sigtramp_frame_prev_register, 00207 NULL, 00208 sparc64fbsd_sigtramp_frame_sniffer 00209 }; 00210 00211 00212 static void 00213 sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00214 { 00215 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00216 00217 tdep->gregset = regset_alloc (gdbarch, sparc64fbsd_supply_gregset, 00218 sparc64fbsd_collect_gregset); 00219 tdep->sizeof_gregset = 256; 00220 00221 tdep->fpregset = regset_alloc (gdbarch, sparc64fbsd_supply_fpregset, 00222 sparc64fbsd_collect_fpregset); 00223 tdep->sizeof_fpregset = 272; 00224 00225 frame_unwind_append_unwinder (gdbarch, &sparc64fbsd_sigtramp_frame_unwind); 00226 00227 sparc64_init_abi (info, gdbarch); 00228 00229 /* FreeBSD/sparc64 has SVR4-style shared libraries. */ 00230 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 00231 set_solib_svr4_fetch_link_map_offsets 00232 (gdbarch, svr4_lp64_fetch_link_map_offsets); 00233 } 00234 00235 /* Provide a prototype to silence -Wmissing-prototypes. */ 00236 void _initialize_sparc64fbsd_tdep (void); 00237 00238 void 00239 _initialize_sparc64fbsd_tdep (void) 00240 { 00241 gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, 00242 GDB_OSABI_FREEBSD_ELF, sparc64fbsd_init_abi); 00243 }