From: Jason Thorpe Date: Tue, 21 May 2002 15:58:41 +0000 (+0000) Subject: * NEWS: Note new MIPS NetBSD native configuration. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=458882614b57606f65ae56e2f491a8b66aacdb6f;p=binutils-gdb.git * NEWS: Note new MIPS NetBSD native configuration. * configure.host (mips*-*-netbsd*): New host. * configure.tgt (mips*-*-netbsd*): New target. * mipsnbsd-nat.c: New file. * mipsnbsd-tdep.c: New file. * mipsnbsd-tdep.h: New file. * config/mips/nbsd.mh: New file. * config/mips/nbsd.mt: New file. * config/mips/nm-nbsd.h: New file. * config/mips/tm-nbsd.h: New file. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 57a965ff598..de8e2e73849 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2002-05-21 Jason Thorpe + + * NEWS: Note new MIPS NetBSD native configuration. + * configure.host (mips*-*-netbsd*): New host. + * configure.tgt (mips*-*-netbsd*): New target. + * mipsnbsd-nat.c: New file. + * mipsnbsd-tdep.c: New file. + * mipsnbsd-tdep.h: New file. + * config/mips/nbsd.mh: New file. + * config/mips/nbsd.mt: New file. + * config/mips/nm-nbsd.h: New file. + * config/mips/tm-nbsd.h: New file. + 2002-05-21 Jason Thorpe * Makefile.in (SFILES): Add osabi.c. diff --git a/gdb/NEWS b/gdb/NEWS index 191c8c9f679..d9e49c0fa0b 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -37,6 +37,7 @@ Atmel AVR avr*-*-* Alpha NetBSD alpha*-*-netbsd* SH NetBSD sh*-*-netbsdelf* +MIPS NetBSD mips*-*-netbsd* * OBSOLETE configurations and files diff --git a/gdb/config/mips/nbsd.mh b/gdb/config/mips/nbsd.mh new file mode 100644 index 00000000000..4556fc60b27 --- /dev/null +++ b/gdb/config/mips/nbsd.mh @@ -0,0 +1,4 @@ +# Host: MIPS running NetBSD +NAT_CLIBS= +NATDEPFILES= infptrace.o inftarg.o fork-child.o mipsnbsd-nat.o +NAT_FILE= nm-nbsd.h diff --git a/gdb/config/mips/nbsd.mt b/gdb/config/mips/nbsd.mt new file mode 100644 index 00000000000..de529166c56 --- /dev/null +++ b/gdb/config/mips/nbsd.mt @@ -0,0 +1,6 @@ +# Target: MIPS running NetBSD +TDEPFILES= mips-tdep.o mipsnbsd-tdep.o corelow.o solib.o solib-svr4.o +TM_FILE= tm-nbsd.h + +SIM_OBS = remote-sim.o +SIM = ../sim/mips/libsim.a diff --git a/gdb/config/mips/nm-nbsd.h b/gdb/config/mips/nm-nbsd.h new file mode 100644 index 00000000000..67628c2fa97 --- /dev/null +++ b/gdb/config/mips/nm-nbsd.h @@ -0,0 +1,28 @@ +/* Native-dependent definitions for NetBSD/mips. + Copyright 2002 Free Software Foundation, Inc. + Contributed by Wasabi Systems, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef NM_NBSD_H +#define NM_NBSD_H + +/* Get generic NetBSD native definitions. */ +#include "config/nm-nbsd.h" + +#endif /* NM_NBSD_H */ diff --git a/gdb/config/mips/tm-nbsd.h b/gdb/config/mips/tm-nbsd.h new file mode 100644 index 00000000000..fc7448665e1 --- /dev/null +++ b/gdb/config/mips/tm-nbsd.h @@ -0,0 +1,45 @@ +/* Target-dependent definitions for NetBSD/mips. + Copyright 2002 Free Software Foundation, Inc. + Contributed by Wasabi Systems, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef TM_NBSD_H +#define TM_NBSD_H + +/* Saved Pc. Get it from sigcontext if within sigtramp. */ +#define SIGCONTEXT_PC_OFFSET 8 + +#include "mips/tm-mips.h" +#include "solib.h" + +/* There's an E_MIPS_ABI_O32 flag in e_flags, but we don't use it - in + fact, using it may violate the o32 ABI. */ + +#define MIPS_DEFAULT_ABI MIPS_ABI_O32 + +/* We don't want to inherit tm-mips.h's shared library trampoline code. */ +#undef IN_SOLIB_CALL_TRAMPOLINE +#undef IN_SOLIB_RETURN_TRAMPOLINE +#undef SKIP_TRAMPOLINE_CODE +#undef IGNORE_HELPER_CALL + +/* XXX undef a bunch of stuff we want to use multi-arch */ +#undef IN_SIGTRAMP + +#endif /* TM_NBSD_H */ diff --git a/gdb/configure.host b/gdb/configure.host index 511ea76f275..c8135288f5c 100644 --- a/gdb/configure.host +++ b/gdb/configure.host @@ -118,6 +118,7 @@ mips-sgi-irix5*) gdb_host=irix5 ;; mips-sgi-irix6*) gdb_host=irix6 ;; mips-sony-*) gdb_host=news-mips ;; mips*-*-linux*) gdb_host=linux ;; +mips*-*-netbsd*) gdb_host=nbsd ;; mips-*-mach3*) gdb_host=mipsm3 ;; mips-*-sysv4*) gdb_host=mipsv4 ;; mips-*-sysv*) gdb_host=riscos ;; diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 94dd8a63764..259bc0370e3 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -201,6 +201,7 @@ mips*-sony-*) gdb_target=bigmips ;; mips*-*-linux*) gdb_target=linux build_gdbserver=yes ;; +mips*-*-netbsd*) gdb_target=nbsd ;; mips*-*-mach3*) gdb_target=mipsm3 ;; mips*-*-sysv4*) gdb_target=mipsv4 ;; mips*-*-sysv*) gdb_target=bigmips ;; diff --git a/gdb/mipsnbsd-nat.c b/gdb/mipsnbsd-nat.c new file mode 100644 index 00000000000..16521f67617 --- /dev/null +++ b/gdb/mipsnbsd-nat.c @@ -0,0 +1,101 @@ +/* Native-dependent code for MIPS systems running NetBSD. + Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "inferior.h" +#include "regcache.h" + +#include "mipsnbsd-tdep.h" + +#include +#include +#include + +/* Determine if PT_GETREGS fetches this register. */ +static int +getregs_supplies (int regno) +{ + return ((regno) >= ZERO_REGNUM && (regno) <= PC_REGNUM); +} + +void +fetch_inferior_registers (int regno) +{ + if (regno == -1 || getregs_supplies (regno)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_ARG3_TYPE) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + mipsnbsd_supply_reg ((char *) ®s, regno); + if (regno != -1) + return; + } + + if (regno == -1 || regno >= FP0_REGNUM) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), + (PTRACE_ARG3_TYPE) &fpregs, 0) == -1) + perror_with_name ("Couldn't get floating point status"); + + mipsnbsd_supply_fpreg ((char *) &fpregs, regno); + } +} + +void +store_inferior_registers (int regno) +{ + if (regno == -1 || getregs_supplies (regno)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, PIDGET (inferior_ptid), + (PTRACE_ARG3_TYPE) ®s, 0) == -1) + perror_with_name ("Couldn't get registers"); + + mipsnbsd_fill_reg ((char *) ®s, regno); + + if (ptrace (PT_SETREGS, PIDGET (inferior_ptid), + (PTRACE_ARG3_TYPE) ®s, 0) == -1) + perror_with_name ("Couldn't write registers"); + + if (regno != -1) + return; + } + + if (regno == -1 || regno >= FP0_REGNUM) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, PIDGET (inferior_ptid), + (PTRACE_ARG3_TYPE) &fpregs, 0) == -1) + perror_with_name ("Couldn't get floating point status"); + + mipsnbsd_fill_fpreg ((char *) &fpregs, regno); + + if (ptrace (PT_SETFPREGS, PIDGET (inferior_ptid), + (PTRACE_ARG3_TYPE) &fpregs, 0) == -1) + perror_with_name ("Couldn't write floating point status"); + } +} diff --git a/gdb/mipsnbsd-tdep.c b/gdb/mipsnbsd-tdep.c new file mode 100644 index 00000000000..029ae6f28bc --- /dev/null +++ b/gdb/mipsnbsd-tdep.c @@ -0,0 +1,367 @@ +/* Target-dependent code for MIPS systems running NetBSD. + Copyright 2002 Free Software Foundation, Inc. + Contributed by Wasabi Systems, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "defs.h" +#include "gdbcore.h" +#include "regcache.h" +#include "target.h" +#include "value.h" +#include "osabi.h" + +#include "mipsnbsd-tdep.h" + +#include "solib-svr4.h" + +/* Conveniently, GDB uses the same register numbering as the + ptrace register structure used by NetBSD/mips. */ + +void +mipsnbsd_supply_reg (char *regs, int regno) +{ + int i; + + for (i = 0; i <= PC_REGNUM; i++) + { + if (regno == i || regno == -1) + { + if (CANNOT_FETCH_REGISTER (i)) + supply_register (i, NULL); + else + supply_register (i, regs + (i * MIPS_REGSIZE)); + } + } +} + +void +mipsnbsd_fill_reg (char *regs, int regno) +{ + int i; + + for (i = 0; i <= PC_REGNUM; i++) + if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i)) + regcache_collect (i, regs + (i * MIPS_REGSIZE)); +} + +void +mipsnbsd_supply_fpreg (char *fpregs, int regno) +{ + int i; + + for (i = FP0_REGNUM; i <= FCRIR_REGNUM; i++) + { + if (regno == i || regno == -1) + { + if (CANNOT_FETCH_REGISTER (i)) + supply_register (i, NULL); + else + supply_register (i, fpregs + ((i - FP0_REGNUM) * MIPS_REGSIZE)); + } + } +} + +void +mipsnbsd_fill_fpreg (char *fpregs, int regno) +{ + int i; + + for (i = FP0_REGNUM; i <= FCRCS_REGNUM; i++) + if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i)) + regcache_collect (i, fpregs + ((i - FP0_REGNUM) * MIPS_REGSIZE)); +} + +static void +fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, + CORE_ADDR ignore) +{ + char *regs, *fpregs; + + /* We get everything from one section. */ + if (which != 0) + return; + + regs = core_reg_sect; + fpregs = core_reg_sect + SIZEOF_STRUCT_REG; + + /* Integer registers. */ + mipsnbsd_supply_reg (regs, -1); + + /* Floating point registers. */ + mipsnbsd_supply_fpreg (regs, -1); +} + +static void +fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which, + CORE_ADDR ignore) +{ + switch (which) + { + case 0: /* Integer registers. */ + if (core_reg_size != SIZEOF_STRUCT_REG) + warning ("Wrong size register set in core file."); + else + mipsnbsd_supply_reg (core_reg_sect, -1); + break; + + case 2: /* Floating point registers. */ + if (core_reg_size != SIZEOF_STRUCT_FPREG) + warning ("Wrong size register set in core file."); + else + mipsnbsd_supply_fpreg (core_reg_sect, -1); + break; + + default: + /* Don't know what kind of register request this is; just ignore it. */ + break; + } +} + +static struct core_fns mipsnbsd_core_fns = +{ + bfd_target_unknown_flavour, /* core_flavour */ + default_check_format, /* check_format */ + default_core_sniffer, /* core_sniffer */ + fetch_core_registers, /* core_read_registers */ + NULL /* next */ +}; + +static struct core_fns mipsnbsd_elfcore_fns = +{ + bfd_target_elf_flavour, /* core_flavour */ + default_check_format, /* check_format */ + default_core_sniffer, /* core_sniffer */ + fetch_elfcore_registers, /* core_read_registers */ + NULL /* next */ +}; + +/* Under NetBSD/mips, signal handler invocations can be identified by the + designated code sequence that is used to return from a signal handler. + In particular, the return address of a signal handler points to the + following code sequence: + + addu a0, sp, 16 + li v0, 295 # __sigreturn14 + syscall + + Each instruction has a unique encoding, so we simply attempt to match + the instruction the PC is pointing to with any of the above instructions. + If there is a hit, we know the offset to the start of the designated + sequence and can then check whether we really are executing in the + signal trampoline. If not, -1 is returned, otherwise the offset from the + start of the return sequence is returned. */ + +#define RETCODE_NWORDS 3 +#define RETCODE_SIZE (RETCODE_NWORDS * 4) + +static const unsigned char sigtramp_retcode_mipsel[RETCODE_SIZE] = +{ + 0x10, 0x00, 0xa4, 0x27, /* addu a0, sp, 16 */ + 0x27, 0x01, 0x02, 0x24, /* li v0, 295 */ + 0x0c, 0x00, 0x00, 0x00, /* syscall */ +}; + +static const unsigned char sigtramp_retcode_mipseb[RETCODE_SIZE] = +{ + 0x27, 0xa4, 0x00, 0x10, /* addu a0, sp, 16 */ + 0x24, 0x02, 0x01, 0x27, /* li v0, 295 */ + 0x00, 0x00, 0x00, 0x0c, /* syscall */ +}; + +static LONGEST +mipsnbsd_sigtramp_offset (CORE_ADDR pc) +{ + const char *retcode = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG + ? sigtramp_retcode_mipseb : sigtramp_retcode_mipsel; + unsigned char ret[RETCODE_SIZE], w[4]; + LONGEST off; + int i; + + if (read_memory_nobpt (pc, (char *) w, sizeof (w)) != 0) + return -1; + + for (i = 0; i < RETCODE_NWORDS; i++) + { + if (memcmp (w, retcode + (i * 4), 4) == 0) + break; + } + if (i == RETCODE_NWORDS) + return -1; + + off = i * 4; + pc -= off; + + if (read_memory_nobpt (pc, (char *) ret, sizeof (ret)) != 0) + return -1; + + if (memcmp (ret, retcode, RETCODE_SIZE) == 0) + return off; + + return -1; +} + +static int +mipsnbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name) +{ + return (mipsnbsd_sigtramp_offset (pc) >= 0); +} + +/* Figure out where the longjmp will land. We expect that we have + just entered longjmp and haven't yet setup the stack frame, so + the args are still in the argument regs. A0_REGNUM points at the + jmp_buf structure from which we extract the PC that we will land + at. The PC is copied into *pc. This routine returns true on + success. */ + +#define NBSD_MIPS_JB_PC (2 * 4) +#define NBSD_MIPS_JB_ELEMENT_SIZE MIPS_REGSIZE +#define NBSD_MIPS_JB_OFFSET (NBSD_MIPS_JB_PC * \ + NBSD_MIPS_JB_ELEMENT_SIZE) + +static int +mipsnbsd_get_longjmp_target (CORE_ADDR *pc) +{ + CORE_ADDR jb_addr; + char *buf; + + buf = alloca (NBSD_MIPS_JB_ELEMENT_SIZE); + + jb_addr = read_register (A0_REGNUM); + + if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET, buf, + NBSD_MIPS_JB_ELEMENT_SIZE)) + return 0; + + *pc = extract_address (buf, NBSD_MIPS_JB_ELEMENT_SIZE); + + return 1; +} + +static int +mipsnbsd_cannot_fetch_register (int regno) +{ + return (regno >= FP_REGNUM + || regno == ZERO_REGNUM + || regno == FCRIR_REGNUM); +} + +static int +mipsnbsd_cannot_store_register (int regno) +{ + return (regno >= FP_REGNUM + || regno == ZERO_REGNUM + || regno == FCRIR_REGNUM); +} + +/* NetBSD/mips uses a slightly different link_map structure from the + other NetBSD platforms. */ +static struct link_map_offsets * +mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets (void) +{ + static struct link_map_offsets lmo; + static struct link_map_offsets *lmp = NULL; + + if (lmp == NULL) + { + lmp = &lmo; + + lmo.r_debug_size = 16; + + lmo.r_map_offset = 4; + lmo.r_map_size = 4; + + lmo.link_map_size = 24; + + lmo.l_addr_offset = 0; + lmo.l_addr_size = 4; + + lmo.l_name_offset = 8; + lmo.l_name_size = 4; + + lmo.l_next_offset = 16; + lmo.l_next_size = 4; + + lmo.l_prev_offset = 20; + lmo.l_prev_size = 4; + } + + return lmp; +} + +static struct link_map_offsets * +mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets (void) +{ + static struct link_map_offsets lmo; + static struct link_map_offsets *lmp = NULL; + + if (lmp == NULL) + { + lmp = &lmo; + + lmo.r_debug_size = 32; + + lmo.r_map_offset = 8; + lmo.r_map_size = 8; + + lmo.link_map_size = 48; + + lmo.l_addr_offset = 0; + lmo.l_addr_size = 8; + + lmo.l_name_offset = 16; + lmo.l_name_size = 8; + + lmo.l_next_offset = 32; + lmo.l_next_size = 8; + + lmo.l_prev_offset = 40; + lmo.l_prev_size = 8; + } + + return lmp; +} + +static void +mipsnbsd_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + set_gdbarch_pc_in_sigtramp (gdbarch, mipsnbsd_pc_in_sigtramp); + + set_gdbarch_get_longjmp_target (gdbarch, mipsnbsd_get_longjmp_target); + + set_gdbarch_cannot_fetch_register (gdbarch, mipsnbsd_cannot_fetch_register); + set_gdbarch_cannot_store_register (gdbarch, mipsnbsd_cannot_store_register); + + set_gdbarch_software_single_step (gdbarch, mips_software_single_step); + + set_solib_svr4_fetch_link_map_offsets (gdbarch, + gdbarch_ptr_bit (gdbarch) == 32 ? + mipsnbsd_ilp32_solib_svr4_fetch_link_map_offsets : + mipsnbsd_lp64_solib_svr4_fetch_link_map_offsets); +} + +void +_initialize_mipsnbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_mips, GDB_OSABI_NETBSD_ELF, + mipsnbsd_init_abi); + + add_core_fns (&mipsnbsd_core_fns); + add_core_fns (&mipsnbsd_elfcore_fns); +} diff --git a/gdb/mipsnbsd-tdep.h b/gdb/mipsnbsd-tdep.h new file mode 100644 index 00000000000..6e9f50ed7c2 --- /dev/null +++ b/gdb/mipsnbsd-tdep.h @@ -0,0 +1,33 @@ +/* Common target dependent code for GDB on MIPS systems running NetBSD. + Copyright 2002 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef MIPSNBSD_TDEP_H +#define MIPSNBSD_TDEP_H + +void mipsnbsd_supply_reg (char *, int); +void mipsnbsd_fill_reg (char *, int); + +void mipsnbsd_supply_fpreg (char *, int); +void mipsnbsd_fill_fpreg (char *, int); + +#define SIZEOF_STRUCT_REG (38 * MIPS_REGSIZE) +#define SIZEOF_STRUCT_FPREG (33 * MIPS_REGSIZE) + +#endif /* MIPSNBSD_TDEP_H */