1 /* Target-dependent code for MIPS systems running NetBSD.
2 Copyright 2002 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"
32 #include "solib-svr4.h"
34 /* Conveniently, GDB uses the same register numbering as the
35 ptrace register structure used by NetBSD/mips. */
38 mipsnbsd_supply_reg (char *regs
, int regno
)
42 for (i
= 0; i
<= PC_REGNUM
; i
++)
44 if (regno
== i
|| regno
== -1)
46 if (CANNOT_FETCH_REGISTER (i
))
47 supply_register (i
, NULL
);
49 supply_register (i
, regs
+ (i
* MIPS_REGSIZE
));
55 mipsnbsd_fill_reg (char *regs
, int regno
)
59 for (i
= 0; i
<= PC_REGNUM
; i
++)
60 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
61 regcache_collect (i
, regs
+ (i
* MIPS_REGSIZE
));
65 mipsnbsd_supply_fpreg (char *fpregs
, int regno
)
69 for (i
= FP0_REGNUM
; i
<= FCRIR_REGNUM
; i
++)
71 if (regno
== i
|| regno
== -1)
73 if (CANNOT_FETCH_REGISTER (i
))
74 supply_register (i
, NULL
);
76 supply_register (i
, fpregs
+ ((i
- FP0_REGNUM
) * MIPS_REGSIZE
));
82 mipsnbsd_fill_fpreg (char *fpregs
, int regno
)
86 for (i
= FP0_REGNUM
; i
<= FCRCS_REGNUM
; i
++)
87 if ((regno
== i
|| regno
== -1) && ! CANNOT_STORE_REGISTER (i
))
88 regcache_collect (i
, fpregs
+ ((i
- FP0_REGNUM
) * MIPS_REGSIZE
));
92 fetch_core_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
97 /* We get everything from one section. */
101 regs
= core_reg_sect
;
102 fpregs
= core_reg_sect
+ SIZEOF_STRUCT_REG
;
104 /* Integer registers. */
105 mipsnbsd_supply_reg (regs
, -1);
107 /* Floating point registers. */
108 mipsnbsd_supply_fpreg (regs
, -1);
112 fetch_elfcore_registers (char *core_reg_sect
, unsigned core_reg_size
, int which
,
117 case 0: /* Integer registers. */
118 if (core_reg_size
!= SIZEOF_STRUCT_REG
)
119 warning ("Wrong size register set in core file.");
121 mipsnbsd_supply_reg (core_reg_sect
, -1);
124 case 2: /* Floating point registers. */
125 if (core_reg_size
!= SIZEOF_STRUCT_FPREG
)
126 warning ("Wrong size register set in core file.");
128 mipsnbsd_supply_fpreg (core_reg_sect
, -1);
132 /* Don't know what kind of register request this is; just ignore it. */
137 static struct core_fns mipsnbsd_core_fns
=
139 bfd_target_unknown_flavour
, /* core_flavour */
140 default_check_format
, /* check_format */
141 default_core_sniffer
, /* core_sniffer */
142 fetch_core_registers
, /* core_read_registers */
146 static struct core_fns mipsnbsd_elfcore_fns
=
148 bfd_target_elf_flavour
, /* core_flavour */
149 default_check_format
, /* check_format */
150 default_core_sniffer
, /* core_sniffer */
151 fetch_elfcore_registers
, /* core_read_registers */
155 /* Under NetBSD/mips, signal handler invocations can be identified by the
156 designated code sequence that is used to return from a signal handler.
157 In particular, the return address of a signal handler points to the
158 following code sequence:
161 li v0, 295 # __sigreturn14
164 Each instruction has a unique encoding, so we simply attempt to match
165 the instruction the PC is pointing to with any of the above instructions.
166 If there is a hit, we know the offset to the start of the designated
167 sequence and can then check whether we really are executing in the
168 signal trampoline. If not, -1 is returned, otherwise the offset from the
169 start of the return sequence is returned. */
171 #define RETCODE_NWORDS 3
172 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
174 static const unsigned char sigtramp_retcode_mipsel
[RETCODE_SIZE
] =
176 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
177 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
178 0x0c, 0x00, 0x00, 0x00, /* syscall */
181 static const unsigned char sigtramp_retcode_mipseb
[RETCODE_SIZE
] =
183 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
184 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
185 0x00, 0x00, 0x00, 0x0c, /* syscall */
189 mipsnbsd_sigtramp_offset (CORE_ADDR pc
)
191 const char *retcode
= TARGET_BYTE_ORDER
== BFD_ENDIAN_BIG
192 ? sigtramp_retcode_mipseb
: sigtramp_retcode_mipsel
;
193 unsigned char ret
[RETCODE_SIZE
], w
[4];
197 if (read_memory_nobpt (pc
, (char *) w
, sizeof (w
)) != 0)
200 for (i
= 0; i
< RETCODE_NWORDS
; i
++)
202 if (memcmp (w
, retcode
+ (i
* 4), 4) == 0)
205 if (i
== RETCODE_NWORDS
)
211 if (read_memory_nobpt (pc
, (char *) ret
, sizeof (ret
)) != 0)
214 if (memcmp (ret
, retcode
, RETCODE_SIZE
) == 0)
221 mipsnbsd_pc_in_sigtramp (CORE_ADDR pc
, char *func_name
)
223 return (nbsd_pc_in_sigtramp (pc
, func_name
)
224 || mipsnbsd_sigtramp_offset (pc
) >= 0);
227 /* Figure out where the longjmp will land. We expect that we have
228 just entered longjmp and haven't yet setup the stack frame, so
229 the args are still in the argument regs. A0_REGNUM points at the
230 jmp_buf structure from which we extract the PC that we will land
231 at. The PC is copied into *pc. This routine returns true on
234 #define NBSD_MIPS_JB_PC (2 * 4)
235 #define NBSD_MIPS_JB_ELEMENT_SIZE MIPS_REGSIZE
236 #define NBSD_MIPS_JB_OFFSET (NBSD_MIPS_JB_PC * \
237 NBSD_MIPS_JB_ELEMENT_SIZE)
240 mipsnbsd_get_longjmp_target (CORE_ADDR
*pc
)
245 buf
= alloca (NBSD_MIPS_JB_ELEMENT_SIZE
);
247 jb_addr
= read_register (A0_REGNUM
);
249 if (target_read_memory (jb_addr
+ NBSD_MIPS_JB_OFFSET
, buf
,
250 NBSD_MIPS_JB_ELEMENT_SIZE
))
253 *pc
= extract_address (buf
, NBSD_MIPS_JB_ELEMENT_SIZE
);
259 mipsnbsd_cannot_fetch_register (int regno
)
261 return (regno
>= FP_REGNUM
262 || regno
== ZERO_REGNUM
263 || regno
== FCRIR_REGNUM
);
267 mipsnbsd_cannot_store_register (int regno
)
269 return (regno
>= FP_REGNUM
270 || regno
== ZERO_REGNUM
271 || regno
== FCRIR_REGNUM
);
274 /* NetBSD/mips uses a slightly different link_map structure from the
275 other NetBSD platforms. */
276 static struct link_map_offsets
*
277 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
279 static struct link_map_offsets lmo
;
280 static struct link_map_offsets
*lmp
= NULL
;
286 lmo
.r_debug_size
= 16;
288 lmo
.r_map_offset
= 4;
291 lmo
.link_map_size
= 24;
293 lmo
.l_addr_offset
= 0;
296 lmo
.l_name_offset
= 8;
299 lmo
.l_next_offset
= 16;
302 lmo
.l_prev_offset
= 20;
309 static struct link_map_offsets
*
310 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets (void)
312 static struct link_map_offsets lmo
;
313 static struct link_map_offsets
*lmp
= NULL
;
319 lmo
.r_debug_size
= 32;
321 lmo
.r_map_offset
= 8;
324 lmo
.link_map_size
= 48;
326 lmo
.l_addr_offset
= 0;
329 lmo
.l_name_offset
= 16;
332 lmo
.l_next_offset
= 32;
335 lmo
.l_prev_offset
= 40;
343 mipsnbsd_init_abi (struct gdbarch_info info
,
344 struct gdbarch
*gdbarch
)
346 set_gdbarch_pc_in_sigtramp (gdbarch
, mipsnbsd_pc_in_sigtramp
);
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
, GDB_OSABI_NETBSD_ELF
,
367 add_core_fns (&mipsnbsd_core_fns
);
368 add_core_fns (&mipsnbsd_elfcore_fns
);