IA64: Migrate from 'regset_from_core_section' to 'iterate_over_regset_sections'
[platform/upstream/binutils.git] / gdb / mips-irix-tdep.c
1 /* Target-dependent code for the MIPS architecture running on IRIX,
2    for GDB, the GNU Debugger.
3
4    Copyright (C) 2002-2014 Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 #include "defs.h"
22 #include "osabi.h"
23 #include "solib.h"
24 #include "solib-irix.h"
25 #include "elf-bfd.h"
26 #include "mips-tdep.h"
27 #include "trad-frame.h"
28 #include "tramp-frame.h"
29
30 static void
31 mips_irix_elf_osabi_sniff_abi_tag_sections (bfd *abfd, asection *sect,
32                                             void *obj)
33 {
34   enum gdb_osabi *os_ident_ptr = obj;
35   const char *name;
36   unsigned int sectsize;
37
38   name = bfd_get_section_name (abfd, sect);
39   sectsize = bfd_section_size (abfd, sect);
40
41   /* The presence of a section named with a ".MIPS." prefix is usually
42      indicative of an IRIX binary, however there are exceptions that
43      are present universally, so check for those names and avoid
44      switching away from the default OS ABI in the case of a match.  */
45   if (strncmp (name, ".MIPS.", 6) == 0
46       && strcmp (name, ".MIPS.abiflags") != 0
47       && strcmp (name, ".MIPS.options") != 0
48       && strcmp (name, ".MIPS.stubs") != 0
49       && sectsize > 0)
50     *os_ident_ptr = GDB_OSABI_IRIX;
51 }
52
53 static enum gdb_osabi
54 mips_irix_elf_osabi_sniffer (bfd *abfd)
55 {
56   unsigned int elfosabi;
57   enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
58
59   /* If the generic sniffer gets a hit, return and let other sniffers
60      get a crack at it.  */
61   bfd_map_over_sections (abfd,
62                          generic_elf_osabi_sniff_abi_tag_sections,
63                          &osabi);
64   if (osabi != GDB_OSABI_UNKNOWN)
65     return GDB_OSABI_UNKNOWN;
66
67   elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI];
68
69   if (elfosabi == ELFOSABI_NONE)
70     {
71       /* When elfosabi is ELFOSABI_NONE (0), then the ELF structures in the
72          file are conforming to the base specification for that machine 
73          (there are no OS-specific extensions).  In order to determine the 
74          real OS in use we must look for OS notes that have been added.
75          
76          For IRIX, we simply look for sections named with .MIPS. as
77          prefixes.  */
78       bfd_map_over_sections (abfd,
79                              mips_irix_elf_osabi_sniff_abi_tag_sections, 
80                              &osabi);
81     }
82   return osabi;
83 }
84
85 /* Unwinding past the signal handler on mips-irix.
86
87    Note: The following has only been tested with N32, but can probably
88          be made to work with a small number of adjustments.
89
90    On mips-irix, the sigcontext_t structure is stored at the base
91    of the frame established by the _sigtramp function.  The definition
92    of this structure can be found in <sys/signal.h> (comments have been
93    C++'ified to avoid a collision with the C-style comment delimiters
94    used by this comment):
95
96       typedef struct sigcontext {
97         __uint32_t      sc_regmask;     // regs to restore in sigcleanup
98         __uint32_t      sc_status;      // cp0 status register
99         __uint64_t      sc_pc;          // pc at time of signal
100         // General purpose registers
101         __uint64_t      sc_regs[32];    // processor regs 0 to 31
102         // Floating point coprocessor state
103         __uint64_t      sc_fpregs[32];  // fp regs 0 to 31
104         __uint32_t      sc_ownedfp;     // fp has been used
105         __uint32_t      sc_fpc_csr;     // fpu control and status reg
106         __uint32_t      sc_fpc_eir;     // fpu exception instruction reg
107                                         // implementation/revision
108         __uint32_t      sc_ssflags;     // signal stack state to restore
109         __uint64_t      sc_mdhi;        // Multiplier hi and low regs
110         __uint64_t      sc_mdlo;
111         // System coprocessor registers at time of signal
112         __uint64_t      sc_cause;       // cp0 cause register
113         __uint64_t      sc_badvaddr;    // cp0 bad virtual address
114         __uint64_t      sc_triggersave; // state of graphics trigger (SGI)
115         sigset_t        sc_sigset;      // signal mask to restore
116         __uint64_t      sc_fp_rounded_result;   // for Ieee 754 support
117         __uint64_t      sc_pad[31];
118       } sigcontext_t;
119
120    The following macros provide the offset of some of the fields
121    used to retrieve the value of the registers before the signal
122    was raised.  */
123
124 /* The size of the sigtramp frame.  The sigtramp frame base can then
125    be computed by adding this size to the SP.  */
126 #define SIGTRAMP_FRAME_SIZE 48
127 /* The offset in sigcontext_t where the PC is saved.  */
128 #define SIGCONTEXT_PC_OFF 8
129 /* The offset in sigcontext_t where the GP registers are saved.  */
130 #define SIGCONTEXT_REGS_OFF (SIGCONTEXT_PC_OFF + 8)
131 /* The offset in sigcontext_t where the FP regsiters are saved.  */
132 #define SIGCONTEXT_FPREGS_OFF (SIGCONTEXT_REGS_OFF + 32 * 8)
133 /* The offset in sigcontext_t where the FP CSR register is saved.  */
134 #define SIGCONTEXT_FPCSR_OFF (SIGCONTEXT_FPREGS_OFF + 32 * 8 + 4)
135 /* The offset in sigcontext_t where the multiplier hi register is saved.  */
136 #define SIGCONTEXT_HI_OFF (SIGCONTEXT_FPCSR_OFF + 2 * 4)
137 /* The offset in sigcontext_t where the multiplier lo register is saved.  */
138 #define SIGCONTEXT_LO_OFF (SIGCONTEXT_HI_OFF + 4)
139
140 /* Implement the "init" routine in struct tramp_frame for the N32 ABI
141    on mips-irix.  */
142 static void
143 mips_irix_n32_tramp_frame_init (const struct tramp_frame *self,
144                                 struct frame_info *this_frame,
145                                 struct trad_frame_cache *this_cache,
146                                 CORE_ADDR func)
147 {
148   struct gdbarch *gdbarch = get_frame_arch (this_frame);
149   const int num_regs = gdbarch_num_regs (gdbarch);
150   int sp_cooked_regno = num_regs + MIPS_SP_REGNUM;
151   const CORE_ADDR sp = get_frame_register_signed (this_frame, sp_cooked_regno);
152   const CORE_ADDR sigcontext_base = sp + 48;
153   const struct mips_regnum *regs = mips_regnum (gdbarch);
154   int ireg;
155
156   trad_frame_set_reg_addr (this_cache, regs->pc + gdbarch_num_regs (gdbarch),
157                            sigcontext_base + SIGCONTEXT_PC_OFF);
158
159   for (ireg = 1; ireg < 32; ireg++)
160     trad_frame_set_reg_addr (this_cache, ireg + MIPS_ZERO_REGNUM + num_regs,
161                              sigcontext_base + SIGCONTEXT_REGS_OFF + ireg * 8);
162
163   for (ireg = 0; ireg < 32; ireg++)
164     trad_frame_set_reg_addr (this_cache, ireg + regs->fp0 + num_regs,
165                              sigcontext_base + SIGCONTEXT_FPREGS_OFF
166                                + ireg * 8);
167
168   trad_frame_set_reg_addr (this_cache, regs->fp_control_status + num_regs,
169                            sigcontext_base + SIGCONTEXT_FPCSR_OFF);
170
171   trad_frame_set_reg_addr (this_cache, regs->hi + num_regs,
172                            sigcontext_base + SIGCONTEXT_HI_OFF);
173
174   trad_frame_set_reg_addr (this_cache, regs->lo + num_regs,
175                            sigcontext_base + SIGCONTEXT_LO_OFF);
176
177   trad_frame_set_id (this_cache, frame_id_build (sigcontext_base, func));
178 }
179
180 /* The tramp_frame structure describing sigtramp frames on mips-irix N32.
181
182    Note that the list of instructions below is pretty much a pure dump
183    of function _sigtramp on mips-irix.  A few instructions are actually
184    not tested (mask set to 0), because a portion of these instructions
185    contain an address which changes due to relocation.  We could use
186    a smarter mask that checks the instrutction code alone, but given
187    the number of instructions already being checked, this seemed
188    unnecessary.  */
189
190 static const struct tramp_frame mips_irix_n32_tramp_frame =
191 {
192   SIGTRAMP_FRAME,
193   4,
194   {
195    { 0x3c0c8000, -1 }, /*    lui     t0,0x8000 */
196    { 0x27bdffd0, -1 }, /*    addiu   sp,sp,-48 */
197    { 0x008c6024, -1 }, /*    and     t0,a0,t0 */
198    { 0xffa40018, -1 }, /*    sd      a0,24(sp) */
199    { 0x00000000,  0 }, /*    beqz    t0,0xfaefcb8 <_sigtramp+40> */
200    { 0xffa60028, -1 }, /*    sd      a2,40(sp) */
201    { 0x01806027, -1 }, /*    nor     t0,t0,zero */
202    { 0xffa00020, -1 }, /*    sd      zero,32(sp) */
203    { 0x00000000,  0 }, /*    b       0xfaefcbc <_sigtramp+44> */
204    { 0x008c2024, -1 }, /*    and     a0,a0,t0 */
205    { 0xffa60020, -1 }, /*    sd      a2,32(sp) */
206    { 0x03e0c025, -1 }, /*    move    t8,ra */
207    { 0x00000000,  0 }, /*    bal     0xfaefcc8 <_sigtramp+56> */
208    { 0x00000000, -1 }, /*    nop */
209    { 0x3c0c0007, -1 }, /*    lui     t0,0x7 */
210    { 0x00e0c825, -1 }, /*    move    t9,a3 */
211    { 0x658c80fc, -1 }, /*    daddiu  t0,t0,-32516 */
212    { 0x019f602d, -1 }, /*    daddu   t0,t0,ra */
213    { 0x0300f825, -1 }, /*    move    ra,t8 */
214    { 0x8d8c9880, -1 }, /*    lw      t0,-26496(t0) */
215    { 0x8d8c0000, -1 }, /*    lw      t0,0(t0) */
216    { 0x8d8d0000, -1 }, /*    lw      t1,0(t0) */
217    { 0xffac0008, -1 }, /*    sd      t0,8(sp) */
218    { 0x0320f809, -1 }, /*    jalr    t9 */
219    { 0xffad0010, -1 }, /*    sd      t1,16(sp) */
220    { 0xdfad0010, -1 }, /*    ld      t1,16(sp) */
221    { 0xdfac0008, -1 }, /*    ld      t0,8(sp) */
222    { 0xad8d0000, -1 }, /*    sw      t1,0(t0) */
223    { 0xdfa40020, -1 }, /*    ld      a0,32(sp) */
224    { 0xdfa50028, -1 }, /*    ld      a1,40(sp) */
225    { 0xdfa60018, -1 }, /*    ld      a2,24(sp) */
226    { 0x24020440, -1 }, /*    li      v0,1088 */
227    { 0x0000000c, -1 }, /*    syscall */
228    { TRAMP_SENTINEL_INSN, -1 }
229   },
230   mips_irix_n32_tramp_frame_init
231 };
232
233 /* Implement the "init" routine in struct tramp_frame for the stack-based
234    trampolines used on mips-irix.  */
235
236 static void
237 mips_irix_n32_stack_tramp_frame_init (const struct tramp_frame *self,
238                                       struct frame_info *this_frame,
239                                       struct trad_frame_cache *this_cache,
240                                       CORE_ADDR func)
241 {
242   struct gdbarch *gdbarch = get_frame_arch (this_frame);
243   const int num_regs = gdbarch_num_regs (gdbarch);
244   int sp_cooked_regno = num_regs + MIPS_SP_REGNUM;
245   const CORE_ADDR sp = get_frame_register_signed (this_frame, sp_cooked_regno);
246
247   /* The previous frame's PC is stored in RA.  */
248   trad_frame_set_reg_realreg (this_cache, gdbarch_pc_regnum (gdbarch),
249                               num_regs + MIPS_RA_REGNUM);
250
251   trad_frame_set_id (this_cache, frame_id_build (sp, func));
252 }
253
254 /* A tramp_frame structure describing the stack-based trampoline
255    used on mips-irix.  These trampolines are created on the stack
256    before being called.  */
257
258 static const struct tramp_frame mips_irix_n32_stack_tramp_frame =
259 {
260   SIGTRAMP_FRAME,
261   4,
262   {
263    { 0x8f210000, 0xffff0000 },  /* lw     at, N(t9) */
264    { 0x8f2f0000, 0xffff0000 },  /* lw     t3, M(t9) */
265    { 0x00200008, 0xffffffff },  /* jr     at        */
266    { 0x0020c82d, 0xffffffff },  /* move   t9, at    */
267    { TRAMP_SENTINEL_INSN, -1 }
268   },
269   mips_irix_n32_stack_tramp_frame_init
270 };
271
272 static void
273 mips_irix_init_abi (struct gdbarch_info info,
274                     struct gdbarch *gdbarch)
275 {
276   set_solib_ops (gdbarch, &irix_so_ops);
277   tramp_frame_prepend_unwinder (gdbarch, &mips_irix_n32_stack_tramp_frame);
278   tramp_frame_prepend_unwinder (gdbarch, &mips_irix_n32_tramp_frame);
279 }
280
281 /* Provide a prototype to silence -Wmissing-prototypes.  */
282 extern initialize_file_ftype _initialize_mips_irix_tdep;
283
284 void
285 _initialize_mips_irix_tdep (void)
286 {
287   /* Register an ELF OS ABI sniffer for IRIX binaries.  */
288   gdbarch_register_osabi_sniffer (bfd_arch_mips,
289                                   bfd_target_elf_flavour,
290                                   mips_irix_elf_osabi_sniffer);
291
292   gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_IRIX,
293                           mips_irix_init_abi);
294 }