1 /* Target-dependent code for MIPS systems running NetBSD.
2 Copyright 2002, 2003 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 (current_gdbarch)));
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 (current_gdbarch)));
65 mipsnbsd_supply_fpreg (char *fpregs, int regno)
70 i <= mips_regnum (current_gdbarch)->fp_implementation_revision;
73 if (regno == i || regno == -1)
75 if (CANNOT_FETCH_REGISTER (i))
76 supply_register (i, NULL);
78 supply_register (i, fpregs + ((i - FP0_REGNUM) * mips_regsize (current_gdbarch)));
84 mipsnbsd_fill_fpreg (char *fpregs, int regno)
88 for (i = FP0_REGNUM; i <= mips_regnum (current_gdbarch)->fp_control_status;
90 if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
91 regcache_collect (i, fpregs + ((i - FP0_REGNUM) * mips_regsize (current_gdbarch)));
95 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
100 /* We get everything from one section. */
104 regs = core_reg_sect;
105 fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
107 /* Integer registers. */
108 mipsnbsd_supply_reg (regs, -1);
110 /* Floating point registers. */
111 mipsnbsd_supply_fpreg (fpregs, -1);
115 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
120 case 0: /* Integer registers. */
121 if (core_reg_size != SIZEOF_STRUCT_REG)
122 warning ("Wrong size register set in core file.");
124 mipsnbsd_supply_reg (core_reg_sect, -1);
127 case 2: /* Floating point registers. */
128 if (core_reg_size != SIZEOF_STRUCT_FPREG)
129 warning ("Wrong size register set in core file.");
131 mipsnbsd_supply_fpreg (core_reg_sect, -1);
135 /* Don't know what kind of register request this is; just ignore it. */
140 static struct core_fns mipsnbsd_core_fns =
142 bfd_target_unknown_flavour, /* core_flavour */
143 default_check_format, /* check_format */
144 default_core_sniffer, /* core_sniffer */
145 fetch_core_registers, /* core_read_registers */
149 static struct core_fns mipsnbsd_elfcore_fns =
151 bfd_target_elf_flavour, /* core_flavour */
152 default_check_format, /* check_format */
153 default_core_sniffer, /* core_sniffer */
154 fetch_elfcore_registers, /* core_read_registers */
158 /* Under NetBSD/mips, signal handler invocations can be identified by the
159 designated code sequence that is used to return from a signal handler.
160 In particular, the return address of a signal handler points to the
161 following code sequence:
164 li v0, 295 # __sigreturn14
167 Each instruction has a unique encoding, so we simply attempt to match
168 the instruction the PC is pointing to with any of the above instructions.
169 If there is a hit, we know the offset to the start of the designated
170 sequence and can then check whether we really are executing in the
171 signal trampoline. If not, -1 is returned, otherwise the offset from the
172 start of the return sequence is returned. */
174 #define RETCODE_NWORDS 3
175 #define RETCODE_SIZE (RETCODE_NWORDS * 4)
177 static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] =
179 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */
180 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */
181 0x0c, 0x00, 0x00, 0x00, /* syscall */
184 static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] =
186 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */
187 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */
188 0x00, 0x00, 0x00, 0x0c, /* syscall */
192 mipsnbsd_sigtramp_offset (CORE_ADDR pc)
194 const char *retcode = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
195 ? sigtramp_retcode_mipseb : sigtramp_retcode_mipsel;
196 unsigned char ret[RETCODE_SIZE], w[4];
200 if (read_memory_nobpt (pc, (char *) w, sizeof (w)) != 0)
203 for (i = 0; i < RETCODE_NWORDS; i++)
205 if (memcmp (w, retcode + (i * 4), 4) == 0)
208 if (i == RETCODE_NWORDS)
214 if (read_memory_nobpt (pc, (char *) ret, sizeof (ret)) != 0)
217 if (memcmp (ret, retcode, RETCODE_SIZE) == 0)
224 mipsnbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
226 return (nbsd_pc_in_sigtramp (pc, func_name)
227 || mipsnbsd_sigtramp_offset (pc) >= 0);
230 /* Figure out where the longjmp will land. We expect that we have
231 just entered longjmp and haven't yet setup the stack frame, so
232 the args are still in the argument regs. A0_REGNUM points at the
233 jmp_buf structure from which we extract the PC that we will land
234 at. The PC is copied into *pc. This routine returns true on
237 #define NBSD_MIPS_JB_PC (2 * 4)
238 #define NBSD_MIPS_JB_ELEMENT_SIZE mips_regsize (current_gdbarch)
239 #define NBSD_MIPS_JB_OFFSET (NBSD_MIPS_JB_PC * \
240 NBSD_MIPS_JB_ELEMENT_SIZE)
243 mipsnbsd_get_longjmp_target (CORE_ADDR *pc)
248 buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE);
250 jb_addr = read_register (A0_REGNUM);
252 if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET, buf,
253 NBSD_MIPS_JB_ELEMENT_SIZE))
256 *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE);
262 mipsnbsd_cannot_fetch_register (int regno)
264 return (regno == ZERO_REGNUM
265 || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
269 mipsnbsd_cannot_store_register (int regno)
271 return (regno == ZERO_REGNUM
272 || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
275 /* NetBSD/mips uses a slightly different link_map structure from the
276 other NetBSD platforms. */
277 static struct link_map_offsets *
278 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
280 static struct link_map_offsets lmo;
281 static struct link_map_offsets *lmp = NULL;
287 lmo.r_debug_size = 16;
289 lmo.r_map_offset = 4;
292 lmo.link_map_size = 24;
294 lmo.l_addr_offset = 0;
297 lmo.l_name_offset = 8;
300 lmo.l_next_offset = 16;
303 lmo.l_prev_offset = 20;
310 static struct link_map_offsets *
311 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets (void)
313 static struct link_map_offsets lmo;
314 static struct link_map_offsets *lmp = NULL;
320 lmo.r_debug_size = 32;
322 lmo.r_map_offset = 8;
325 lmo.link_map_size = 48;
327 lmo.l_addr_offset = 0;
330 lmo.l_name_offset = 16;
333 lmo.l_next_offset = 32;
336 lmo.l_prev_offset = 40;
344 mipsnbsd_init_abi (struct gdbarch_info info,
345 struct gdbarch *gdbarch)
347 set_gdbarch_pc_in_sigtramp (gdbarch, mipsnbsd_pc_in_sigtramp);
349 set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target);
351 set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register);
352 set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register);
354 set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
356 set_solib_svr4_fetch_link_map_offsets (gdbarch,
357 gdbarch_ptr_bit (gdbarch) == 32 ?
358 mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets :
359 mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets);
363 _initialize_mipsnbsd_tdep (void)
365 gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF,
368 add_core_fns (&mipsnbsd_core_fns);
369 add_core_fns (&mipsnbsd_elfcore_fns);