daily update
[deliverable/binutils-gdb.git] / gdb / mips-irix-tdep.c
CommitLineData
b96d0a4e
KB
1/* Target-dependent code for the MIPS architecture running on IRIX,
2 for GDB, the GNU Debugger.
3
ecd75fc8 4 Copyright (C) 2002-2014 Free Software Foundation, Inc.
b96d0a4e
KB
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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
b96d0a4e
KB
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
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
b96d0a4e
KB
20
21#include "defs.h"
22#include "osabi.h"
734598d9
UW
23#include "solib.h"
24#include "solib-irix.h"
b96d0a4e 25#include "elf-bfd.h"
6d8eadbd
JB
26#include "mips-tdep.h"
27#include "trad-frame.h"
28#include "tramp-frame.h"
b96d0a4e
KB
29
30static void
31mips_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
6e466374
MR
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;
b96d0a4e
KB
51}
52
53static enum gdb_osabi
54mips_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
025bb325 74 real OS in use we must look for OS notes that have been added.
b96d0a4e
KB
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
6d8eadbd
JB
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. */
142static void
143mips_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
190static 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
1324a0d9
JB
233/* Implement the "init" routine in struct tramp_frame for the stack-based
234 trampolines used on mips-irix. */
235
236static void
237mips_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
258static 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
b96d0a4e
KB
272static void
273mips_irix_init_abi (struct gdbarch_info info,
274 struct gdbarch *gdbarch)
275{
734598d9 276 set_solib_ops (gdbarch, &irix_so_ops);
1324a0d9 277 tramp_frame_prepend_unwinder (gdbarch, &mips_irix_n32_stack_tramp_frame);
6d8eadbd 278 tramp_frame_prepend_unwinder (gdbarch, &mips_irix_n32_tramp_frame);
b96d0a4e
KB
279}
280
63807e1d
PA
281/* Provide a prototype to silence -Wmissing-prototypes. */
282extern initialize_file_ftype _initialize_mips_irix_tdep;
283
b96d0a4e
KB
284void
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
05816f70 292 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_IRIX,
b96d0a4e
KB
293 mips_irix_init_abi);
294}
This page took 1.030646 seconds and 4 git commands to generate.