GDB (API)
|
00001 /* Target-dependent code for the MIPS architecture running on IRIX, 00002 for GDB, the GNU Debugger. 00003 00004 Copyright (C) 2002-2013 Free Software Foundation, 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 "osabi.h" 00023 #include "gdb_string.h" 00024 #include "solib.h" 00025 #include "solib-irix.h" 00026 #include "elf-bfd.h" 00027 #include "mips-tdep.h" 00028 #include "trad-frame.h" 00029 #include "tramp-frame.h" 00030 00031 static void 00032 mips_irix_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect, 00033 void *obj) 00034 { 00035 enum gdb_osabi *os_ident_ptr = obj; 00036 const char *name; 00037 unsigned int sectsize; 00038 00039 name = bfd_get_section_name (abfd, sect); 00040 sectsize = bfd_section_size (abfd, sect); 00041 00042 if (strncmp (name, ".MIPS.", 6) == 0 && sectsize > 0) 00043 { 00044 /* The presence of a section named with a ".MIPS." prefix is 00045 indicative of an IRIX binary. */ 00046 *os_ident_ptr = GDB_OSABI_IRIX; 00047 } 00048 } 00049 00050 static enum gdb_osabi 00051 mips_irix_elf_osabi_sniffer (bfd *abfd) 00052 { 00053 unsigned int elfosabi; 00054 enum gdb_osabi osabi = GDB_OSABI_UNKNOWN; 00055 00056 /* If the generic sniffer gets a hit, return and let other sniffers 00057 get a crack at it. */ 00058 bfd_map_over_sections (abfd, 00059 generic_elf_osabi_sniff_abi_tag_sections, 00060 &osabi); 00061 if (osabi != GDB_OSABI_UNKNOWN) 00062 return GDB_OSABI_UNKNOWN; 00063 00064 elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; 00065 00066 if (elfosabi == ELFOSABI_NONE) 00067 { 00068 /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the 00069 file are conforming to the base specification for that machine 00070 (there are no OS-specific extensions). In order to determine the 00071 real OS in use we must look for OS notes that have been added. 00072 00073 For IRIX, we simply look for sections named with .MIPS. as 00074 prefixes. */ 00075 bfd_map_over_sections (abfd, 00076 mips_irix_elf_osabi_sniff_abi_tag_sections, 00077 &osabi); 00078 } 00079 return osabi; 00080 } 00081 00082 /* Unwinding past the signal handler on mips-irix. 00083 00084 Note: The following has only been tested with N32, but can probably 00085 be made to work with a small number of adjustments. 00086 00087 On mips-irix, the sigcontext_t structure is stored at the base 00088 of the frame established by the _sigtramp function. The definition 00089 of this structure can be found in <sys/signal.h> (comments have been 00090 C++'ified to avoid a collision with the C-style comment delimiters 00091 used by this comment): 00092 00093 typedef struct sigcontext { 00094 __uint32_t sc_regmask; // regs to restore in sigcleanup 00095 __uint32_t sc_status; // cp0 status register 00096 __uint64_t sc_pc; // pc at time of signal 00097 // General purpose registers 00098 __uint64_t sc_regs[32]; // processor regs 0 to 31 00099 // Floating point coprocessor state 00100 __uint64_t sc_fpregs[32]; // fp regs 0 to 31 00101 __uint32_t sc_ownedfp; // fp has been used 00102 __uint32_t sc_fpc_csr; // fpu control and status reg 00103 __uint32_t sc_fpc_eir; // fpu exception instruction reg 00104 // implementation/revision 00105 __uint32_t sc_ssflags; // signal stack state to restore 00106 __uint64_t sc_mdhi; // Multiplier hi and low regs 00107 __uint64_t sc_mdlo; 00108 // System coprocessor registers at time of signal 00109 __uint64_t sc_cause; // cp0 cause register 00110 __uint64_t sc_badvaddr; // cp0 bad virtual address 00111 __uint64_t sc_triggersave; // state of graphics trigger (SGI) 00112 sigset_t sc_sigset; // signal mask to restore 00113 __uint64_t sc_fp_rounded_result; // for Ieee 754 support 00114 __uint64_t sc_pad[31]; 00115 } sigcontext_t; 00116 00117 The following macros provide the offset of some of the fields 00118 used to retrieve the value of the registers before the signal 00119 was raised. */ 00120 00121 /* The size of the sigtramp frame. The sigtramp frame base can then 00122 be computed by adding this size to the SP. */ 00123 #define SIGTRAMP_FRAME_SIZE 48 00124 /* The offset in sigcontext_t where the PC is saved. */ 00125 #define SIGCONTEXT_PC_OFF 8 00126 /* The offset in sigcontext_t where the GP registers are saved. */ 00127 #define SIGCONTEXT_REGS_OFF (SIGCONTEXT_PC_OFF + 8) 00128 /* The offset in sigcontext_t where the FP regsiters are saved. */ 00129 #define SIGCONTEXT_FPREGS_OFF (SIGCONTEXT_REGS_OFF + 32 * 8) 00130 /* The offset in sigcontext_t where the FP CSR register is saved. */ 00131 #define SIGCONTEXT_FPCSR_OFF (SIGCONTEXT_FPREGS_OFF + 32 * 8 + 4) 00132 /* The offset in sigcontext_t where the multiplier hi register is saved. */ 00133 #define SIGCONTEXT_HI_OFF (SIGCONTEXT_FPCSR_OFF + 2 * 4) 00134 /* The offset in sigcontext_t where the multiplier lo register is saved. */ 00135 #define SIGCONTEXT_LO_OFF (SIGCONTEXT_HI_OFF + 4) 00136 00137 /* Implement the "init" routine in struct tramp_frame for the N32 ABI 00138 on mips-irix. */ 00139 static void 00140 mips_irix_n32_tramp_frame_init (const struct tramp_frame *self, 00141 struct frame_info *this_frame, 00142 struct trad_frame_cache *this_cache, 00143 CORE_ADDR func) 00144 { 00145 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00146 const int num_regs = gdbarch_num_regs (gdbarch); 00147 int sp_cooked_regno = num_regs + MIPS_SP_REGNUM; 00148 const CORE_ADDR sp = get_frame_register_signed (this_frame, sp_cooked_regno); 00149 const CORE_ADDR sigcontext_base = sp + 48; 00150 const struct mips_regnum *regs = mips_regnum (gdbarch); 00151 int ireg; 00152 00153 trad_frame_set_reg_addr (this_cache, regs->pc + gdbarch_num_regs (gdbarch), 00154 sigcontext_base + SIGCONTEXT_PC_OFF); 00155 00156 for (ireg = 1; ireg < 32; ireg++) 00157 trad_frame_set_reg_addr (this_cache, ireg + MIPS_ZERO_REGNUM + num_regs, 00158 sigcontext_base + SIGCONTEXT_REGS_OFF + ireg * 8); 00159 00160 for (ireg = 0; ireg < 32; ireg++) 00161 trad_frame_set_reg_addr (this_cache, ireg + regs->fp0 + num_regs, 00162 sigcontext_base + SIGCONTEXT_FPREGS_OFF 00163 + ireg * 8); 00164 00165 trad_frame_set_reg_addr (this_cache, regs->fp_control_status + num_regs, 00166 sigcontext_base + SIGCONTEXT_FPCSR_OFF); 00167 00168 trad_frame_set_reg_addr (this_cache, regs->hi + num_regs, 00169 sigcontext_base + SIGCONTEXT_HI_OFF); 00170 00171 trad_frame_set_reg_addr (this_cache, regs->lo + num_regs, 00172 sigcontext_base + SIGCONTEXT_LO_OFF); 00173 00174 trad_frame_set_id (this_cache, frame_id_build (sigcontext_base, func)); 00175 } 00176 00177 /* The tramp_frame structure describing sigtramp frames on mips-irix N32. 00178 00179 Note that the list of instructions below is pretty much a pure dump 00180 of function _sigtramp on mips-irix. A few instructions are actually 00181 not tested (mask set to 0), because a portion of these instructions 00182 contain an address which changes due to relocation. We could use 00183 a smarter mask that checks the instrutction code alone, but given 00184 the number of instructions already being checked, this seemed 00185 unnecessary. */ 00186 00187 static const struct tramp_frame mips_irix_n32_tramp_frame = 00188 { 00189 SIGTRAMP_FRAME, 00190 4, 00191 { 00192 { 0x3c0c8000, -1 }, /* lui t0,0x8000 */ 00193 { 0x27bdffd0, -1 }, /* addiu sp,sp,-48 */ 00194 { 0x008c6024, -1 }, /* and t0,a0,t0 */ 00195 { 0xffa40018, -1 }, /* sd a0,24(sp) */ 00196 { 0x00000000, 0 }, /* beqz t0,0xfaefcb8 <_sigtramp+40> */ 00197 { 0xffa60028, -1 }, /* sd a2,40(sp) */ 00198 { 0x01806027, -1 }, /* nor t0,t0,zero */ 00199 { 0xffa00020, -1 }, /* sd zero,32(sp) */ 00200 { 0x00000000, 0 }, /* b 0xfaefcbc <_sigtramp+44> */ 00201 { 0x008c2024, -1 }, /* and a0,a0,t0 */ 00202 { 0xffa60020, -1 }, /* sd a2,32(sp) */ 00203 { 0x03e0c025, -1 }, /* move t8,ra */ 00204 { 0x00000000, 0 }, /* bal 0xfaefcc8 <_sigtramp+56> */ 00205 { 0x00000000, -1 }, /* nop */ 00206 { 0x3c0c0007, -1 }, /* lui t0,0x7 */ 00207 { 0x00e0c825, -1 }, /* move t9,a3 */ 00208 { 0x658c80fc, -1 }, /* daddiu t0,t0,-32516 */ 00209 { 0x019f602d, -1 }, /* daddu t0,t0,ra */ 00210 { 0x0300f825, -1 }, /* move ra,t8 */ 00211 { 0x8d8c9880, -1 }, /* lw t0,-26496(t0) */ 00212 { 0x8d8c0000, -1 }, /* lw t0,0(t0) */ 00213 { 0x8d8d0000, -1 }, /* lw t1,0(t0) */ 00214 { 0xffac0008, -1 }, /* sd t0,8(sp) */ 00215 { 0x0320f809, -1 }, /* jalr t9 */ 00216 { 0xffad0010, -1 }, /* sd t1,16(sp) */ 00217 { 0xdfad0010, -1 }, /* ld t1,16(sp) */ 00218 { 0xdfac0008, -1 }, /* ld t0,8(sp) */ 00219 { 0xad8d0000, -1 }, /* sw t1,0(t0) */ 00220 { 0xdfa40020, -1 }, /* ld a0,32(sp) */ 00221 { 0xdfa50028, -1 }, /* ld a1,40(sp) */ 00222 { 0xdfa60018, -1 }, /* ld a2,24(sp) */ 00223 { 0x24020440, -1 }, /* li v0,1088 */ 00224 { 0x0000000c, -1 }, /* syscall */ 00225 { TRAMP_SENTINEL_INSN, -1 } 00226 }, 00227 mips_irix_n32_tramp_frame_init 00228 }; 00229 00230 /* Implement the "init" routine in struct tramp_frame for the stack-based 00231 trampolines used on mips-irix. */ 00232 00233 static void 00234 mips_irix_n32_stack_tramp_frame_init (const struct tramp_frame *self, 00235 struct frame_info *this_frame, 00236 struct trad_frame_cache *this_cache, 00237 CORE_ADDR func) 00238 { 00239 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00240 const int num_regs = gdbarch_num_regs (gdbarch); 00241 int sp_cooked_regno = num_regs + MIPS_SP_REGNUM; 00242 const CORE_ADDR sp = get_frame_register_signed (this_frame, sp_cooked_regno); 00243 00244 /* The previous frame's PC is stored in RA. */ 00245 trad_frame_set_reg_realreg (this_cache, gdbarch_pc_regnum (gdbarch), 00246 num_regs + MIPS_RA_REGNUM); 00247 00248 trad_frame_set_id (this_cache, frame_id_build (sp, func)); 00249 } 00250 00251 /* A tramp_frame structure describing the stack-based trampoline 00252 used on mips-irix. These trampolines are created on the stack 00253 before being called. */ 00254 00255 static const struct tramp_frame mips_irix_n32_stack_tramp_frame = 00256 { 00257 SIGTRAMP_FRAME, 00258 4, 00259 { 00260 { 0x8f210000, 0xffff0000 }, /* lw at, N(t9) */ 00261 { 0x8f2f0000, 0xffff0000 }, /* lw t3, M(t9) */ 00262 { 0x00200008, 0xffffffff }, /* jr at */ 00263 { 0x0020c82d, 0xffffffff }, /* move t9, at */ 00264 { TRAMP_SENTINEL_INSN, -1 } 00265 }, 00266 mips_irix_n32_stack_tramp_frame_init 00267 }; 00268 00269 static void 00270 mips_irix_init_abi (struct gdbarch_info info, 00271 struct gdbarch *gdbarch) 00272 { 00273 set_solib_ops (gdbarch, &irix_so_ops); 00274 tramp_frame_prepend_unwinder (gdbarch, &mips_irix_n32_stack_tramp_frame); 00275 tramp_frame_prepend_unwinder (gdbarch, &mips_irix_n32_tramp_frame); 00276 } 00277 00278 /* Provide a prototype to silence -Wmissing-prototypes. */ 00279 extern initialize_file_ftype _initialize_mips_irix_tdep; 00280 00281 void 00282 _initialize_mips_irix_tdep (void) 00283 { 00284 /* Register an ELF OS ABI sniffer for IRIX binaries. */ 00285 gdbarch_register_osabi_sniffer (bfd_arch_mips, 00286 bfd_target_elf_flavour, 00287 mips_irix_elf_osabi_sniffer); 00288 00289 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_IRIX, 00290 mips_irix_init_abi); 00291 }