GDB (API)
|
00001 /* Target-dependent code for OpenBSD/sparc. 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 "floatformat.h" 00022 #include "frame.h" 00023 #include "frame-unwind.h" 00024 #include "gdbcore.h" 00025 #include "osabi.h" 00026 #include "regcache.h" 00027 #include "symtab.h" 00028 #include "trad-frame.h" 00029 00030 #include "gdb_assert.h" 00031 00032 #include "obsd-tdep.h" 00033 #include "sparc-tdep.h" 00034 #include "solib-svr4.h" 00035 #include "bsd-uthread.h" 00036 00037 /* Signal trampolines. */ 00038 00039 /* The OpenBSD kernel maps the signal trampoline at some random 00040 location in user space, which means that the traditional BSD way of 00041 detecting it won't work. 00042 00043 The signal trampoline will be mapped at an address that is page 00044 aligned. We recognize the signal trampoline by looking for the 00045 sigreturn system call. */ 00046 00047 static const int sparc32obsd_page_size = 4096; 00048 00049 static int 00050 sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) 00051 { 00052 CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1)); 00053 unsigned long insn; 00054 00055 if (name) 00056 return 0; 00057 00058 /* Check for "restore %g0, SYS_sigreturn, %g1". */ 00059 insn = sparc_fetch_instruction (start_pc + 0xec); 00060 if (insn != 0x83e82067) 00061 return 0; 00062 00063 /* Check for "t ST_SYSCALL". */ 00064 insn = sparc_fetch_instruction (start_pc + 0xf4); 00065 if (insn != 0x91d02000) 00066 return 0; 00067 00068 return 1; 00069 } 00070 00071 static struct sparc_frame_cache * 00072 sparc32obsd_sigtramp_frame_cache (struct frame_info *this_frame, 00073 void **this_cache) 00074 { 00075 struct sparc_frame_cache *cache; 00076 CORE_ADDR addr; 00077 00078 if (*this_cache) 00079 return *this_cache; 00080 00081 cache = sparc_frame_cache (this_frame, this_cache); 00082 gdb_assert (cache == *this_cache); 00083 00084 /* If we couldn't find the frame's function, we're probably dealing 00085 with an on-stack signal trampoline. */ 00086 if (cache->pc == 0) 00087 { 00088 cache->pc = get_frame_pc (this_frame); 00089 cache->pc &= ~(sparc32obsd_page_size - 1); 00090 00091 /* Since we couldn't find the frame's function, the cache was 00092 initialized under the assumption that we're frameless. */ 00093 sparc_record_save_insn (cache); 00094 addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); 00095 cache->base = addr; 00096 } 00097 00098 cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame); 00099 00100 return cache; 00101 } 00102 00103 static void 00104 sparc32obsd_sigtramp_frame_this_id (struct frame_info *this_frame, 00105 void **this_cache, 00106 struct frame_id *this_id) 00107 { 00108 struct sparc_frame_cache *cache = 00109 sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); 00110 00111 (*this_id) = frame_id_build (cache->base, cache->pc); 00112 } 00113 00114 static struct value * 00115 sparc32obsd_sigtramp_frame_prev_register (struct frame_info *this_frame, 00116 void **this_cache, int regnum) 00117 { 00118 struct sparc_frame_cache *cache = 00119 sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); 00120 00121 return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); 00122 } 00123 00124 static int 00125 sparc32obsd_sigtramp_frame_sniffer (const struct frame_unwind *self, 00126 struct frame_info *this_frame, 00127 void **this_cache) 00128 { 00129 CORE_ADDR pc = get_frame_pc (this_frame); 00130 const char *name; 00131 00132 find_pc_partial_function (pc, &name, NULL, NULL); 00133 if (sparc32obsd_pc_in_sigtramp (pc, name)) 00134 return 1; 00135 00136 return 0; 00137 } 00138 static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind = 00139 { 00140 SIGTRAMP_FRAME, 00141 default_frame_unwind_stop_reason, 00142 sparc32obsd_sigtramp_frame_this_id, 00143 sparc32obsd_sigtramp_frame_prev_register, 00144 NULL, 00145 sparc32obsd_sigtramp_frame_sniffer 00146 }; 00147 00148 00149 00150 /* Offset wthin the thread structure where we can find %fp and %i7. */ 00151 #define SPARC32OBSD_UTHREAD_FP_OFFSET 128 00152 #define SPARC32OBSD_UTHREAD_PC_OFFSET 132 00153 00154 static void 00155 sparc32obsd_supply_uthread (struct regcache *regcache, 00156 int regnum, CORE_ADDR addr) 00157 { 00158 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00159 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00160 CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; 00161 gdb_byte buf[4]; 00162 00163 gdb_assert (regnum >= -1); 00164 00165 fp = read_memory_unsigned_integer (fp_addr, 4, byte_order); 00166 if (regnum == SPARC_SP_REGNUM || regnum == -1) 00167 { 00168 store_unsigned_integer (buf, 4, byte_order, fp); 00169 regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf); 00170 00171 if (regnum == SPARC_SP_REGNUM) 00172 return; 00173 } 00174 00175 if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM 00176 || regnum == -1) 00177 { 00178 CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; 00179 00180 i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order); 00181 if (regnum == SPARC32_PC_REGNUM || regnum == -1) 00182 { 00183 store_unsigned_integer (buf, 4, byte_order, i7 + 8); 00184 regcache_raw_supply (regcache, SPARC32_PC_REGNUM, buf); 00185 } 00186 if (regnum == SPARC32_NPC_REGNUM || regnum == -1) 00187 { 00188 store_unsigned_integer (buf, 4, byte_order, i7 + 12); 00189 regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, buf); 00190 } 00191 00192 if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM) 00193 return; 00194 } 00195 00196 sparc_supply_rwindow (regcache, fp, regnum); 00197 } 00198 00199 static void 00200 sparc32obsd_collect_uthread(const struct regcache *regcache, 00201 int regnum, CORE_ADDR addr) 00202 { 00203 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00204 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00205 CORE_ADDR sp; 00206 gdb_byte buf[4]; 00207 00208 gdb_assert (regnum >= -1); 00209 00210 if (regnum == SPARC_SP_REGNUM || regnum == -1) 00211 { 00212 CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; 00213 00214 regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); 00215 write_memory (fp_addr,buf, 4); 00216 } 00217 00218 if (regnum == SPARC32_PC_REGNUM || regnum == -1) 00219 { 00220 CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; 00221 00222 regcache_raw_collect (regcache, SPARC32_PC_REGNUM, buf); 00223 i7 = extract_unsigned_integer (buf, 4, byte_order) - 8; 00224 write_memory_unsigned_integer (i7_addr, 4, byte_order, i7); 00225 00226 if (regnum == SPARC32_PC_REGNUM) 00227 return; 00228 } 00229 00230 regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); 00231 sp = extract_unsigned_integer (buf, 4, byte_order); 00232 sparc_collect_rwindow (regcache, sp, regnum); 00233 } 00234 00235 00236 static void 00237 sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00238 { 00239 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00240 00241 /* OpenBSD/sparc is very similar to NetBSD/sparc ELF. */ 00242 sparc32nbsd_elf_init_abi (info, gdbarch); 00243 00244 set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); 00245 00246 frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind); 00247 00248 /* OpenBSD provides a user-level threads implementation. */ 00249 bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread); 00250 bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread); 00251 } 00252 00253 00254 /* Provide a prototype to silence -Wmissing-prototypes. */ 00255 void _initialize_sparc32obsd_tdep (void); 00256 00257 void 00258 _initialize_sparc32obsd_tdep (void) 00259 { 00260 gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF, 00261 sparc32obsd_init_abi); 00262 }