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 regcache_raw_supply (current_regcache
, i
, NULL
);
50 regcache_raw_supply (current_regcache
, i
,
51 regs
+ (i
* mips_isa_regsize (current_gdbarch
)));
57 mipsnbsd_fill_reg (char *regs
, int regno
)
61 for (i
= 0; i
<= PC_REGNUM
; i
++)
62 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
63 regcache_collect (i
, regs
+ (i
* mips_isa_regsize (current_gdbarch
)));
67 mipsnbsd_supply_fpreg (char *fpregs
, int regno
)
72 i
<= mips_regnum (current_gdbarch
)->fp_implementation_revision
;
75 if (regno
== i
|| regno
== -1)
77 if (CANNOT_FETCH_REGISTER (i
))
78 regcache_raw_supply (current_regcache
, i
, NULL
);
80 regcache_raw_supply (current_regcache
, i
,
81 fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
87 mipsnbsd_fill_fpreg (char *fpregs
, int regno
)
91 for (i
= FP0_REGNUM
; i
<= mips_regnum (current_gdbarch
)->fp_control_status
;
93 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
94 regcache_collect (i
, fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
98 fetch_core_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
103 /* We get everything from one section. */
107 regs
= core_reg_sect
;
108 fpregs
= core_reg_sect
+ SIZEOF_STRUCT_REG
;
110 /* Integer registers. */
111 mipsnbsd_supply_reg (regs
, -1);
113 /* Floating point registers. */
114 mipsnbsd_supply_fpreg (fpregs
, -1);
118 fetch_elfcore_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
123 case 0: /* Integer registers. */
124 if (core_reg_size
!= SIZEOF_STRUCT_REG
)
125 warning ("Wrong size register set in core file.");
127 mipsnbsd_supply_reg (core_reg_sect
, -1);
130 case 2: /* Floating point registers. */
131 if (core_reg_size
!= SIZEOF_STRUCT_FPREG
)
132 warning ("Wrong size register set in core file.");
134 mipsnbsd_supply_fpreg (core_reg_sect
, -1);
138 /* Don't know what kind of register request this is; just ignore it. */
143 static struct core_fns mipsnbsd_core_fns
=
145 bfd_target_unknown_flavour
, /* core_flavour */
146 default_check_format
, /* check_format */
147 default_core_sniffer
, /* core_sniffer */
148 fetch_core_registers
, /* core_read_registers */
152 static struct core_fns mipsnbsd_elfcore_fns
=
154 bfd_target_elf_flavour
, /* core_flavour */
155 default_check_format
, /* check_format */
156 default_core_sniffer
, /* core_sniffer */
157 fetch_elfcore_registers
, /* core_read_registers */
161 /* Under NetBSD/mips, signal handler invocations can be identified by the
162 designated code sequence that is used to return from a signal handler.
163 In particular, the return address of a signal handler points to the
164 following code sequence:
167 li v0, 295 # __sigreturn14
170 Each instruction has a unique encoding, so we simply attempt to match
171 the instruction the PC is pointing to with any of the above instructions.
172 If there is a hit, we know the offset to the start of the designated
173 sequence and can then check whether we really are executing in the
174 signal trampoline. If not, -1 is returned, otherwise the offset from the
175 start of the return sequence is returned. */
177 #define RETCODE_NWORDS 3
178 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
180 static const unsigned char sigtramp_retcode_mipsel
[RETCODE_SIZE
] =
182 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
183 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
184 0x0c, 0x00, 0x00, 0x00, /* syscall */
187 static const unsigned char sigtramp_retcode_mipseb
[RETCODE_SIZE
] =
189 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
190 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
191 0x00, 0x00, 0x00, 0x0c, /* syscall */
195 mipsnbsd_sigtramp_offset (CORE_ADDR pc
)
197 const char *retcode
= TARGET_BYTE_ORDER
== BFD_ENDIAN_BIG
198 ? sigtramp_retcode_mipseb
: sigtramp_retcode_mipsel
;
199 unsigned char ret
[RETCODE_SIZE
], w
[4];
203 if (deprecated_read_memory_nobpt (pc
, (char *) w
, sizeof (w
)) != 0)
206 for (i
= 0; i
< RETCODE_NWORDS
; i
++)
208 if (memcmp (w
, retcode
+ (i
* 4), 4) == 0)
211 if (i
== RETCODE_NWORDS
)
217 if (deprecated_read_memory_nobpt (pc
, (char *) ret
, sizeof (ret
)) != 0)
220 if (memcmp (ret
, retcode
, RETCODE_SIZE
) == 0)
226 /* Figure out where the longjmp will land. We expect that we have
227 just entered longjmp and haven't yet setup the stack frame, so
228 the args are still in the argument regs. A0_REGNUM points at the
229 jmp_buf structure from which we extract the PC that we will land
230 at. The PC is copied into *pc. This routine returns true on
233 #define NBSD_MIPS_JB_PC (2 * 4)
234 #define NBSD_MIPS_JB_ELEMENT_SIZE mips_isa_regsize (current_gdbarch)
235 #define NBSD_MIPS_JB_OFFSET (NBSD_MIPS_JB_PC * \
236 NBSD_MIPS_JB_ELEMENT_SIZE)
239 mipsnbsd_get_longjmp_target (CORE_ADDR
*pc
)
244 buf
= alloca (NBSD_MIPS_JB_ELEMENT_SIZE
);
246 jb_addr
= read_register (A0_REGNUM
);
248 if (target_read_memory (jb_addr
+ NBSD_MIPS_JB_OFFSET
, buf
,
249 NBSD_MIPS_JB_ELEMENT_SIZE
))
252 *pc
= extract_unsigned_integer (buf
, NBSD_MIPS_JB_ELEMENT_SIZE
);
258 mipsnbsd_cannot_fetch_register (int regno
)
260 return (regno
== ZERO_REGNUM
261 || regno
== mips_regnum (current_gdbarch
)->fp_implementation_revision
);
265 mipsnbsd_cannot_store_register (int regno
)
267 return (regno
== ZERO_REGNUM
268 || regno
== mips_regnum (current_gdbarch
)->fp_implementation_revision
);
271 /* NetBSD/mips uses a slightly different link_map structure from the
272 other NetBSD platforms. */
273 static struct link_map_offsets
*
274 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
276 static struct link_map_offsets lmo
;
277 static struct link_map_offsets
*lmp
= NULL
;
283 lmo
.r_debug_size
= 16;
285 lmo
.r_map_offset
= 4;
288 lmo
.link_map_size
= 24;
290 lmo
.l_addr_offset
= 0;
293 lmo
.l_name_offset
= 8;
296 lmo
.l_next_offset
= 16;
299 lmo
.l_prev_offset
= 20;
306 static struct link_map_offsets
*
307 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets (void)
309 static struct link_map_offsets lmo
;
310 static struct link_map_offsets
*lmp
= NULL
;
316 lmo
.r_debug_size
= 32;
318 lmo
.r_map_offset
= 8;
321 lmo
.link_map_size
= 48;
323 lmo
.l_addr_offset
= 0;
326 lmo
.l_name_offset
= 16;
329 lmo
.l_next_offset
= 32;
332 lmo
.l_prev_offset
= 40;
340 mipsnbsd_init_abi (struct gdbarch_info info
,
341 struct gdbarch
*gdbarch
)
343 set_gdbarch_get_longjmp_target (gdbarch
, mipsnbsd_get_longjmp_target
);
345 set_gdbarch_cannot_fetch_register (gdbarch
, mipsnbsd_cannot_fetch_register
);
346 set_gdbarch_cannot_store_register (gdbarch
, mipsnbsd_cannot_store_register
);
348 set_gdbarch_software_single_step (gdbarch
, mips_software_single_step
);
350 set_solib_svr4_fetch_link_map_offsets (gdbarch
,
351 gdbarch_ptr_bit (gdbarch
) == 32 ?
352 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets
:
353 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets
);
357 _initialize_mipsnbsd_tdep (void)
359 gdbarch_register_osabi (bfd_arch_mips
, 0, GDB_OSABI_NETBSD_ELF
,
362 deprecated_add_core_fns (&mipsnbsd_core_fns
);
363 deprecated_add_core_fns (&mipsnbsd_elfcore_fns
);