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 "nbsd-tdep.h"
30 #include "mipsnbsd-tdep.h"
31 #include "mips-tdep.h"
33 #include "solib-svr4.h"
35 /* Conveniently, GDB uses the same register numbering as the
36 ptrace register structure used by NetBSD/mips. */
39 mipsnbsd_supply_reg (char *regs
, int regno
)
43 for (i
= 0; i
<= PC_REGNUM
; i
++)
45 if (regno
== i
|| regno
== -1)
47 if (CANNOT_FETCH_REGISTER (i
))
48 supply_register (i
, NULL
);
50 supply_register (i
, regs
+ (i
* mips_isa_regsize (current_gdbarch
)));
56 mipsnbsd_fill_reg (char *regs
, int regno
)
60 for (i
= 0; i
<= PC_REGNUM
; i
++)
61 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
62 regcache_collect (i
, regs
+ (i
* mips_isa_regsize (current_gdbarch
)));
66 mipsnbsd_supply_fpreg (char *fpregs
, int regno
)
71 i
<= mips_regnum (current_gdbarch
)->fp_implementation_revision
;
74 if (regno
== i
|| regno
== -1)
76 if (CANNOT_FETCH_REGISTER (i
))
77 supply_register (i
, NULL
);
79 supply_register (i
, fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
85 mipsnbsd_fill_fpreg (char *fpregs
, int regno
)
89 for (i
= FP0_REGNUM
; i
<= mips_regnum (current_gdbarch
)->fp_control_status
;
91 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
92 regcache_collect (i
, fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
96 fetch_core_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
101 /* We get everything from one section. */
105 regs
= core_reg_sect
;
106 fpregs
= core_reg_sect
+ SIZEOF_STRUCT_REG
;
108 /* Integer registers. */
109 mipsnbsd_supply_reg (regs
, -1);
111 /* Floating point registers. */
112 mipsnbsd_supply_fpreg (fpregs
, -1);
116 fetch_elfcore_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
121 case 0: /* Integer registers. */
122 if (core_reg_size
!= SIZEOF_STRUCT_REG
)
123 warning ("Wrong size register set in core file.");
125 mipsnbsd_supply_reg (core_reg_sect
, -1);
128 case 2: /* Floating point registers. */
129 if (core_reg_size
!= SIZEOF_STRUCT_FPREG
)
130 warning ("Wrong size register set in core file.");
132 mipsnbsd_supply_fpreg (core_reg_sect
, -1);
136 /* Don't know what kind of register request this is; just ignore it. */
141 static struct core_fns mipsnbsd_core_fns
=
143 bfd_target_unknown_flavour
, /* core_flavour */
144 default_check_format
, /* check_format */
145 default_core_sniffer
, /* core_sniffer */
146 fetch_core_registers
, /* core_read_registers */
150 static struct core_fns mipsnbsd_elfcore_fns
=
152 bfd_target_elf_flavour
, /* core_flavour */
153 default_check_format
, /* check_format */
154 default_core_sniffer
, /* core_sniffer */
155 fetch_elfcore_registers
, /* core_read_registers */
159 /* Under NetBSD/mips, signal handler invocations can be identified by the
160 designated code sequence that is used to return from a signal handler.
161 In particular, the return address of a signal handler points to the
162 following code sequence:
165 li v0, 295 # __sigreturn14
168 Each instruction has a unique encoding, so we simply attempt to match
169 the instruction the PC is pointing to with any of the above instructions.
170 If there is a hit, we know the offset to the start of the designated
171 sequence and can then check whether we really are executing in the
172 signal trampoline. If not, -1 is returned, otherwise the offset from the
173 start of the return sequence is returned. */
175 #define RETCODE_NWORDS 3
176 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
178 static const unsigned char sigtramp_retcode_mipsel
[RETCODE_SIZE
] =
180 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
181 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
182 0x0c, 0x00, 0x00, 0x00, /* syscall */
185 static const unsigned char sigtramp_retcode_mipseb
[RETCODE_SIZE
] =
187 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
188 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
189 0x00, 0x00, 0x00, 0x0c, /* syscall */
193 mipsnbsd_sigtramp_offset (CORE_ADDR pc
)
195 const char *retcode
= TARGET_BYTE_ORDER
== BFD_ENDIAN_BIG
196 ? sigtramp_retcode_mipseb
: sigtramp_retcode_mipsel
;
197 unsigned char ret
[RETCODE_SIZE
], w
[4];
201 if (read_memory_nobpt (pc
, (char *) w
, sizeof (w
)) != 0)
204 for (i
= 0; i
< RETCODE_NWORDS
; i
++)
206 if (memcmp (w
, retcode
+ (i
* 4), 4) == 0)
209 if (i
== RETCODE_NWORDS
)
215 if (read_memory_nobpt (pc
, (char *) ret
, sizeof (ret
)) != 0)
218 if (memcmp (ret
, retcode
, RETCODE_SIZE
) == 0)
225 mipsnbsd_pc_in_sigtramp (CORE_ADDR pc
, char *func_name
)
227 return (nbsd_pc_in_sigtramp (pc
, func_name
)
228 || mipsnbsd_sigtramp_offset (pc
) >= 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
233 the args are still in the argument regs. 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 (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
== ZERO_REGNUM
266 || regno
== mips_regnum (current_gdbarch
)->fp_implementation_revision
);
270 mipsnbsd_cannot_store_register (int regno
)
272 return (regno
== 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
= 0;
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_deprecated_pc_in_sigtramp (gdbarch
, mipsnbsd_pc_in_sigtramp
);
350 set_gdbarch_get_longjmp_target (gdbarch
, mipsnbsd_get_longjmp_target
);
352 set_gdbarch_cannot_fetch_register (gdbarch
, mipsnbsd_cannot_fetch_register
);
353 set_gdbarch_cannot_store_register (gdbarch
, mipsnbsd_cannot_store_register
);
355 set_gdbarch_software_single_step (gdbarch
, mips_software_single_step
);
357 set_solib_svr4_fetch_link_map_offsets (gdbarch
,
358 gdbarch_ptr_bit (gdbarch
) == 32 ?
359 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets
:
360 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets
);
364 _initialize_mipsnbsd_tdep (void)
366 gdbarch_register_osabi (bfd_arch_mips
, 0, GDB_OSABI_NETBSD_ELF
,
369 deprecated_add_core_fns (&mipsnbsd_core_fns
);
370 deprecated_add_core_fns (&mipsnbsd_elfcore_fns
);