GDB (API)
/home/stan/gdb/src/gdb/mips-irix-tdep.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines