1 /* Target-dependent code for GNU/Linux running on the Fujitsu FR-V, 2 for GDB. 3 Copyright 2004 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, 20 Boston, MA 02111-1307, USA. */ 21 22 #include "defs.h" 23 #include "target.h" 24 #include "frame.h" 25 #include "osabi.h" 26 #include "elf-bfd.h" 27 #include "elf/frv.h" 28 #include "frv-tdep.h" 29 #include "trad-frame.h" 30 #include "frame-unwind.h" 31 32 /* Define the size (in bytes) of an FR-V instruction. */ 33 static const int frv_instr_size = 4; 34 35 enum { 36 NORMAL_SIGTRAMP = 1, 37 RT_SIGTRAMP = 2 38 }; 39 40 static int 41 frv_linux_pc_in_sigtramp (CORE_ADDR pc, char *name) 42 { 43 char buf[frv_instr_size]; 44 LONGEST instr; 45 int retval = 0; 46 47 if (target_read_memory (pc, buf, sizeof buf) != 0) 48 return 0; 49 50 instr = extract_unsigned_integer (buf, sizeof buf); 51 52 if (instr == 0x8efc0077) /* setlos #__NR_sigreturn, gr7 */ 53 retval = NORMAL_SIGTRAMP; 54 else if (instr -= 0x8efc00ad) /* setlos #__NR_rt_sigreturn, gr7 */ 55 retval = RT_SIGTRAMP; 56 else 57 return 0; 58 59 if (target_read_memory (pc + frv_instr_size, buf, sizeof buf) != 0) 60 return 0; 61 instr = extract_unsigned_integer (buf, sizeof buf); 62 if (instr != 0xc0700000) /* tira gr0, 0 */ 63 return 0; 64 65 /* If we get this far, we'll return a non-zero value, either 66 NORMAL_SIGTRAMP (1) or RT_SIGTRAMP (2). */ 67 return retval; 68 } 69 70 /* Given NEXT_FRAME, "callee" frame of the sigtramp frame that we 71 wish to decode, and REGNO, one of the frv register numbers defined 72 in frv-tdep.h, return the address of the saved register (corresponding 73 to REGNO) in the sigtramp frame. Return -1 if the register is not 74 found in the sigtramp frame. The magic numbers in the code below 75 were computed by examining the following kernel structs: 76 77 From arch/frvnommu/signal.c: 78 79 struct sigframe 80 { 81 void (*pretcode)(void); 82 int sig; 83 struct sigcontext sc; 84 unsigned long extramask[_NSIG_WORDS-1]; 85 uint32_t retcode[2]; 86 }; 87 88 struct rt_sigframe 89 { 90 void (*pretcode)(void); 91 int sig; 92 struct siginfo *pinfo; 93 void *puc; 94 struct siginfo info; 95 struct ucontext uc; 96 uint32_t retcode[2]; 97 }; 98 99 From include/asm-frvnommu/ucontext.h: 100 101 struct ucontext { 102 unsigned long uc_flags; 103 struct ucontext *uc_link; 104 stack_t uc_stack; 105 struct sigcontext uc_mcontext; 106 sigset_t uc_sigmask; 107 }; 108 109 From include/asm-frvnommu/sigcontext.h: 110 111 struct sigcontext { 112 struct user_context sc_context; 113 unsigned long sc_oldmask; 114 } __attribute__((aligned(8))); 115 116 From include/asm-frvnommu/registers.h: 117 struct user_int_regs 118 { 119 unsigned long psr; 120 unsigned long isr; 121 unsigned long ccr; 122 unsigned long cccr; 123 unsigned long lr; 124 unsigned long lcr; 125 unsigned long pc; 126 unsigned long __status; 127 unsigned long syscallno; 128 unsigned long orig_gr8; 129 unsigned long gner[2]; 130 unsigned long long iacc[1]; 131 132 union { 133 unsigned long tbr; 134 unsigned long gr[64]; 135 }; 136 }; 137 138 struct user_fpmedia_regs 139 { 140 unsigned long fr[64]; 141 unsigned long fner[2]; 142 unsigned long msr[2]; 143 unsigned long acc[8]; 144 unsigned char accg[8]; 145 unsigned long fsr[1]; 146 }; 147 148 struct user_context 149 { 150 struct user_int_regs i; 151 struct user_fpmedia_regs f; 152 153 void *extension; 154 } __attribute__((aligned(8))); */ 155 156 static LONGEST 157 frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno, 158 CORE_ADDR *sc_addr_cache_ptr) 159 { 160 CORE_ADDR sc_addr; 161 162 if (sc_addr_cache_ptr && *sc_addr_cache_ptr) 163 { 164 sc_addr = *sc_addr_cache_ptr; 165 } 166 else 167 { 168 CORE_ADDR pc, sp; 169 char buf[4]; 170 int tramp_type; 171 172 pc = frame_pc_unwind (next_frame); 173 tramp_type = frv_linux_pc_in_sigtramp (pc, 0); 174 175 frame_unwind_register (next_frame, sp_regnum, buf); 176 sp = extract_unsigned_integer (buf, sizeof buf); 177 178 if (tramp_type == NORMAL_SIGTRAMP) 179 { 180 /* For a normal sigtramp frame, the sigcontext struct starts 181 at SP + 8. */ 182 sc_addr = sp + 8; 183 } 184 else if (tramp_type == RT_SIGTRAMP) 185 { 186 /* For a realtime sigtramp frame, SP + 12 contains a pointer 187 to the a ucontext struct. The ucontext struct contains 188 a sigcontext struct starting 12 bytes in. */ 189 if (target_read_memory (sp + 12, buf, sizeof buf) != 0) 190 { 191 warning ("Can't read realtime sigtramp frame."); 192 return 0; 193 } 194 sc_addr = extract_unsigned_integer (buf, sizeof buf); 195 sc_addr += 12; 196 } 197 else 198 internal_error (__FILE__, __LINE__, "not a signal trampoline"); 199 200 if (sc_addr_cache_ptr) 201 *sc_addr_cache_ptr = sc_addr; 202 } 203 204 switch (regno) 205 { 206 case psr_regnum : 207 return sc_addr + 0; 208 /* sc_addr + 4 has "isr", the Integer Status Register. */ 209 case ccr_regnum : 210 return sc_addr + 8; 211 case cccr_regnum : 212 return sc_addr + 12; 213 case lr_regnum : 214 return sc_addr + 16; 215 case lcr_regnum : 216 return sc_addr + 20; 217 case pc_regnum : 218 return sc_addr + 24; 219 /* sc_addr + 28 is __status, the exception status. 220 sc_addr + 32 is syscallno, the syscall number or -1. 221 sc_addr + 36 is orig_gr8, the original syscall arg #1. 222 sc_addr + 40 is gner[0]. 223 sc_addr + 44 is gner[1]. */ 224 case iacc0h_regnum : 225 return sc_addr + 48; 226 case iacc0l_regnum : 227 return sc_addr + 52; 228 default : 229 if (first_gpr_regnum <= regno && regno <= last_gpr_regnum) 230 return sc_addr + 56 + 4 * (regno - first_gpr_regnum); 231 else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum) 232 return sc_addr + 312 + 4 * (regno - first_fpr_regnum); 233 else 234 return -1; /* not saved. */ 235 } 236 } 237 238 /* Signal trampolines. */ 239 240 static struct trad_frame_cache * 241 frv_linux_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache) 242 { 243 struct trad_frame_cache *cache; 244 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); 245 CORE_ADDR addr; 246 char buf[4]; 247 int regnum; 248 CORE_ADDR sc_addr_cache_val = 0; 249 struct frame_id this_id; 250 251 if (*this_cache) 252 return *this_cache; 253 254 cache = trad_frame_cache_zalloc (next_frame); 255 256 /* FIXME: cagney/2004-05-01: This is is long standing broken code. 257 The frame ID's code address should be the start-address of the 258 signal trampoline and not the current PC within that 259 trampoline. */ 260 frame_unwind_register (next_frame, sp_regnum, buf); 261 this_id = frame_id_build (extract_unsigned_integer (buf, sizeof buf), 262 frame_pc_unwind (next_frame)); 263 trad_frame_set_id (cache, this_id); 264 265 for (regnum = 0; regnum < frv_num_regs; regnum++) 266 { 267 LONGEST reg_addr = frv_linux_sigcontext_reg_addr (next_frame, regnum, 268 &sc_addr_cache_val); 269 if (reg_addr != -1) 270 trad_frame_set_reg_addr (cache, regnum, reg_addr); 271 } 272 273 *this_cache = cache; 274 return cache; 275 } 276 277 static void 278 frv_linux_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache, 279 struct frame_id *this_id) 280 { 281 struct trad_frame_cache *cache = 282 frv_linux_sigtramp_frame_cache (next_frame, this_cache); 283 trad_frame_get_id (cache, this_id); 284 } 285 286 static void 287 frv_linux_sigtramp_frame_prev_register (struct frame_info *next_frame, 288 void **this_cache, 289 int regnum, int *optimizedp, 290 enum lval_type *lvalp, CORE_ADDR *addrp, 291 int *realnump, void *valuep) 292 { 293 /* Make sure we've initialized the cache. */ 294 struct trad_frame_cache *cache = 295 frv_linux_sigtramp_frame_cache (next_frame, this_cache); 296 trad_frame_get_register (cache, next_frame, regnum, optimizedp, lvalp, 297 addrp, realnump, valuep); 298 } 299 300 static const struct frame_unwind frv_linux_sigtramp_frame_unwind = 301 { 302 SIGTRAMP_FRAME, 303 frv_linux_sigtramp_frame_this_id, 304 frv_linux_sigtramp_frame_prev_register 305 }; 306 307 static const struct frame_unwind * 308 frv_linux_sigtramp_frame_sniffer (struct frame_info *next_frame) 309 { 310 CORE_ADDR pc = frame_pc_unwind (next_frame); 311 char *name; 312 313 find_pc_partial_function (pc, &name, NULL, NULL); 314 if (frv_linux_pc_in_sigtramp (pc, name)) 315 return &frv_linux_sigtramp_frame_unwind; 316 317 return NULL; 318 } 319 320 static void 321 frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 322 { 323 /* Set the sigtramp frame sniffer. */ 324 frame_unwind_append_sniffer (gdbarch, frv_linux_sigtramp_frame_sniffer); 325 } 326 327 static enum gdb_osabi 328 frv_linux_elf_osabi_sniffer (bfd *abfd) 329 { 330 int elf_flags; 331 332 elf_flags = elf_elfheader (abfd)->e_flags; 333 334 /* Assume GNU/Linux if using the FDPIC ABI. If/when another OS shows 335 up that uses this ABI, we'll need to start using .note sections 336 or some such. */ 337 if (elf_flags & EF_FRV_FDPIC) 338 return GDB_OSABI_LINUX; 339 else 340 return GDB_OSABI_UNKNOWN; 341 } 342 343 /* Provide a prototype to silence -Wmissing-prototypes. */ 344 void _initialize_frv_linux_tdep (void); 345 346 void 347 _initialize_frv_linux_tdep (void) 348 { 349 gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX, frv_linux_init_abi); 350 gdbarch_register_osabi_sniffer (bfd_arch_frv, 351 bfd_target_elf_flavour, 352 frv_linux_elf_osabi_sniffer); 353 } 354