1 /* Target-dependent code for MIPS systems running NetBSD.
2 Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
3 Contributed by Wasabi Systems, Inc.
5 This file is part of GDB.
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.
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.
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. */
29 #include "gdb_string.h"
31 #include "nbsd-tdep.h"
32 #include "mipsnbsd-tdep.h"
33 #include "mips-tdep.h"
35 #include "solib-svr4.h"
37 /* Conveniently, GDB uses the same register numbering as the
38 ptrace register structure used by NetBSD/mips. */
41 mipsnbsd_supply_reg (char *regs
, int regno
)
45 for (i
= 0; i
<= PC_REGNUM
; i
++)
47 if (regno
== i
|| regno
== -1)
49 if (CANNOT_FETCH_REGISTER (i
))
50 regcache_raw_supply (current_regcache
, i
, NULL
);
52 regcache_raw_supply (current_regcache
, i
,
53 regs
+ (i
* mips_isa_regsize (current_gdbarch
)));
59 mipsnbsd_fill_reg (char *regs
, int regno
)
63 for (i
= 0; i
<= PC_REGNUM
; i
++)
64 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
65 regcache_raw_collect (current_regcache
, i
,
66 regs
+ (i
* mips_isa_regsize (current_gdbarch
)));
70 mipsnbsd_supply_fpreg (char *fpregs
, int regno
)
75 i
<= mips_regnum (current_gdbarch
)->fp_implementation_revision
;
78 if (regno
== i
|| regno
== -1)
80 if (CANNOT_FETCH_REGISTER (i
))
81 regcache_raw_supply (current_regcache
, i
, NULL
);
83 regcache_raw_supply (current_regcache
, i
,
84 fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
90 mipsnbsd_fill_fpreg (char *fpregs
, int regno
)
94 for (i
= FP0_REGNUM
; i
<= mips_regnum (current_gdbarch
)->fp_control_status
;
96 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
97 regcache_raw_collect (current_regcache
, i
,
98 fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
102 fetch_core_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
107 /* We get everything from one section. */
111 regs
= core_reg_sect
;
112 fpregs
= core_reg_sect
+ SIZEOF_STRUCT_REG
;
114 /* Integer registers. */
115 mipsnbsd_supply_reg (regs
, -1);
117 /* Floating point registers. */
118 mipsnbsd_supply_fpreg (fpregs
, -1);
122 fetch_elfcore_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
127 case 0: /* Integer registers. */
128 if (core_reg_size
!= SIZEOF_STRUCT_REG
)
129 warning ("Wrong size register set in core file.");
131 mipsnbsd_supply_reg (core_reg_sect
, -1);
134 case 2: /* Floating point registers. */
135 if (core_reg_size
!= SIZEOF_STRUCT_FPREG
)
136 warning ("Wrong size register set in core file.");
138 mipsnbsd_supply_fpreg (core_reg_sect
, -1);
142 /* Don't know what kind of register request this is; just ignore it. */
147 static struct core_fns mipsnbsd_core_fns
=
149 bfd_target_unknown_flavour
, /* core_flavour */
150 default_check_format
, /* check_format */
151 default_core_sniffer
, /* core_sniffer */
152 fetch_core_registers
, /* core_read_registers */
156 static struct core_fns mipsnbsd_elfcore_fns
=
158 bfd_target_elf_flavour
, /* core_flavour */
159 default_check_format
, /* check_format */
160 default_core_sniffer
, /* core_sniffer */
161 fetch_elfcore_registers
, /* core_read_registers */
165 /* Under NetBSD/mips, signal handler invocations can be identified by the
166 designated code sequence that is used to return from a signal handler.
167 In particular, the return address of a signal handler points to the
168 following code sequence:
171 li v0, 295 # __sigreturn14
174 Each instruction has a unique encoding, so we simply attempt to match
175 the instruction the PC is pointing to with any of the above instructions.
176 If there is a hit, we know the offset to the start of the designated
177 sequence and can then check whether we really are executing in the
178 signal trampoline. If not, -1 is returned, otherwise the offset from the
179 start of the return sequence is returned. */
181 #define RETCODE_NWORDS 3
182 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
184 static const unsigned char sigtramp_retcode_mipsel
[RETCODE_SIZE
] =
186 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
187 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
188 0x0c, 0x00, 0x00, 0x00, /* syscall */
191 static const unsigned char sigtramp_retcode_mipseb
[RETCODE_SIZE
] =
193 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
194 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
195 0x00, 0x00, 0x00, 0x0c, /* syscall */
199 mipsnbsd_sigtramp_offset (struct frame_info
*next_frame
)
201 CORE_ADDR pc
= frame_pc_unwind (next_frame
);
202 const char *retcode
= TARGET_BYTE_ORDER
== BFD_ENDIAN_BIG
203 ? sigtramp_retcode_mipseb
: sigtramp_retcode_mipsel
;
204 unsigned char ret
[RETCODE_SIZE
], w
[4];
208 if (!safe_frame_unwind_memory (next_frame
, pc
, w
, sizeof (w
)))
211 for (i
= 0; i
< RETCODE_NWORDS
; i
++)
213 if (memcmp (w
, retcode
+ (i
* 4), 4) == 0)
216 if (i
== RETCODE_NWORDS
)
222 if (!safe_frame_unwind_memory (next_frame
, pc
, ret
, sizeof (ret
)))
225 if (memcmp (ret
, retcode
, RETCODE_SIZE
) == 0)
231 /* Figure out where the longjmp will land. We expect that we have
232 just entered longjmp and haven't yet setup the stack frame, so the
233 args are still in the argument regs. MIPS_A0_REGNUM points at the
234 jmp_buf structure from which we extract the PC that we will land
235 at. The PC is copied into *pc. This routine returns true on
238 #define NBSD_MIPS_JB_PC (2 * 4)
239 #define NBSD_MIPS_JB_ELEMENT_SIZE mips_isa_regsize (current_gdbarch)
240 #define NBSD_MIPS_JB_OFFSET (NBSD_MIPS_JB_PC * \
241 NBSD_MIPS_JB_ELEMENT_SIZE)
244 mipsnbsd_get_longjmp_target (CORE_ADDR
*pc
)
249 buf
= alloca (NBSD_MIPS_JB_ELEMENT_SIZE
);
251 jb_addr
= read_register (MIPS_A0_REGNUM
);
253 if (target_read_memory (jb_addr
+ NBSD_MIPS_JB_OFFSET
, buf
,
254 NBSD_MIPS_JB_ELEMENT_SIZE
))
257 *pc
= extract_unsigned_integer (buf
, NBSD_MIPS_JB_ELEMENT_SIZE
);
263 mipsnbsd_cannot_fetch_register (int regno
)
265 return (regno
== MIPS_ZERO_REGNUM
266 || regno
== mips_regnum (current_gdbarch
)->fp_implementation_revision
);
270 mipsnbsd_cannot_store_register (int regno
)
272 return (regno
== MIPS_ZERO_REGNUM
273 || regno
== mips_regnum (current_gdbarch
)->fp_implementation_revision
);
276 /* NetBSD/mips uses a slightly different link_map structure from the
277 other NetBSD platforms. */
278 static struct link_map_offsets
*
279 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
281 static struct link_map_offsets lmo
;
282 static struct link_map_offsets
*lmp
= NULL
;
288 lmo
.r_debug_size
= 16;
290 lmo
.r_map_offset
= 4;
293 lmo
.link_map_size
= 24;
295 lmo
.l_addr_offset
= 4;
298 lmo
.l_name_offset
= 8;
301 lmo
.l_next_offset
= 16;
304 lmo
.l_prev_offset
= 20;
311 static struct link_map_offsets
*
312 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets (void)
314 static struct link_map_offsets lmo
;
315 static struct link_map_offsets
*lmp
= NULL
;
321 lmo
.r_debug_size
= 32;
323 lmo
.r_map_offset
= 8;
326 lmo
.link_map_size
= 48;
328 lmo
.l_addr_offset
= 0;
331 lmo
.l_name_offset
= 16;
334 lmo
.l_next_offset
= 32;
337 lmo
.l_prev_offset
= 40;
345 mipsnbsd_init_abi (struct gdbarch_info info
,
346 struct gdbarch
*gdbarch
)
348 set_gdbarch_get_longjmp_target (gdbarch
, mipsnbsd_get_longjmp_target
);
350 set_gdbarch_cannot_fetch_register (gdbarch
, mipsnbsd_cannot_fetch_register
);
351 set_gdbarch_cannot_store_register (gdbarch
, mipsnbsd_cannot_store_register
);
353 set_gdbarch_software_single_step (gdbarch
, mips_software_single_step
);
355 set_solib_svr4_fetch_link_map_offsets (gdbarch
,
356 gdbarch_ptr_bit (gdbarch
) == 32 ?
357 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets
:
358 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets
);
362 _initialize_mipsnbsd_tdep (void)
364 gdbarch_register_osabi (bfd_arch_mips
, 0, GDB_OSABI_NETBSD_ELF
,
367 deprecated_add_core_fns (&mipsnbsd_core_fns
);
368 deprecated_add_core_fns (&mipsnbsd_elfcore_fns
);