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_raw_collect (current_regcache
, i
,
64 regs
+ (i
* mips_isa_regsize (current_gdbarch
)));
68 mipsnbsd_supply_fpreg (char *fpregs
, int regno
)
73 i
<= mips_regnum (current_gdbarch
)->fp_implementation_revision
;
76 if (regno
== i
|| regno
== -1)
78 if (CANNOT_FETCH_REGISTER (i
))
79 regcache_raw_supply (current_regcache
, i
, NULL
);
81 regcache_raw_supply (current_regcache
, i
,
82 fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
88 mipsnbsd_fill_fpreg (char *fpregs
, int regno
)
92 for (i
= FP0_REGNUM
; i
<= mips_regnum (current_gdbarch
)->fp_control_status
;
94 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
95 regcache_raw_collect (current_regcache
, i
,
96 fpregs
+ ((i
- FP0_REGNUM
) * mips_isa_regsize (current_gdbarch
)));
100 fetch_core_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
105 /* We get everything from one section. */
109 regs
= core_reg_sect
;
110 fpregs
= core_reg_sect
+ SIZEOF_STRUCT_REG
;
112 /* Integer registers. */
113 mipsnbsd_supply_reg (regs
, -1);
115 /* Floating point registers. */
116 mipsnbsd_supply_fpreg (fpregs
, -1);
120 fetch_elfcore_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
125 case 0: /* Integer registers. */
126 if (core_reg_size
!= SIZEOF_STRUCT_REG
)
127 warning ("Wrong size register set in core file.");
129 mipsnbsd_supply_reg (core_reg_sect
, -1);
132 case 2: /* Floating point registers. */
133 if (core_reg_size
!= SIZEOF_STRUCT_FPREG
)
134 warning ("Wrong size register set in core file.");
136 mipsnbsd_supply_fpreg (core_reg_sect
, -1);
140 /* Don't know what kind of register request this is; just ignore it. */
145 static struct core_fns mipsnbsd_core_fns
=
147 bfd_target_unknown_flavour
, /* core_flavour */
148 default_check_format
, /* check_format */
149 default_core_sniffer
, /* core_sniffer */
150 fetch_core_registers
, /* core_read_registers */
154 static struct core_fns mipsnbsd_elfcore_fns
=
156 bfd_target_elf_flavour
, /* core_flavour */
157 default_check_format
, /* check_format */
158 default_core_sniffer
, /* core_sniffer */
159 fetch_elfcore_registers
, /* core_read_registers */
163 /* Under NetBSD/mips, signal handler invocations can be identified by the
164 designated code sequence that is used to return from a signal handler.
165 In particular, the return address of a signal handler points to the
166 following code sequence:
169 li v0, 295 # __sigreturn14
172 Each instruction has a unique encoding, so we simply attempt to match
173 the instruction the PC is pointing to with any of the above instructions.
174 If there is a hit, we know the offset to the start of the designated
175 sequence and can then check whether we really are executing in the
176 signal trampoline. If not, -1 is returned, otherwise the offset from the
177 start of the return sequence is returned. */
179 #define RETCODE_NWORDS 3
180 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
182 static const unsigned char sigtramp_retcode_mipsel
[RETCODE_SIZE
] =
184 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
185 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
186 0x0c, 0x00, 0x00, 0x00, /* syscall */
189 static const unsigned char sigtramp_retcode_mipseb
[RETCODE_SIZE
] =
191 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
192 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
193 0x00, 0x00, 0x00, 0x0c, /* syscall */
197 mipsnbsd_sigtramp_offset (CORE_ADDR pc
)
199 const char *retcode
= TARGET_BYTE_ORDER
== BFD_ENDIAN_BIG
200 ? sigtramp_retcode_mipseb
: sigtramp_retcode_mipsel
;
201 unsigned char ret
[RETCODE_SIZE
], w
[4];
205 if (deprecated_read_memory_nobpt (pc
, (char *) w
, sizeof (w
)) != 0)
208 for (i
= 0; i
< RETCODE_NWORDS
; i
++)
210 if (memcmp (w
, retcode
+ (i
* 4), 4) == 0)
213 if (i
== RETCODE_NWORDS
)
219 if (deprecated_read_memory_nobpt (pc
, (char *) ret
, sizeof (ret
)) != 0)
222 if (memcmp (ret
, retcode
, RETCODE_SIZE
) == 0)
228 /* Figure out where the longjmp will land. We expect that we have
229 just entered longjmp and haven't yet setup the stack frame, so
230 the args are still in the argument regs. A0_REGNUM points at the
231 jmp_buf structure from which we extract the PC that we will land
232 at. The PC is copied into *pc. This routine returns true on
235 #define NBSD_MIPS_JB_PC (2 * 4)
236 #define NBSD_MIPS_JB_ELEMENT_SIZE mips_isa_regsize (current_gdbarch)
237 #define NBSD_MIPS_JB_OFFSET (NBSD_MIPS_JB_PC * \
238 NBSD_MIPS_JB_ELEMENT_SIZE)
241 mipsnbsd_get_longjmp_target (CORE_ADDR
*pc
)
246 buf
= alloca (NBSD_MIPS_JB_ELEMENT_SIZE
);
248 jb_addr
= read_register (A0_REGNUM
);
250 if (target_read_memory (jb_addr
+ NBSD_MIPS_JB_OFFSET
, buf
,
251 NBSD_MIPS_JB_ELEMENT_SIZE
))
254 *pc
= extract_unsigned_integer (buf
, NBSD_MIPS_JB_ELEMENT_SIZE
);
260 mipsnbsd_cannot_fetch_register (int regno
)
262 return (regno
== ZERO_REGNUM
263 || regno
== mips_regnum (current_gdbarch
)->fp_implementation_revision
);
267 mipsnbsd_cannot_store_register (int regno
)
269 return (regno
== ZERO_REGNUM
270 || regno
== mips_regnum (current_gdbarch
)->fp_implementation_revision
);
273 /* NetBSD/mips uses a slightly different link_map structure from the
274 other NetBSD platforms. */
275 static struct link_map_offsets
*
276 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
278 static struct link_map_offsets lmo
;
279 static struct link_map_offsets
*lmp
= NULL
;
285 lmo
.r_debug_size
= 16;
287 lmo
.r_map_offset
= 4;
290 lmo
.link_map_size
= 24;
292 lmo
.l_addr_offset
= 0;
295 lmo
.l_name_offset
= 8;
298 lmo
.l_next_offset
= 16;
301 lmo
.l_prev_offset
= 20;
308 static struct link_map_offsets
*
309 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets (void)
311 static struct link_map_offsets lmo
;
312 static struct link_map_offsets
*lmp
= NULL
;
318 lmo
.r_debug_size
= 32;
320 lmo
.r_map_offset
= 8;
323 lmo
.link_map_size
= 48;
325 lmo
.l_addr_offset
= 0;
328 lmo
.l_name_offset
= 16;
331 lmo
.l_next_offset
= 32;
334 lmo
.l_prev_offset
= 40;
342 mipsnbsd_init_abi (struct gdbarch_info info
,
343 struct gdbarch
*gdbarch
)
345 set_gdbarch_get_longjmp_target (gdbarch
, mipsnbsd_get_longjmp_target
);
347 set_gdbarch_cannot_fetch_register (gdbarch
, mipsnbsd_cannot_fetch_register
);
348 set_gdbarch_cannot_store_register (gdbarch
, mipsnbsd_cannot_store_register
);
350 set_gdbarch_software_single_step (gdbarch
, mips_software_single_step
);
352 set_solib_svr4_fetch_link_map_offsets (gdbarch
,
353 gdbarch_ptr_bit (gdbarch
) == 32 ?
354 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets
:
355 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets
);
359 _initialize_mipsnbsd_tdep (void)
361 gdbarch_register_osabi (bfd_arch_mips
, 0, GDB_OSABI_NETBSD_ELF
,
364 deprecated_add_core_fns (&mipsnbsd_core_fns
);
365 deprecated_add_core_fns (&mipsnbsd_elfcore_fns
);