From: Kamil Rytarowski Date: Tue, 6 Oct 2020 19:36:22 +0000 (+0200) Subject: Normalize names of the NetBSD files X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1b71cfcfdc3e13a655fefa6566b5564cec044c10;p=binutils-gdb.git Normalize names of the NetBSD files The files used to be named 'nbsd', which incorrectly reflects the name of the OS and confuses it with other BSD derived OSes. gdb/ChangeLog: * Makefile.in (ALL_64_TARGET_OBS, ALL_TARGET_OBS) HFILES_NO_SRCDIR, ALLDEPFILES): Rename files. * alpha-bsd-nat.c: Adjust include. * alpha-bsd-tdep.h: Adjust comment. * alpha-nbsd-tdep.c: Rename to ... * alpha-netbsd-tdep.c: ... this, adjust include. * amd64-nbsd-nat.c: Rename to ... * amd64-netbsd-nat.c: ... this, adjust include. * amd64-nbsd-tdep.c: Rename to ... * amd64-netbsd-tdep.c: ... this, adjust include. * amd64-tdep.h: Adjust include. * arm-nbsd-nat.c: Rename to ... * arm-netbsd-nat.c: ... this, adjust include. * arm-nbsd-tdep.c: Rename to ... * arm-netbsd-tdep.c: ... this, adjust include. * arm-nbsd-tdep.h: Rename to ... * arm-netbsd-tdep.h: ... this, adjust include. * configure.nat: Adjust file lists. * configure.tgt: Likewise. * hppa-nbsd-nat.c: Rename to ... * hppa-netbsd-nat.c: ... this, adjust include. * hppa-nbsd-tdep.c: Rename to ... * hppa-netbsd-tdep.c: ... this, adjust include. * i386-nbsd-nat.c: Rename to ... * i386-netbsd-nat.c: ... this, adjust include. * i386-nbsd-tdep.c: Rename to ... * i386-netbsd-tdep.c: ... this, adjust include. * m68k-bsd-nat.c: Adjust include. * mips-nbsd-nat.c: Rename to ... * mips-netbsd-nat.c: ... this, adjust include. * mips-nbsd-tdep.c: Rename to ... * mips-netbsd-tdep.c: ... this, adjust include. * mips-nbsd-tdep.h: Rename to ... * mips-netbsd-tdep.h: ... this. * nbsd-nat.c: Rename to ... * netbsd-nat.c: ... this, adjust include. * nbsd-nat.h: Rename to ... * netbsd-nat.h: ... this, adjust include. * nbsd-tdep.c: Rename to ... * netbsd-tdep.c: ... this, adjust include. * nbsd-tdep.h: Rename to ... * netbsd-tdep.h: ... this. * ppc-nbsd-nat.c: Rename to ... * ppc-netbsd-nat.c: ... this, adjust include. * ppc-nbsd-tdep.c: Rename to ... * ppc-netbsd-tdep.c: ... this, adjust include and comment. * ppc-nbsd-tdep.h: Rename to ... * ppc-netbsd-tdep.h: ... this. * sh-nbsd-nat.c: Rename to ... * sh-netbsd-nat.c: ... this, adjust include. * sh-nbsd-tdep.c: Rename to ... * sh-netbsd-tdep.c: ... this, adjust include. * sparc-nbsd-nat.c: Rename to ... * sparc-netbsd-nat.c: ... this. * sparc-nbsd-tdep.c: Rename to ... * sparc-netbsd-tdep.c: ... this, adjust include. * sparc64-nbsd-nat.c: Rename to ... * sparc64-netbsd-nat.c: ... this. * sparc64-nbsd-tdep.c: Rename to ... * sparc64-netbsd-tdep.c: ... this, adjust include. * sparc64-tdep.h: Adjust comment. * vax-bsd-nat.c: Adjust include. * vax-nbsd-tdep.c: Rename to ... * vax-netbsd-tdep.c: ... this, adjust include. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7dc3590f146..79530385617 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,70 @@ +2020-10-13 Kamil Rytarowski + + * Makefile.in (ALL_64_TARGET_OBS, ALL_TARGET_OBS) + HFILES_NO_SRCDIR, ALLDEPFILES): Rename files. + * alpha-bsd-nat.c: Adjust include. + * alpha-bsd-tdep.h: Adjust comment. + * alpha-nbsd-tdep.c: Rename to ... + * alpha-netbsd-tdep.c: ... this, adjust include. + * amd64-nbsd-nat.c: Rename to ... + * amd64-netbsd-nat.c: ... this, adjust include. + * amd64-nbsd-tdep.c: Rename to ... + * amd64-netbsd-tdep.c: ... this, adjust include. + * amd64-tdep.h: Adjust include. + * arm-nbsd-nat.c: Rename to ... + * arm-netbsd-nat.c: ... this, adjust include. + * arm-nbsd-tdep.c: Rename to ... + * arm-netbsd-tdep.c: ... this, adjust include. + * arm-nbsd-tdep.h: Rename to ... + * arm-netbsd-tdep.h: ... this, adjust include. + * configure.nat: Adjust file lists. + * configure.tgt: Likewise. + * hppa-nbsd-nat.c: Rename to ... + * hppa-netbsd-nat.c: ... this, adjust include. + * hppa-nbsd-tdep.c: Rename to ... + * hppa-netbsd-tdep.c: ... this, adjust include. + * i386-nbsd-nat.c: Rename to ... + * i386-netbsd-nat.c: ... this, adjust include. + * i386-nbsd-tdep.c: Rename to ... + * i386-netbsd-tdep.c: ... this, adjust include. + * m68k-bsd-nat.c: Adjust include. + * mips-nbsd-nat.c: Rename to ... + * mips-netbsd-nat.c: ... this, adjust include. + * mips-nbsd-tdep.c: Rename to ... + * mips-netbsd-tdep.c: ... this, adjust include. + * mips-nbsd-tdep.h: Rename to ... + * mips-netbsd-tdep.h: ... this. + * nbsd-nat.c: Rename to ... + * netbsd-nat.c: ... this, adjust include. + * nbsd-nat.h: Rename to ... + * netbsd-nat.h: ... this, adjust include. + * nbsd-tdep.c: Rename to ... + * netbsd-tdep.c: ... this, adjust include. + * nbsd-tdep.h: Rename to ... + * netbsd-tdep.h: ... this. + * ppc-nbsd-nat.c: Rename to ... + * ppc-netbsd-nat.c: ... this, adjust include. + * ppc-nbsd-tdep.c: Rename to ... + * ppc-netbsd-tdep.c: ... this, adjust include and comment. + * ppc-nbsd-tdep.h: Rename to ... + * ppc-netbsd-tdep.h: ... this. + * sh-nbsd-nat.c: Rename to ... + * sh-netbsd-nat.c: ... this, adjust include. + * sh-nbsd-tdep.c: Rename to ... + * sh-netbsd-tdep.c: ... this, adjust include. + * sparc-nbsd-nat.c: Rename to ... + * sparc-netbsd-nat.c: ... this. + * sparc-nbsd-tdep.c: Rename to ... + * sparc-netbsd-tdep.c: ... this, adjust include. + * sparc64-nbsd-nat.c: Rename to ... + * sparc64-netbsd-nat.c: ... this. + * sparc64-nbsd-tdep.c: Rename to ... + * sparc64-netbsd-tdep.c: ... this, adjust include. + * sparc64-tdep.h: Adjust comment. + * vax-bsd-nat.c: Adjust include. + * vax-nbsd-tdep.c: Rename to ... + * vax-netbsd-tdep.c: ... this, adjust include. + 2020-10-12 Tom Tromey * target.h (struct target_ops) : Update. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5f92e8781e7..8a160896e2c 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -678,14 +678,14 @@ ALL_64_TARGET_OBS = \ alpha-bsd-tdep.o \ alpha-linux-tdep.o \ alpha-mdebug-tdep.o \ - alpha-nbsd-tdep.o \ + alpha-netbsd-tdep.o \ alpha-obsd-tdep.o \ alpha-tdep.o \ amd64-darwin-tdep.o \ amd64-dicos-tdep.o \ amd64-fbsd-tdep.o \ amd64-linux-tdep.o \ - amd64-nbsd-tdep.o \ + amd64-netbsd-tdep.o \ amd64-obsd-tdep.o \ amd64-sol2-tdep.o \ amd64-tdep.o \ @@ -699,7 +699,7 @@ ALL_64_TARGET_OBS = \ mips64-obsd-tdep.o \ sparc64-fbsd-tdep.o \ sparc64-linux-tdep.o \ - sparc64-nbsd-tdep.o \ + sparc64-netbsd-tdep.o \ sparc64-obsd-tdep.o \ sparc64-sol2-tdep.o \ sparc64-tdep.o @@ -720,7 +720,7 @@ ALL_TARGET_OBS = \ arm-bsd-tdep.o \ arm-fbsd-tdep.o \ arm-linux-tdep.o \ - arm-nbsd-tdep.o \ + arm-netbsd-tdep.o \ arm-obsd-tdep.o \ arm-pikeos-tdep.o \ arm-symbian-tdep.o \ @@ -744,7 +744,7 @@ ALL_TARGET_OBS = \ h8300-tdep.o \ hppa-bsd-tdep.o \ hppa-linux-tdep.o \ - hppa-nbsd-tdep.o \ + hppa-netbsd-tdep.o \ hppa-obsd-tdep.o \ hppa-tdep.o \ i386-bsd-tdep.o \ @@ -754,7 +754,7 @@ ALL_TARGET_OBS = \ i386-gnu-tdep.o \ i386-go32-tdep.o \ i386-linux-tdep.o \ - i386-nbsd-tdep.o \ + i386-netbsd-tdep.o \ i386-nto-tdep.o \ i386-obsd-tdep.o \ i386-sol2-tdep.o \ @@ -777,14 +777,14 @@ ALL_TARGET_OBS = \ microblaze-tdep.o \ mips-fbsd-tdep.o \ mips-linux-tdep.o \ - mips-nbsd-tdep.o \ + mips-netbsd-tdep.o \ mips-sde-tdep.o \ mips-tdep.o \ mn10300-linux-tdep.o \ mn10300-tdep.o \ moxie-tdep.o \ msp430-tdep.o \ - nbsd-tdep.o \ + netbsd-tdep.o \ nds32-tdep.o \ nios2-linux-tdep.o \ nios2-tdep.o \ @@ -794,7 +794,7 @@ ALL_TARGET_OBS = \ or1k-tdep.o \ ppc-fbsd-tdep.o \ ppc-linux-tdep.o \ - ppc-nbsd-tdep.o \ + ppc-netbsd-tdep.o \ ppc-obsd-tdep.o \ ppc-ravenscar-thread.o \ ppc-sysv-tdep.o \ @@ -814,7 +814,7 @@ ALL_TARGET_OBS = \ s390-tdep.o \ score-tdep.o \ sh-linux-tdep.o \ - sh-nbsd-tdep.o \ + sh-netbsd-tdep.o \ sh-tdep.o \ sol2-tdep.o \ solib-aix.o \ @@ -823,7 +823,7 @@ ALL_TARGET_OBS = \ solib-frv.o \ solib-svr4.o \ sparc-linux-tdep.o \ - sparc-nbsd-tdep.o \ + sparc-netbsd-tdep.o \ sparc-obsd-tdep.o \ sparc-ravenscar-thread.o \ sparc-sol2-tdep.o \ @@ -834,7 +834,7 @@ ALL_TARGET_OBS = \ tilegx-linux-tdep.o \ tilegx-tdep.o \ v850-tdep.o \ - vax-nbsd-tdep.o \ + vax-netbsd-tdep.o \ vax-tdep.o \ windows-tdep.o \ x86-tdep.o \ @@ -1224,7 +1224,7 @@ HFILES_NO_SRCDIR = \ arc-tdep.h \ arch-utils.h \ arm-linux-tdep.h \ - arm-nbsd-tdep.h \ + arm-netbsd-tdep.h \ arm-tdep.h \ async-event.h \ auto-load.h \ @@ -1342,12 +1342,12 @@ HFILES_NO_SRCDIR = \ memrange.h \ microblaze-tdep.h \ mips-linux-tdep.h \ - mips-nbsd-tdep.h \ + mips-netbsd-tdep.h \ mips-tdep.h \ mn10300-tdep.h \ moxie-tdep.h \ - nbsd-nat.h \ - nbsd-tdep.h \ + netbsd-nat.h \ + netbsd-tdep.h \ nds32-tdep.h \ nios2-tdep.h \ nto-tdep.h \ @@ -1361,7 +1361,7 @@ HFILES_NO_SRCDIR = \ parser-defs.h \ ppc-fbsd-tdep.h \ ppc-linux-tdep.h \ - ppc-nbsd-tdep.h \ + ppc-netbsd-tdep.h \ ppc-obsd-tdep.h \ ppc-ravenscar-thread.h \ ppc-tdep.h \ @@ -2124,7 +2124,7 @@ ALLDEPFILES = \ alpha-linux-nat.c \ alpha-linux-tdep.c \ alpha-mdebug-tdep.c \ - alpha-nbsd-tdep.c \ + alpha-netbsd-tdep.c \ alpha-obsd-tdep.c \ alpha-tdep.c \ amd64-bsd-nat.c \ @@ -2135,8 +2135,8 @@ ALLDEPFILES = \ amd64-linux-nat.c \ amd64-linux-tdep.c \ amd64-nat.c \ - amd64-nbsd-nat.c \ - amd64-nbsd-tdep.c \ + amd64-netbsd-nat.c \ + amd64-netbsd-tdep.c \ amd64-obsd-nat.c \ amd64-obsd-tdep.c \ amd64-sol2-tdep.c \ @@ -2150,8 +2150,8 @@ ALLDEPFILES = \ arm-linux.c \ arm-linux-nat.c \ arm-linux-tdep.c \ - arm-nbsd-nat.c \ - arm-nbsd-tdep.c \ + arm-netbsd-nat.c \ + arm-netbsd-tdep.c \ arm-obsd-tdep.c \ arm-symbian-tdep.c \ arm-tdep.c \ @@ -2175,8 +2175,8 @@ ALLDEPFILES = \ hppa-bsd-tdep.c \ hppa-linux-nat.c \ hppa-linux-tdep.c \ - hppa-nbsd-nat.c \ - hppa-nbsd-tdep.c \ + hppa-netbsd-nat.c \ + hppa-netbsd-tdep.c \ hppa-obsd-nat.c \ hppa-obsd-tdep.c \ hppa-tdep.c \ @@ -2191,8 +2191,8 @@ ALLDEPFILES = \ i386-gnu-tdep.c \ i386-linux-nat.c \ i386-linux-tdep.c \ - i386-nbsd-nat.c \ - i386-nbsd-tdep.c \ + i386-netbsd-nat.c \ + i386-netbsd-tdep.c \ i386-obsd-nat.c \ i386-obsd-tdep.c \ i386-sol2-nat.c \ @@ -2226,15 +2226,15 @@ ALLDEPFILES = \ mips-fbsd-tdep.c \ mips-linux-nat.c \ mips-linux-tdep.c \ - mips-nbsd-nat.c \ - mips-nbsd-tdep.c \ + mips-netbsd-nat.c \ + mips-netbsd-tdep.c \ mips-sde-tdep.c \ mips-tdep.c \ mips64-obsd-nat.c \ mips64-obsd-tdep.c \ msp430-tdep.c \ - nbsd-nat.c \ - nbsd-tdep.c \ + netbsd-nat.c \ + netbsd-tdep.c \ nds32-tdep.c \ nios2-linux-tdep.c \ nios2-tdep.c \ @@ -2245,8 +2245,8 @@ ALLDEPFILES = \ ppc-fbsd-tdep.c \ ppc-linux-nat.c \ ppc-linux-tdep.c \ - ppc-nbsd-nat.c \ - ppc-nbsd-tdep.c \ + ppc-netbsd-nat.c \ + ppc-netbsd-tdep.c \ ppc-obsd-nat.c \ ppc-obsd-tdep.c \ ppc-ravenscar-thread.c \ @@ -2275,8 +2275,8 @@ ALLDEPFILES = \ ser-pipe.c \ ser-tcp.c \ ser-uds.c \ - sh-nbsd-nat.c \ - sh-nbsd-tdep.c \ + sh-netbsd-nat.c \ + sh-netbsd-tdep.c \ sh-tdep.c \ sol2-tdep.c \ solib-aix.c \ @@ -2284,8 +2284,8 @@ ALLDEPFILES = \ sparc-linux-nat.c \ sparc-linux-tdep.c \ sparc-nat.c \ - sparc-nbsd-nat.c \ - sparc-nbsd-tdep.c \ + sparc-netbsd-nat.c \ + sparc-netbsd-tdep.c \ sparc-obsd-tdep.c \ sparc-ravenscar-thread.c \ sparc-sol2-nat.c \ @@ -2296,8 +2296,8 @@ ALLDEPFILES = \ sparc64-linux-nat.c \ sparc64-linux-tdep.c \ sparc64-nat.c \ - sparc64-nbsd-nat.c \ - sparc64-nbsd-tdep.c \ + sparc64-netbsd-nat.c \ + sparc64-netbsd-tdep.c \ sparc64-obsd-nat.c \ sparc64-obsd-tdep.c \ sparc64-sol2-tdep.c \ @@ -2307,7 +2307,7 @@ ALLDEPFILES = \ tilegx-tdep.c \ v850-tdep.c \ vax-bsd-nat.c \ - vax-nbsd-tdep.c \ + vax-netbsd-tdep.c \ vax-tdep.c \ windows-nat.c \ windows-tdep.c \ diff --git a/gdb/alpha-bsd-nat.c b/gdb/alpha-bsd-nat.c index 8a8273934c4..df9892e7e8c 100644 --- a/gdb/alpha-bsd-nat.c +++ b/gdb/alpha-bsd-nat.c @@ -26,7 +26,7 @@ #include "alpha-tdep.h" #include "alpha-bsd-tdep.h" #include "inf-ptrace.h" -#include "nbsd-nat.h" +#include "netbsd-nat.h" #include #include diff --git a/gdb/alpha-bsd-tdep.h b/gdb/alpha-bsd-tdep.h index a8fd7ba9d1b..728763f0b1f 100644 --- a/gdb/alpha-bsd-tdep.h +++ b/gdb/alpha-bsd-tdep.h @@ -31,7 +31,7 @@ void alphabsd_supply_fpreg (struct regcache *, const char *, int); void alphabsd_fill_fpreg (const struct regcache *, char *, int); -/* Functions exported from alpha-nbsd-tdep.c. */ +/* Functions exported from alpha-netbsd-tdep.c. */ /* Iterate over supported core file register note sections. */ void alphanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, diff --git a/gdb/alpha-nbsd-tdep.c b/gdb/alpha-nbsd-tdep.c deleted file mode 100644 index 58294edb3f6..00000000000 --- a/gdb/alpha-nbsd-tdep.c +++ /dev/null @@ -1,292 +0,0 @@ -/* Target-dependent code for NetBSD/alpha. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "frame.h" -#include "gdbcore.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "value.h" - -#include "alpha-tdep.h" -#include "alpha-bsd-tdep.h" -#include "nbsd-tdep.h" -#include "solib-svr4.h" -#include "target.h" - -/* Core file support. */ - -/* Sizeof `struct reg' in . */ -#define ALPHANBSD_SIZEOF_GREGS (32 * 8) - -/* Sizeof `struct fpreg' in = ALPHANBSD_SIZEOF_FPREGS); - - for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++) - { - if (regnum == i || regnum == -1) - regcache->raw_supply (i, regs + (i - ALPHA_FP0_REGNUM) * 8); - } - - if (regnum == ALPHA_FPCR_REGNUM || regnum == -1) - regcache->raw_supply (ALPHA_FPCR_REGNUM, regs + 32 * 8); -} - -/* Supply register REGNUM from the buffer specified by GREGS and LEN - in the general-purpose register set REGSET to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -static void -alphanbsd_aout_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - const gdb_byte *regs = (const gdb_byte *) gregs; - int i; - - /* Table to map a GDB register number to a trapframe register index. */ - static const int regmap[] = - { - 0, 1, 2, 3, - 4, 5, 6, 7, - 8, 9, 10, 11, - 12, 13, 14, 15, - 30, 31, 32, 16, - 17, 18, 19, 20, - 21, 22, 23, 24, - 25, 29, 26 - }; - - gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS); - - for (i = 0; i < ARRAY_SIZE(regmap); i++) - { - if (regnum == i || regnum == -1) - regcache->raw_supply (i, regs + regmap[i] * 8); - } - - if (regnum == ALPHA_PC_REGNUM || regnum == -1) - regcache->raw_supply (ALPHA_PC_REGNUM, regs + 31 * 8); - - if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS) - { - regs += ALPHANBSD_SIZEOF_GREGS; - len -= ALPHANBSD_SIZEOF_GREGS; - alphanbsd_supply_fpregset (regset, regcache, regnum, regs, len); - } -} - -/* Supply register REGNUM from the buffer specified by GREGS and LEN - in the general-purpose register set REGSET to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -static void -alphanbsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - const gdb_byte *regs = (const gdb_byte *) gregs; - int i; - - if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS) - { - alphanbsd_aout_supply_gregset (regset, regcache, regnum, gregs, len); - return; - } - - for (i = 0; i < ALPHA_ZERO_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache->raw_supply (i, regs + i * 8); - } - - if (regnum == ALPHA_PC_REGNUM || regnum == -1) - regcache->raw_supply (ALPHA_PC_REGNUM, regs + 31 * 8); -} - -/* NetBSD/alpha register sets. */ - -static const struct regset alphanbsd_gregset = -{ - NULL, - alphanbsd_supply_gregset, - NULL, - REGSET_VARIABLE_SIZE -}; - -static const struct regset alphanbsd_fpregset = -{ - NULL, - alphanbsd_supply_fpregset -}; - -/* Iterate over supported core file register note sections. */ - -void -alphanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", ALPHANBSD_SIZEOF_GREGS, ALPHANBSD_SIZEOF_GREGS, - &alphanbsd_gregset, NULL, cb_data); - cb (".reg2", ALPHANBSD_SIZEOF_FPREGS, ALPHANBSD_SIZEOF_FPREGS, - &alphanbsd_fpregset, NULL, cb_data); -} - - -/* Signal trampolines. */ - -/* Under NetBSD/alpha, 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: - - ldq a0, 0(sp) - lda sp, 16(sp) - lda v0, 295(zero) # __sigreturn14 - call_pal callsys - - 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. */ -static const gdb_byte sigtramp_retcode[] = -{ - 0x00, 0x00, 0x1e, 0xa6, /* ldq a0, 0(sp) */ - 0x10, 0x00, 0xde, 0x23, /* lda sp, 16(sp) */ - 0x27, 0x01, 0x1f, 0x20, /* lda v0, 295(zero) */ - 0x83, 0x00, 0x00, 0x00, /* call_pal callsys */ -}; -#define RETCODE_NWORDS 4 -#define RETCODE_SIZE (RETCODE_NWORDS * 4) - -static LONGEST -alphanbsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) -{ - gdb_byte ret[RETCODE_SIZE], w[4]; - LONGEST off; - int i; - - if (target_read_memory (pc, w, 4) != 0) - return -1; - - for (i = 0; i < RETCODE_NWORDS; i++) - { - if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0) - break; - } - if (i == RETCODE_NWORDS) - return (-1); - - off = i * 4; - pc -= off; - - if (target_read_memory (pc, ret, sizeof (ret)) != 0) - return -1; - - if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0) - return off; - - return -1; -} - -static int -alphanbsd_pc_in_sigtramp (struct gdbarch *gdbarch, - CORE_ADDR pc, const char *func_name) -{ - return (nbsd_pc_in_sigtramp (pc, func_name) - || alphanbsd_sigtramp_offset (gdbarch, pc) >= 0); -} - -static CORE_ADDR -alphanbsd_sigcontext_addr (struct frame_info *frame) -{ - /* FIXME: This is not correct for all versions of NetBSD/alpha. - We will probably need to disassemble the trampoline to figure - out which trampoline frame type we have. */ - if (!get_next_frame (frame)) - return 0; - return get_frame_base (get_next_frame (frame)); -} - - -static void -alphanbsd_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Hook into the DWARF CFI frame unwinder. */ - alpha_dwarf2_init_abi (info, gdbarch); - - /* Hook into the MDEBUG frame unwinder. */ - alpha_mdebug_init_abi (info, gdbarch); - - nbsd_init_abi (info, gdbarch); - - /* NetBSD/alpha does not provide single step support via ptrace(2); we - must use software single-stepping. */ - set_gdbarch_software_single_step (gdbarch, alpha_software_single_step); - - /* NetBSD/alpha has SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); - - tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset; - tdep->pc_in_sigtramp = alphanbsd_pc_in_sigtramp; - tdep->sigcontext_addr = alphanbsd_sigcontext_addr; - - tdep->jb_pc = 2; - tdep->jb_elt_size = 8; - - set_gdbarch_iterate_over_regset_sections - (gdbarch, alphanbsd_iterate_over_regset_sections); -} - - -void _initialize_alphanbsd_tdep (); -void -_initialize_alphanbsd_tdep () -{ - /* Even though NetBSD/alpha used ELF since day one, it used the - traditional a.out-style core dump format before NetBSD 1.6, but - we don't support those. */ - gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD, - alphanbsd_init_abi); -} diff --git a/gdb/alpha-netbsd-tdep.c b/gdb/alpha-netbsd-tdep.c new file mode 100644 index 00000000000..c78e49601f2 --- /dev/null +++ b/gdb/alpha-netbsd-tdep.c @@ -0,0 +1,292 @@ +/* Target-dependent code for NetBSD/alpha. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "frame.h" +#include "gdbcore.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "value.h" + +#include "alpha-tdep.h" +#include "alpha-bsd-tdep.h" +#include "netbsd-tdep.h" +#include "solib-svr4.h" +#include "target.h" + +/* Core file support. */ + +/* Sizeof `struct reg' in . */ +#define ALPHANBSD_SIZEOF_GREGS (32 * 8) + +/* Sizeof `struct fpreg' in = ALPHANBSD_SIZEOF_FPREGS); + + for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++) + { + if (regnum == i || regnum == -1) + regcache->raw_supply (i, regs + (i - ALPHA_FP0_REGNUM) * 8); + } + + if (regnum == ALPHA_FPCR_REGNUM || regnum == -1) + regcache->raw_supply (ALPHA_FPCR_REGNUM, regs + 32 * 8); +} + +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +alphanbsd_aout_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const gdb_byte *regs = (const gdb_byte *) gregs; + int i; + + /* Table to map a GDB register number to a trapframe register index. */ + static const int regmap[] = + { + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 30, 31, 32, 16, + 17, 18, 19, 20, + 21, 22, 23, 24, + 25, 29, 26 + }; + + gdb_assert (len >= ALPHANBSD_SIZEOF_GREGS); + + for (i = 0; i < ARRAY_SIZE(regmap); i++) + { + if (regnum == i || regnum == -1) + regcache->raw_supply (i, regs + regmap[i] * 8); + } + + if (regnum == ALPHA_PC_REGNUM || regnum == -1) + regcache->raw_supply (ALPHA_PC_REGNUM, regs + 31 * 8); + + if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS) + { + regs += ALPHANBSD_SIZEOF_GREGS; + len -= ALPHANBSD_SIZEOF_GREGS; + alphanbsd_supply_fpregset (regset, regcache, regnum, regs, len); + } +} + +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +alphanbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const gdb_byte *regs = (const gdb_byte *) gregs; + int i; + + if (len >= ALPHANBSD_SIZEOF_GREGS + ALPHANBSD_SIZEOF_FPREGS) + { + alphanbsd_aout_supply_gregset (regset, regcache, regnum, gregs, len); + return; + } + + for (i = 0; i < ALPHA_ZERO_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache->raw_supply (i, regs + i * 8); + } + + if (regnum == ALPHA_PC_REGNUM || regnum == -1) + regcache->raw_supply (ALPHA_PC_REGNUM, regs + 31 * 8); +} + +/* NetBSD/alpha register sets. */ + +static const struct regset alphanbsd_gregset = +{ + NULL, + alphanbsd_supply_gregset, + NULL, + REGSET_VARIABLE_SIZE +}; + +static const struct regset alphanbsd_fpregset = +{ + NULL, + alphanbsd_supply_fpregset +}; + +/* Iterate over supported core file register note sections. */ + +void +alphanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", ALPHANBSD_SIZEOF_GREGS, ALPHANBSD_SIZEOF_GREGS, + &alphanbsd_gregset, NULL, cb_data); + cb (".reg2", ALPHANBSD_SIZEOF_FPREGS, ALPHANBSD_SIZEOF_FPREGS, + &alphanbsd_fpregset, NULL, cb_data); +} + + +/* Signal trampolines. */ + +/* Under NetBSD/alpha, 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: + + ldq a0, 0(sp) + lda sp, 16(sp) + lda v0, 295(zero) # __sigreturn14 + call_pal callsys + + 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. */ +static const gdb_byte sigtramp_retcode[] = +{ + 0x00, 0x00, 0x1e, 0xa6, /* ldq a0, 0(sp) */ + 0x10, 0x00, 0xde, 0x23, /* lda sp, 16(sp) */ + 0x27, 0x01, 0x1f, 0x20, /* lda v0, 295(zero) */ + 0x83, 0x00, 0x00, 0x00, /* call_pal callsys */ +}; +#define RETCODE_NWORDS 4 +#define RETCODE_SIZE (RETCODE_NWORDS * 4) + +static LONGEST +alphanbsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_byte ret[RETCODE_SIZE], w[4]; + LONGEST off; + int i; + + if (target_read_memory (pc, w, 4) != 0) + return -1; + + for (i = 0; i < RETCODE_NWORDS; i++) + { + if (memcmp (w, sigtramp_retcode + (i * 4), 4) == 0) + break; + } + if (i == RETCODE_NWORDS) + return (-1); + + off = i * 4; + pc -= off; + + if (target_read_memory (pc, ret, sizeof (ret)) != 0) + return -1; + + if (memcmp (ret, sigtramp_retcode, RETCODE_SIZE) == 0) + return off; + + return -1; +} + +static int +alphanbsd_pc_in_sigtramp (struct gdbarch *gdbarch, + CORE_ADDR pc, const char *func_name) +{ + return (nbsd_pc_in_sigtramp (pc, func_name) + || alphanbsd_sigtramp_offset (gdbarch, pc) >= 0); +} + +static CORE_ADDR +alphanbsd_sigcontext_addr (struct frame_info *frame) +{ + /* FIXME: This is not correct for all versions of NetBSD/alpha. + We will probably need to disassemble the trampoline to figure + out which trampoline frame type we have. */ + if (!get_next_frame (frame)) + return 0; + return get_frame_base (get_next_frame (frame)); +} + + +static void +alphanbsd_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Hook into the DWARF CFI frame unwinder. */ + alpha_dwarf2_init_abi (info, gdbarch); + + /* Hook into the MDEBUG frame unwinder. */ + alpha_mdebug_init_abi (info, gdbarch); + + nbsd_init_abi (info, gdbarch); + + /* NetBSD/alpha does not provide single step support via ptrace(2); we + must use software single-stepping. */ + set_gdbarch_software_single_step (gdbarch, alpha_software_single_step); + + /* NetBSD/alpha has SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); + + tdep->dynamic_sigtramp_offset = alphanbsd_sigtramp_offset; + tdep->pc_in_sigtramp = alphanbsd_pc_in_sigtramp; + tdep->sigcontext_addr = alphanbsd_sigcontext_addr; + + tdep->jb_pc = 2; + tdep->jb_elt_size = 8; + + set_gdbarch_iterate_over_regset_sections + (gdbarch, alphanbsd_iterate_over_regset_sections); +} + + +void _initialize_alphanbsd_tdep (); +void +_initialize_alphanbsd_tdep () +{ + /* Even though NetBSD/alpha used ELF since day one, it used the + traditional a.out-style core dump format before NetBSD 1.6, but + we don't support those. */ + gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD, + alphanbsd_init_abi); +} diff --git a/gdb/amd64-nbsd-nat.c b/gdb/amd64-nbsd-nat.c deleted file mode 100644 index 7a4c0057352..00000000000 --- a/gdb/amd64-nbsd-nat.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Native-dependent code for NetBSD/amd64. - - Copyright (C) 2003-2020 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 3 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, see . */ - -#include "defs.h" -#include "target.h" - -#include "nbsd-nat.h" -#include "amd64-tdep.h" -#include "amd64-bsd-nat.h" -#include "amd64-nat.h" - -/* Mapping between the general-purpose registers in NetBSD/amd64 - `struct reg' format and GDB's register cache layout for - NetBSD/i386. - - Note that most (if not all) NetBSD/amd64 registers are 64-bit, - while the NetBSD/i386 registers are all 32-bit, but since we're - little-endian we get away with that. */ - -/* From . */ -static int amd64nbsd32_r_reg_offset[] = -{ - 14 * 8, /* %eax */ - 3 * 8, /* %ecx */ - 2 * 8, /* %edx */ - 13 * 8, /* %ebx */ - 24 * 8, /* %esp */ - 12 * 8, /* %ebp */ - 1 * 8, /* %esi */ - 0 * 8, /* %edi */ - 21 * 8, /* %eip */ - 23 * 8, /* %eflags */ - 22 * 8, /* %cs */ - 25 * 8, /* %ss */ - 18 * 8, /* %ds */ - 17 * 8, /* %es */ - 16 * 8, /* %fs */ - 15 * 8 /* %gs */ -}; - -static amd64_bsd_nat_target the_amd64_nbsd_nat_target; - -void _initialize_amd64nbsd_nat (); -void -_initialize_amd64nbsd_nat () -{ - amd64_native_gregset32_reg_offset = amd64nbsd32_r_reg_offset; - amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64nbsd32_r_reg_offset); - amd64_native_gregset64_reg_offset = amd64nbsd_r_reg_offset; - - add_inf_child_target (&the_amd64_nbsd_nat_target); -} diff --git a/gdb/amd64-nbsd-tdep.c b/gdb/amd64-nbsd-tdep.c deleted file mode 100644 index 59071488ed7..00000000000 --- a/gdb/amd64-nbsd-tdep.c +++ /dev/null @@ -1,133 +0,0 @@ -/* Target-dependent code for NetBSD/amd64. - - Copyright (C) 2003-2020 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 3 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, see . */ - -#include "defs.h" -#include "arch-utils.h" -#include "frame.h" -#include "gdbcore.h" -#include "osabi.h" -#include "symtab.h" - -#include "amd64-tdep.h" -#include "gdbsupport/x86-xstate.h" -#include "nbsd-tdep.h" -#include "solib-svr4.h" - -/* Support for signal handlers. */ - -/* Return whether THIS_FRAME corresponds to a NetBSD sigtramp - routine. */ - -static int -amd64nbsd_sigtramp_p (struct frame_info *this_frame) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - const char *name; - - find_pc_partial_function (pc, &name, NULL, NULL); - return nbsd_pc_in_sigtramp (pc, name); -} - -/* Assuming THIS_FRAME corresponds to a NetBSD sigtramp routine, - return the address of the associated mcontext structure. */ - -static CORE_ADDR -amd64nbsd_mcontext_addr (struct frame_info *this_frame) -{ - CORE_ADDR addr; - - /* The register %r15 points at `struct ucontext' upon entry of a - signal trampoline. */ - addr = get_frame_register_unsigned (this_frame, AMD64_R15_REGNUM); - - /* The mcontext structure lives as offset 56 in `struct ucontext'. */ - return addr + 56; -} - -/* NetBSD 2.0 or later. */ - -/* Mapping between the general-purpose registers in `struct reg' - format and GDB's register cache layout. */ - -/* From . */ -int amd64nbsd_r_reg_offset[] = -{ - 14 * 8, /* %rax */ - 13 * 8, /* %rbx */ - 3 * 8, /* %rcx */ - 2 * 8, /* %rdx */ - 1 * 8, /* %rsi */ - 0 * 8, /* %rdi */ - 12 * 8, /* %rbp */ - 24 * 8, /* %rsp */ - 4 * 8, /* %r8 .. */ - 5 * 8, - 6 * 8, - 7 * 8, - 8 * 8, - 9 * 8, - 10 * 8, - 11 * 8, /* ... %r15 */ - 21 * 8, /* %rip */ - 23 * 8, /* %eflags */ - 22 * 8, /* %cs */ - 25 * 8, /* %ss */ - 18 * 8, /* %ds */ - 17 * 8, /* %es */ - 16 * 8, /* %fs */ - 15 * 8 /* %gs */ -}; - -static void -amd64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Initialize general-purpose register set details first. */ - tdep->gregset_reg_offset = amd64nbsd_r_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset); - tdep->sizeof_gregset = 26 * 8; - - amd64_init_abi (info, gdbarch, - amd64_target_description (X86_XSTATE_SSE_MASK, true)); - nbsd_init_abi (info, gdbarch); - - tdep->jb_pc_offset = 7 * 8; - - /* NetBSD has its own convention for signal trampolines. */ - tdep->sigtramp_p = amd64nbsd_sigtramp_p; - tdep->sigcontext_addr = amd64nbsd_mcontext_addr; - tdep->sc_reg_offset = amd64nbsd_r_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset); - - /* NetBSD uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); -} - -void _initialize_amd64nbsd_tdep (); -void -_initialize_amd64nbsd_tdep () -{ - /* The NetBSD/amd64 native dependent code makes this assumption. */ - gdb_assert (ARRAY_SIZE (amd64nbsd_r_reg_offset) == AMD64_NUM_GREGS); - - gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, - GDB_OSABI_NETBSD, amd64nbsd_init_abi); -} diff --git a/gdb/amd64-netbsd-nat.c b/gdb/amd64-netbsd-nat.c new file mode 100644 index 00000000000..f518d37fb86 --- /dev/null +++ b/gdb/amd64-netbsd-nat.c @@ -0,0 +1,68 @@ +/* Native-dependent code for NetBSD/amd64. + + Copyright (C) 2003-2020 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 3 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, see . */ + +#include "defs.h" +#include "target.h" + +#include "netbsd-nat.h" +#include "amd64-tdep.h" +#include "amd64-bsd-nat.h" +#include "amd64-nat.h" + +/* Mapping between the general-purpose registers in NetBSD/amd64 + `struct reg' format and GDB's register cache layout for + NetBSD/i386. + + Note that most (if not all) NetBSD/amd64 registers are 64-bit, + while the NetBSD/i386 registers are all 32-bit, but since we're + little-endian we get away with that. */ + +/* From . */ +static int amd64nbsd32_r_reg_offset[] = +{ + 14 * 8, /* %eax */ + 3 * 8, /* %ecx */ + 2 * 8, /* %edx */ + 13 * 8, /* %ebx */ + 24 * 8, /* %esp */ + 12 * 8, /* %ebp */ + 1 * 8, /* %esi */ + 0 * 8, /* %edi */ + 21 * 8, /* %eip */ + 23 * 8, /* %eflags */ + 22 * 8, /* %cs */ + 25 * 8, /* %ss */ + 18 * 8, /* %ds */ + 17 * 8, /* %es */ + 16 * 8, /* %fs */ + 15 * 8 /* %gs */ +}; + +static amd64_bsd_nat_target the_amd64_nbsd_nat_target; + +void _initialize_amd64nbsd_nat (); +void +_initialize_amd64nbsd_nat () +{ + amd64_native_gregset32_reg_offset = amd64nbsd32_r_reg_offset; + amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64nbsd32_r_reg_offset); + amd64_native_gregset64_reg_offset = amd64nbsd_r_reg_offset; + + add_inf_child_target (&the_amd64_nbsd_nat_target); +} diff --git a/gdb/amd64-netbsd-tdep.c b/gdb/amd64-netbsd-tdep.c new file mode 100644 index 00000000000..16c4f0b135c --- /dev/null +++ b/gdb/amd64-netbsd-tdep.c @@ -0,0 +1,133 @@ +/* Target-dependent code for NetBSD/amd64. + + Copyright (C) 2003-2020 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 3 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, see . */ + +#include "defs.h" +#include "arch-utils.h" +#include "frame.h" +#include "gdbcore.h" +#include "osabi.h" +#include "symtab.h" + +#include "amd64-tdep.h" +#include "gdbsupport/x86-xstate.h" +#include "netbsd-tdep.h" +#include "solib-svr4.h" + +/* Support for signal handlers. */ + +/* Return whether THIS_FRAME corresponds to a NetBSD sigtramp + routine. */ + +static int +amd64nbsd_sigtramp_p (struct frame_info *this_frame) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + const char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + return nbsd_pc_in_sigtramp (pc, name); +} + +/* Assuming THIS_FRAME corresponds to a NetBSD sigtramp routine, + return the address of the associated mcontext structure. */ + +static CORE_ADDR +amd64nbsd_mcontext_addr (struct frame_info *this_frame) +{ + CORE_ADDR addr; + + /* The register %r15 points at `struct ucontext' upon entry of a + signal trampoline. */ + addr = get_frame_register_unsigned (this_frame, AMD64_R15_REGNUM); + + /* The mcontext structure lives as offset 56 in `struct ucontext'. */ + return addr + 56; +} + +/* NetBSD 2.0 or later. */ + +/* Mapping between the general-purpose registers in `struct reg' + format and GDB's register cache layout. */ + +/* From . */ +int amd64nbsd_r_reg_offset[] = +{ + 14 * 8, /* %rax */ + 13 * 8, /* %rbx */ + 3 * 8, /* %rcx */ + 2 * 8, /* %rdx */ + 1 * 8, /* %rsi */ + 0 * 8, /* %rdi */ + 12 * 8, /* %rbp */ + 24 * 8, /* %rsp */ + 4 * 8, /* %r8 .. */ + 5 * 8, + 6 * 8, + 7 * 8, + 8 * 8, + 9 * 8, + 10 * 8, + 11 * 8, /* ... %r15 */ + 21 * 8, /* %rip */ + 23 * 8, /* %eflags */ + 22 * 8, /* %cs */ + 25 * 8, /* %ss */ + 18 * 8, /* %ds */ + 17 * 8, /* %es */ + 16 * 8, /* %fs */ + 15 * 8 /* %gs */ +}; + +static void +amd64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Initialize general-purpose register set details first. */ + tdep->gregset_reg_offset = amd64nbsd_r_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset); + tdep->sizeof_gregset = 26 * 8; + + amd64_init_abi (info, gdbarch, + amd64_target_description (X86_XSTATE_SSE_MASK, true)); + nbsd_init_abi (info, gdbarch); + + tdep->jb_pc_offset = 7 * 8; + + /* NetBSD has its own convention for signal trampolines. */ + tdep->sigtramp_p = amd64nbsd_sigtramp_p; + tdep->sigcontext_addr = amd64nbsd_mcontext_addr; + tdep->sc_reg_offset = amd64nbsd_r_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (amd64nbsd_r_reg_offset); + + /* NetBSD uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); +} + +void _initialize_amd64nbsd_tdep (); +void +_initialize_amd64nbsd_tdep () +{ + /* The NetBSD/amd64 native dependent code makes this assumption. */ + gdb_assert (ARRAY_SIZE (amd64nbsd_r_reg_offset) == AMD64_NUM_GREGS); + + gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, + GDB_OSABI_NETBSD, amd64nbsd_init_abi); +} diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h index 44c1250cb91..a4e69565593 100644 --- a/gdb/amd64-tdep.h +++ b/gdb/amd64-tdep.h @@ -139,7 +139,7 @@ extern const struct regset amd64_fpregset; /* Variables exported from amd64-linux-tdep.c. */ extern int amd64_linux_gregset_reg_offset[]; -/* Variables exported from amd64-nbsd-tdep.c. */ +/* Variables exported from amd64-netbsd-tdep.c. */ extern int amd64nbsd_r_reg_offset[]; /* Variables exported from amd64-obsd-tdep.c. */ diff --git a/gdb/arm-nbsd-nat.c b/gdb/arm-nbsd-nat.c deleted file mode 100644 index a8a67e6e852..00000000000 --- a/gdb/arm-nbsd-nat.c +++ /dev/null @@ -1,363 +0,0 @@ -/* Native-dependent code for BSD Unix running on ARM's, for GDB. - - Copyright (C) 1988-2020 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 3 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, see . */ - -/* We define this to get types like register_t. */ -#define _KERNTYPES -#include "defs.h" -#include "gdbcore.h" -#include "inferior.h" -#include "regcache.h" -#include "target.h" -#include -#include -#include -#include -#include - -#include "arm-tdep.h" -#include "arm-nbsd-tdep.h" -#include "aarch32-tdep.h" -#include "inf-ptrace.h" -#include "nbsd-nat.h" - -class arm_netbsd_nat_target final : public nbsd_nat_target -{ -public: - /* Add our register access methods. */ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; - const struct target_desc *read_description () override; -}; - -static arm_netbsd_nat_target the_arm_netbsd_nat_target; - -static void -arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); - if (tdep->vfp_register_count == 0) - return; - - struct vfpreg &vfp = fpregset->fpr_vfp; - for (int regno = 0; regno <= tdep->vfp_register_count; regno++) - regcache->raw_supply (regno + ARM_D0_REGNUM, (char *) &vfp.vfp_regs[regno]); - - regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr); -} - -static void -fetch_register (struct regcache *regcache, int regno) -{ - struct reg inferior_registers; - int ret; - int lwp = regcache->ptid ().lwp (); - - ret = ptrace (PT_GETREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_registers, lwp); - - if (ret < 0) - { - warning (_("unable to fetch general register")); - return; - } - arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers, - sizeof (inferior_registers)); -} - -static void -fetch_fp_register (struct regcache *regcache, int regno) -{ - struct fpreg inferior_fp_registers; - int lwp = regcache->ptid ().lwp (); - - int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); - - struct vfpreg &vfp = inferior_fp_registers.fpr_vfp; - - if (ret < 0) - { - warning (_("unable to fetch floating-point register")); - return; - } - - struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); - if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0) - regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr); - else if (regno >= ARM_D0_REGNUM - && regno <= ARM_D0_REGNUM + tdep->vfp_register_count) - { - regcache->raw_supply (regno, - (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]); - } - else - warning (_("Invalid register number.")); -} - -static void -fetch_fp_regs (struct regcache *regcache) -{ - struct fpreg inferior_fp_registers; - int lwp = regcache->ptid ().lwp (); - int ret; - int regno; - - ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); - - if (ret < 0) - { - warning (_("unable to fetch general registers")); - return; - } - - arm_supply_vfpregset (regcache, &inferior_fp_registers); -} - -void -arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) -{ - if (regno >= 0) - { - if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) - fetch_register (regcache, regno); - else - fetch_fp_register (regcache, regno); - } - else - { - fetch_register (regcache, -1); - fetch_fp_regs (regcache); - } -} - - -static void -store_register (const struct regcache *regcache, int regno) -{ - struct gdbarch *gdbarch = regcache->arch (); - struct reg inferior_registers; - int lwp = regcache->ptid ().lwp (); - int ret; - - ret = ptrace (PT_GETREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_registers, lwp); - - if (ret < 0) - { - warning (_("unable to fetch general registers")); - return; - } - - switch (regno) - { - case ARM_SP_REGNUM: - regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); - break; - - case ARM_LR_REGNUM: - regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); - break; - - case ARM_PC_REGNUM: - if (arm_apcs_32) - regcache->raw_collect (ARM_PC_REGNUM, - (char *) &inferior_registers.r_pc); - else - { - unsigned pc_val; - - regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val); - - pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); - inferior_registers.r_pc ^= gdbarch_addr_bits_remove - (gdbarch, inferior_registers.r_pc); - inferior_registers.r_pc |= pc_val; - } - break; - - case ARM_PS_REGNUM: - if (arm_apcs_32) - regcache->raw_collect (ARM_PS_REGNUM, - (char *) &inferior_registers.r_cpsr); - else - { - unsigned psr_val; - - regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val); - - psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); - inferior_registers.r_pc = gdbarch_addr_bits_remove - (gdbarch, inferior_registers.r_pc); - inferior_registers.r_pc |= psr_val; - } - break; - - default: - regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]); - break; - } - - ret = ptrace (PT_SETREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_registers, lwp); - - if (ret < 0) - warning (_("unable to write register %d to inferior"), regno); -} - -static void -store_regs (const struct regcache *regcache) -{ - struct gdbarch *gdbarch = regcache->arch (); - struct reg inferior_registers; - int lwp = regcache->ptid ().lwp (); - int ret; - int regno; - - - for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) - regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]); - - regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); - regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); - - if (arm_apcs_32) - { - regcache->raw_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); - regcache->raw_collect (ARM_PS_REGNUM, - (char *) &inferior_registers.r_cpsr); - } - else - { - unsigned pc_val; - unsigned psr_val; - - regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val); - regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val); - - pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); - psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); - - inferior_registers.r_pc = pc_val | psr_val; - } - - ret = ptrace (PT_SETREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_registers, lwp); - - if (ret < 0) - warning (_("unable to store general registers")); -} - -static void -store_fp_register (const struct regcache *regcache, int regno) -{ - struct fpreg inferior_fp_registers; - int lwp = regcache->ptid ().lwp (); - int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); - struct vfpreg &vfp = inferior_fp_registers.fpr_vfp; - - if (ret < 0) - { - warning (_("unable to fetch floating-point registers")); - return; - } - - struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); - if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0) - regcache->raw_collect (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr); - else if (regno >= ARM_D0_REGNUM - && regno <= ARM_D0_REGNUM + tdep->vfp_register_count) - { - regcache->raw_collect (regno, - (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]); - } - else - warning (_("Invalid register number.")); - - ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); - - if (ret < 0) - warning (_("unable to write register %d to inferior"), regno); -} - -static void -store_fp_regs (const struct regcache *regcache) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); - int lwp = regcache->ptid ().lwp (); - if (tdep->vfp_register_count == 0) - return; - - struct fpreg fpregs; - for (int regno = 0; regno <= tdep->vfp_register_count; regno++) - regcache->raw_collect - (regno + ARM_D0_REGNUM, (char *) &fpregs.fpr_vfp.vfp_regs[regno]); - - regcache->raw_collect (ARM_FPSCR_REGNUM, - (char *) &fpregs.fpr_vfp.vfp_fpscr); - - int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (), - (PTRACE_TYPE_ARG3) &fpregs, lwp); - - if (ret < 0) - warning (_("unable to store floating-point registers")); -} - -void -arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno) -{ - if (regno >= 0) - { - if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) - store_register (regcache, regno); - else - store_fp_register (regcache, regno); - } - else - { - store_regs (regcache); - store_fp_regs (regcache); - } -} - -const struct target_desc * -arm_netbsd_nat_target::read_description () -{ - int flag; - size_t len = sizeof (flag); - - if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0 - || !flag) - return arm_read_description (ARM_FP_TYPE_NONE); - - len = sizeof(flag); - if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag) - return aarch32_read_description (); - - return arm_read_description (ARM_FP_TYPE_VFPV3); -} - -void _initialize_arm_netbsd_nat (); -void -_initialize_arm_netbsd_nat () -{ - add_inf_child_target (&the_arm_netbsd_nat_target); -} diff --git a/gdb/arm-nbsd-tdep.c b/gdb/arm-nbsd-tdep.c deleted file mode 100644 index b1e369d41c2..00000000000 --- a/gdb/arm-nbsd-tdep.c +++ /dev/null @@ -1,171 +0,0 @@ -/* Target-dependent code for NetBSD/arm. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "osabi.h" - -#include "arch/arm.h" -#include "arm-nbsd-tdep.h" -#include "nbsd-tdep.h" -#include "arm-tdep.h" -#include "regset.h" -#include "solib-svr4.h" - -/* Description of the longjmp buffer. */ -#define ARM_NBSD_JB_PC 24 -#define ARM_NBSD_JB_ELEMENT_SIZE ARM_INT_REGISTER_SIZE - -/* For compatibility with previous implementations of GDB on arm/NetBSD, - override the default little-endian breakpoint. */ -static const gdb_byte arm_nbsd_arm_le_breakpoint[] = {0x11, 0x00, 0x00, 0xe6}; -static const gdb_byte arm_nbsd_arm_be_breakpoint[] = {0xe6, 0x00, 0x00, 0x11}; -static const gdb_byte arm_nbsd_thumb_le_breakpoint[] = {0xfe, 0xde}; -static const gdb_byte arm_nbsd_thumb_be_breakpoint[] = {0xde, 0xfe}; - -/* This matches struct reg from NetBSD's sys/arch/arm/include/reg.h: - https://github.com/NetBSD/src/blob/7c13e6e6773bb171f4ed3ed53013e9d24b3c1eac/sys/arch/arm/include/reg.h#L39 - */ -struct arm_nbsd_reg -{ - uint32_t reg[13]; - uint32_t sp; - uint32_t lr; - uint32_t pc; - uint32_t cpsr; -}; - -void -arm_nbsd_supply_gregset (const struct regset *regset, struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - const arm_nbsd_reg *gregset = static_cast(gregs); - gdb_assert (len >= sizeof (arm_nbsd_reg)); - - /* Integer registers. */ - for (int i = ARM_A1_REGNUM; i < ARM_SP_REGNUM; i++) - if (regnum == -1 || regnum == i) - regcache->raw_supply (i, (char *) &gregset->reg[i]); - - if (regnum == -1 || regnum == ARM_SP_REGNUM) - regcache->raw_supply (ARM_SP_REGNUM, (char *) &gregset->sp); - - if (regnum == -1 || regnum == ARM_LR_REGNUM) - regcache->raw_supply (ARM_LR_REGNUM, (char *) &gregset->lr); - - if (regnum == -1 || regnum == ARM_PC_REGNUM) - { - CORE_ADDR r_pc = gdbarch_addr_bits_remove (regcache->arch (), gregset->pc); - regcache->raw_supply (ARM_PC_REGNUM, (char *) &r_pc); - } - - if (regnum == -1 || regnum == ARM_PS_REGNUM) - { - if (arm_apcs_32) - regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->cpsr); - else - regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->pc); - } -} - -static const struct regset arm_nbsd_regset = { - nullptr, - arm_nbsd_supply_gregset, - /* We don't need a collect function because we only use this reading registers - (via iterate_over_regset_sections and fetch_regs/fetch_register). */ - nullptr, - 0 -}; - -static void -arm_nbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", sizeof (arm_nbsd_reg), sizeof (arm_nbsd_reg), &arm_nbsd_regset, - NULL, cb_data); - /* cbiesinger/2020-02-12 -- as far as I can tell, ARM/NetBSD does - not write any floating point registers into the core file (tested - with NetBSD 9.1_RC1). When it does, this function will need to read them, - and the arm-netbsd gdbarch will need a core_read_description function - to return the right description for them. */ -} - -static void -arm_netbsd_init_abi_common (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->lowest_pc = 0x8000; - switch (info.byte_order) - { - case BFD_ENDIAN_LITTLE: - tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint; - tdep->thumb_breakpoint = arm_nbsd_thumb_le_breakpoint; - tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint); - tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_le_breakpoint); - break; - - case BFD_ENDIAN_BIG: - tdep->arm_breakpoint = arm_nbsd_arm_be_breakpoint; - tdep->thumb_breakpoint = arm_nbsd_thumb_be_breakpoint; - tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_be_breakpoint); - tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_be_breakpoint); - break; - - default: - internal_error (__FILE__, __LINE__, - _("arm_gdbarch_init: bad byte order for float format")); - } - - tdep->jb_pc = ARM_NBSD_JB_PC; - tdep->jb_elt_size = ARM_NBSD_JB_ELEMENT_SIZE; - - set_gdbarch_iterate_over_regset_sections - (gdbarch, arm_nbsd_iterate_over_regset_sections); - /* Single stepping. */ - set_gdbarch_software_single_step (gdbarch, arm_software_single_step); -} - -static void -arm_netbsd_elf_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - arm_netbsd_init_abi_common (info, gdbarch); - - nbsd_init_abi (info, gdbarch); - - if (tdep->fp_model == ARM_FLOAT_AUTO) - tdep->fp_model = ARM_FLOAT_SOFT_VFP; - - /* NetBSD ELF uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - -void _initialize_arm_netbsd_tdep (); -void -_initialize_arm_netbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD, - arm_netbsd_elf_init_abi); -} diff --git a/gdb/arm-nbsd-tdep.h b/gdb/arm-nbsd-tdep.h deleted file mode 100644 index 1b35395031c..00000000000 --- a/gdb/arm-nbsd-tdep.h +++ /dev/null @@ -1,27 +0,0 @@ -/* NetBSD/ARM support. - - Copyright (C) 2020 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 3 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, see . */ - -#ifndef ARM_NBSD_TDEP_H -#define ARM_NBSD_TDEP_H - -void arm_nbsd_supply_gregset - (const struct regset *regset, struct regcache *regcache, - int regnum, const void *gregs, size_t len); - -#endif diff --git a/gdb/arm-netbsd-nat.c b/gdb/arm-netbsd-nat.c new file mode 100644 index 00000000000..acdbdd3de7d --- /dev/null +++ b/gdb/arm-netbsd-nat.c @@ -0,0 +1,363 @@ +/* Native-dependent code for BSD Unix running on ARM's, for GDB. + + Copyright (C) 1988-2020 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 3 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, see . */ + +/* We define this to get types like register_t. */ +#define _KERNTYPES +#include "defs.h" +#include "gdbcore.h" +#include "inferior.h" +#include "regcache.h" +#include "target.h" +#include +#include +#include +#include +#include + +#include "arm-tdep.h" +#include "arm-netbsd-tdep.h" +#include "aarch32-tdep.h" +#include "inf-ptrace.h" +#include "netbsd-nat.h" + +class arm_netbsd_nat_target final : public nbsd_nat_target +{ +public: + /* Add our register access methods. */ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; + const struct target_desc *read_description () override; +}; + +static arm_netbsd_nat_target the_arm_netbsd_nat_target; + +static void +arm_supply_vfpregset (struct regcache *regcache, struct fpreg *fpregset) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); + if (tdep->vfp_register_count == 0) + return; + + struct vfpreg &vfp = fpregset->fpr_vfp; + for (int regno = 0; regno <= tdep->vfp_register_count; regno++) + regcache->raw_supply (regno + ARM_D0_REGNUM, (char *) &vfp.vfp_regs[regno]); + + regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr); +} + +static void +fetch_register (struct regcache *regcache, int regno) +{ + struct reg inferior_registers; + int ret; + int lwp = regcache->ptid ().lwp (); + + ret = ptrace (PT_GETREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_registers, lwp); + + if (ret < 0) + { + warning (_("unable to fetch general register")); + return; + } + arm_nbsd_supply_gregset (nullptr, regcache, regno, &inferior_registers, + sizeof (inferior_registers)); +} + +static void +fetch_fp_register (struct regcache *regcache, int regno) +{ + struct fpreg inferior_fp_registers; + int lwp = regcache->ptid ().lwp (); + + int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); + + struct vfpreg &vfp = inferior_fp_registers.fpr_vfp; + + if (ret < 0) + { + warning (_("unable to fetch floating-point register")); + return; + } + + struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); + if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0) + regcache->raw_supply (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr); + else if (regno >= ARM_D0_REGNUM + && regno <= ARM_D0_REGNUM + tdep->vfp_register_count) + { + regcache->raw_supply (regno, + (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]); + } + else + warning (_("Invalid register number.")); +} + +static void +fetch_fp_regs (struct regcache *regcache) +{ + struct fpreg inferior_fp_registers; + int lwp = regcache->ptid ().lwp (); + int ret; + int regno; + + ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); + + if (ret < 0) + { + warning (_("unable to fetch general registers")); + return; + } + + arm_supply_vfpregset (regcache, &inferior_fp_registers); +} + +void +arm_netbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) +{ + if (regno >= 0) + { + if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) + fetch_register (regcache, regno); + else + fetch_fp_register (regcache, regno); + } + else + { + fetch_register (regcache, -1); + fetch_fp_regs (regcache); + } +} + + +static void +store_register (const struct regcache *regcache, int regno) +{ + struct gdbarch *gdbarch = regcache->arch (); + struct reg inferior_registers; + int lwp = regcache->ptid ().lwp (); + int ret; + + ret = ptrace (PT_GETREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_registers, lwp); + + if (ret < 0) + { + warning (_("unable to fetch general registers")); + return; + } + + switch (regno) + { + case ARM_SP_REGNUM: + regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); + break; + + case ARM_LR_REGNUM: + regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); + break; + + case ARM_PC_REGNUM: + if (arm_apcs_32) + regcache->raw_collect (ARM_PC_REGNUM, + (char *) &inferior_registers.r_pc); + else + { + unsigned pc_val; + + regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val); + + pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); + inferior_registers.r_pc ^= gdbarch_addr_bits_remove + (gdbarch, inferior_registers.r_pc); + inferior_registers.r_pc |= pc_val; + } + break; + + case ARM_PS_REGNUM: + if (arm_apcs_32) + regcache->raw_collect (ARM_PS_REGNUM, + (char *) &inferior_registers.r_cpsr); + else + { + unsigned psr_val; + + regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val); + + psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); + inferior_registers.r_pc = gdbarch_addr_bits_remove + (gdbarch, inferior_registers.r_pc); + inferior_registers.r_pc |= psr_val; + } + break; + + default: + regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]); + break; + } + + ret = ptrace (PT_SETREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_registers, lwp); + + if (ret < 0) + warning (_("unable to write register %d to inferior"), regno); +} + +static void +store_regs (const struct regcache *regcache) +{ + struct gdbarch *gdbarch = regcache->arch (); + struct reg inferior_registers; + int lwp = regcache->ptid ().lwp (); + int ret; + int regno; + + + for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) + regcache->raw_collect (regno, (char *) &inferior_registers.r[regno]); + + regcache->raw_collect (ARM_SP_REGNUM, (char *) &inferior_registers.r_sp); + regcache->raw_collect (ARM_LR_REGNUM, (char *) &inferior_registers.r_lr); + + if (arm_apcs_32) + { + regcache->raw_collect (ARM_PC_REGNUM, (char *) &inferior_registers.r_pc); + regcache->raw_collect (ARM_PS_REGNUM, + (char *) &inferior_registers.r_cpsr); + } + else + { + unsigned pc_val; + unsigned psr_val; + + regcache->raw_collect (ARM_PC_REGNUM, (char *) &pc_val); + regcache->raw_collect (ARM_PS_REGNUM, (char *) &psr_val); + + pc_val = gdbarch_addr_bits_remove (gdbarch, pc_val); + psr_val ^= gdbarch_addr_bits_remove (gdbarch, psr_val); + + inferior_registers.r_pc = pc_val | psr_val; + } + + ret = ptrace (PT_SETREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_registers, lwp); + + if (ret < 0) + warning (_("unable to store general registers")); +} + +static void +store_fp_register (const struct regcache *regcache, int regno) +{ + struct fpreg inferior_fp_registers; + int lwp = regcache->ptid ().lwp (); + int ret = ptrace (PT_GETFPREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); + struct vfpreg &vfp = inferior_fp_registers.fpr_vfp; + + if (ret < 0) + { + warning (_("unable to fetch floating-point registers")); + return; + } + + struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); + if (regno == ARM_FPSCR_REGNUM && tdep->vfp_register_count != 0) + regcache->raw_collect (ARM_FPSCR_REGNUM, (char *) &vfp.vfp_fpscr); + else if (regno >= ARM_D0_REGNUM + && regno <= ARM_D0_REGNUM + tdep->vfp_register_count) + { + regcache->raw_collect (regno, + (char *) &vfp.vfp_regs[regno - ARM_D0_REGNUM]); + } + else + warning (_("Invalid register number.")); + + ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, lwp); + + if (ret < 0) + warning (_("unable to write register %d to inferior"), regno); +} + +static void +store_fp_regs (const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (regcache->arch ()); + int lwp = regcache->ptid ().lwp (); + if (tdep->vfp_register_count == 0) + return; + + struct fpreg fpregs; + for (int regno = 0; regno <= tdep->vfp_register_count; regno++) + regcache->raw_collect + (regno + ARM_D0_REGNUM, (char *) &fpregs.fpr_vfp.vfp_regs[regno]); + + regcache->raw_collect (ARM_FPSCR_REGNUM, + (char *) &fpregs.fpr_vfp.vfp_fpscr); + + int ret = ptrace (PT_SETFPREGS, regcache->ptid ().pid (), + (PTRACE_TYPE_ARG3) &fpregs, lwp); + + if (ret < 0) + warning (_("unable to store floating-point registers")); +} + +void +arm_netbsd_nat_target::store_registers (struct regcache *regcache, int regno) +{ + if (regno >= 0) + { + if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM) + store_register (regcache, regno); + else + store_fp_register (regcache, regno); + } + else + { + store_regs (regcache); + store_fp_regs (regcache); + } +} + +const struct target_desc * +arm_netbsd_nat_target::read_description () +{ + int flag; + size_t len = sizeof (flag); + + if (sysctlbyname("machdep.fpu_present", &flag, &len, NULL, 0) != 0 + || !flag) + return arm_read_description (ARM_FP_TYPE_NONE); + + len = sizeof(flag); + if (sysctlbyname("machdep.neon_present", &flag, &len, NULL, 0) == 0 && flag) + return aarch32_read_description (); + + return arm_read_description (ARM_FP_TYPE_VFPV3); +} + +void _initialize_arm_netbsd_nat (); +void +_initialize_arm_netbsd_nat () +{ + add_inf_child_target (&the_arm_netbsd_nat_target); +} diff --git a/gdb/arm-netbsd-tdep.c b/gdb/arm-netbsd-tdep.c new file mode 100644 index 00000000000..fa2e4498eca --- /dev/null +++ b/gdb/arm-netbsd-tdep.c @@ -0,0 +1,171 @@ +/* Target-dependent code for NetBSD/arm. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "osabi.h" + +#include "arch/arm.h" +#include "arm-netbsd-tdep.h" +#include "netbsd-tdep.h" +#include "arm-tdep.h" +#include "regset.h" +#include "solib-svr4.h" + +/* Description of the longjmp buffer. */ +#define ARM_NBSD_JB_PC 24 +#define ARM_NBSD_JB_ELEMENT_SIZE ARM_INT_REGISTER_SIZE + +/* For compatibility with previous implementations of GDB on arm/NetBSD, + override the default little-endian breakpoint. */ +static const gdb_byte arm_nbsd_arm_le_breakpoint[] = {0x11, 0x00, 0x00, 0xe6}; +static const gdb_byte arm_nbsd_arm_be_breakpoint[] = {0xe6, 0x00, 0x00, 0x11}; +static const gdb_byte arm_nbsd_thumb_le_breakpoint[] = {0xfe, 0xde}; +static const gdb_byte arm_nbsd_thumb_be_breakpoint[] = {0xde, 0xfe}; + +/* This matches struct reg from NetBSD's sys/arch/arm/include/reg.h: + https://github.com/NetBSD/src/blob/7c13e6e6773bb171f4ed3ed53013e9d24b3c1eac/sys/arch/arm/include/reg.h#L39 + */ +struct arm_nbsd_reg +{ + uint32_t reg[13]; + uint32_t sp; + uint32_t lr; + uint32_t pc; + uint32_t cpsr; +}; + +void +arm_nbsd_supply_gregset (const struct regset *regset, struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const arm_nbsd_reg *gregset = static_cast(gregs); + gdb_assert (len >= sizeof (arm_nbsd_reg)); + + /* Integer registers. */ + for (int i = ARM_A1_REGNUM; i < ARM_SP_REGNUM; i++) + if (regnum == -1 || regnum == i) + regcache->raw_supply (i, (char *) &gregset->reg[i]); + + if (regnum == -1 || regnum == ARM_SP_REGNUM) + regcache->raw_supply (ARM_SP_REGNUM, (char *) &gregset->sp); + + if (regnum == -1 || regnum == ARM_LR_REGNUM) + regcache->raw_supply (ARM_LR_REGNUM, (char *) &gregset->lr); + + if (regnum == -1 || regnum == ARM_PC_REGNUM) + { + CORE_ADDR r_pc = gdbarch_addr_bits_remove (regcache->arch (), gregset->pc); + regcache->raw_supply (ARM_PC_REGNUM, (char *) &r_pc); + } + + if (regnum == -1 || regnum == ARM_PS_REGNUM) + { + if (arm_apcs_32) + regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->cpsr); + else + regcache->raw_supply (ARM_PS_REGNUM, (char *) &gregset->pc); + } +} + +static const struct regset arm_nbsd_regset = { + nullptr, + arm_nbsd_supply_gregset, + /* We don't need a collect function because we only use this reading registers + (via iterate_over_regset_sections and fetch_regs/fetch_register). */ + nullptr, + 0 +}; + +static void +arm_nbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", sizeof (arm_nbsd_reg), sizeof (arm_nbsd_reg), &arm_nbsd_regset, + NULL, cb_data); + /* cbiesinger/2020-02-12 -- as far as I can tell, ARM/NetBSD does + not write any floating point registers into the core file (tested + with NetBSD 9.1_RC1). When it does, this function will need to read them, + and the arm-netbsd gdbarch will need a core_read_description function + to return the right description for them. */ +} + +static void +arm_netbsd_init_abi_common (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + tdep->lowest_pc = 0x8000; + switch (info.byte_order) + { + case BFD_ENDIAN_LITTLE: + tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint; + tdep->thumb_breakpoint = arm_nbsd_thumb_le_breakpoint; + tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint); + tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_le_breakpoint); + break; + + case BFD_ENDIAN_BIG: + tdep->arm_breakpoint = arm_nbsd_arm_be_breakpoint; + tdep->thumb_breakpoint = arm_nbsd_thumb_be_breakpoint; + tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_be_breakpoint); + tdep->thumb_breakpoint_size = sizeof (arm_nbsd_thumb_be_breakpoint); + break; + + default: + internal_error (__FILE__, __LINE__, + _("arm_gdbarch_init: bad byte order for float format")); + } + + tdep->jb_pc = ARM_NBSD_JB_PC; + tdep->jb_elt_size = ARM_NBSD_JB_ELEMENT_SIZE; + + set_gdbarch_iterate_over_regset_sections + (gdbarch, arm_nbsd_iterate_over_regset_sections); + /* Single stepping. */ + set_gdbarch_software_single_step (gdbarch, arm_software_single_step); +} + +static void +arm_netbsd_elf_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + arm_netbsd_init_abi_common (info, gdbarch); + + nbsd_init_abi (info, gdbarch); + + if (tdep->fp_model == ARM_FLOAT_AUTO) + tdep->fp_model = ARM_FLOAT_SOFT_VFP; + + /* NetBSD ELF uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +void _initialize_arm_netbsd_tdep (); +void +_initialize_arm_netbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD, + arm_netbsd_elf_init_abi); +} diff --git a/gdb/arm-netbsd-tdep.h b/gdb/arm-netbsd-tdep.h new file mode 100644 index 00000000000..1b35395031c --- /dev/null +++ b/gdb/arm-netbsd-tdep.h @@ -0,0 +1,27 @@ +/* NetBSD/ARM support. + + Copyright (C) 2020 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 3 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, see . */ + +#ifndef ARM_NBSD_TDEP_H +#define ARM_NBSD_TDEP_H + +void arm_nbsd_supply_gregset + (const struct regset *regset, struct regcache *regcache, + int regnum, const void *gregs, size_t len); + +#endif diff --git a/gdb/configure.nat b/gdb/configure.nat index 3e94a064aeb..ef2218f0b8d 100644 --- a/gdb/configure.nat +++ b/gdb/configure.nat @@ -338,20 +338,20 @@ case ${gdb_host} in ;; mips) # Host: NetBSD/mips - NATDEPFILES="${NATDEPFILES} mips-nbsd-nat.o" + NATDEPFILES="${NATDEPFILES} mips-netbsd-nat.o" ;; pa) # Host: NetBSD/hppa - NATDEPFILES="${NATDEPFILES} nbsd-nat.o hppa-nbsd-nat.o" + NATDEPFILES="${NATDEPFILES} netbsd-nat.o hppa-netbsd-nat.o" ;; powerpc) # Host: NetBSD/powerpc - NATDEPFILES="${NATDEPFILES} ppc-nbsd-nat.o bsd-kvm.o" + NATDEPFILES="${NATDEPFILES} ppc-netbsd-nat.o bsd-kvm.o" LOADLIBES='-lkvm' ;; sh) # Host: NetBSD/sh - NATDEPFILES="${NATDEPFILES} sh-nbsd-nat.o" + NATDEPFILES="${NATDEPFILES} sh-netbsd-nat.o" ;; esac @@ -360,12 +360,12 @@ case ${gdb_host} in case ${gdb_host_cpu} in i386) # Host: NetBSD/amd64 - NATDEPFILES="${NATDEPFILES} nbsd-nat.o amd64-nat.o x86-nat.o \ - nat/x86-dregs.o x86-bsd-nat.o amd64-bsd-nat.o amd64-nbsd-nat.o" + NATDEPFILES="${NATDEPFILES} netbsd-nat.o amd64-nat.o x86-nat.o \ + nat/x86-dregs.o x86-bsd-nat.o amd64-bsd-nat.o amd64-netbsd-nat.o" ;; sparc) # Host: NetBSD/sparc64 - NATDEPFILES="${NATDEPFILES} sparc64-nbsd-nat.o sparc-nat.o \ + NATDEPFILES="${NATDEPFILES} sparc64-netbsd-nat.o sparc-nat.o \ bsd-kvm.o" LOADLIBES='-lkvm' ;; @@ -376,13 +376,13 @@ case ${gdb_host} in case ${gdb_host_cpu} in arm) # Host: NetBSD/arm - NATDEPFILES="${NATDEPFILES} arm-nbsd-nat.o" + NATDEPFILES="${NATDEPFILES} arm-netbsd-nat.o" ;; i386) # Host: NetBSD/i386 ELF - NATDEPFILES="${NATDEPFILES} nbsd-nat.o x86-nat.o \ + NATDEPFILES="${NATDEPFILES} netbsd-nat.o x86-nat.o \ nat/x86-dregs.o \ - x86-bsd-nat.o i386-bsd-nat.o i386-nbsd-nat.o bsd-kvm.o" + x86-bsd-nat.o i386-bsd-nat.o i386-netbsd-nat.o bsd-kvm.o" LOADLIBES='-lkvm' ;; m68k) @@ -392,7 +392,7 @@ case ${gdb_host} in ;; sparc) # Host: NetBSD/sparc ELF - NATDEPFILES="${NATDEPFILES} sparc-nat.o sparc-nbsd-nat.o \ + NATDEPFILES="${NATDEPFILES} sparc-nat.o sparc-netbsd-nat.o \ bsd-kvm.o" LOADLIBES='-lkvm' ;; diff --git a/gdb/configure.tgt b/gdb/configure.tgt index a3e11c4b9b8..d865ecdcb60 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -138,12 +138,12 @@ alpha*-*-linux*) alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu) # Target: NetBSD/alpha gdb_target_obs="alpha-mdebug-tdep.o alpha-bsd-tdep.o \ - alpha-nbsd-tdep.o" + alpha-netbsd-tdep.o" ;; alpha*-*-openbsd*) # Target: OpenBSD/alpha gdb_target_obs="alpha-mdebug-tdep.o alpha-bsd-tdep.o \ - alpha-nbsd-tdep.o alpha-obsd-tdep.o nbsd-tdep.o" + alpha-netbsd-tdep.o alpha-obsd-tdep.o nbsd-tdep.o" ;; am33_2.0*-*-linux*) @@ -177,7 +177,7 @@ arm*-*-freebsd*) ;; arm*-*-netbsd* | arm*-*-knetbsd*-gnu) # Target: NetBSD/arm - gdb_target_obs="arm-nbsd-tdep.o" + gdb_target_obs="arm-netbsd-tdep.o" ;; arm*-*-openbsd*) # Target: OpenBSD/arm @@ -256,7 +256,7 @@ hppa*-*-linux*) ;; hppa*-*-netbsd*) # Target: NetBSD/hppa - gdb_target_obs="hppa-bsd-tdep.o hppa-nbsd-tdep.o solib-svr4.o" + gdb_target_obs="hppa-bsd-tdep.o hppa-netbsd-tdep.o solib-svr4.o" ;; hppa*-*-openbsd*) # Target: OpenBSD/hppa @@ -281,7 +281,7 @@ i[34567]86-*-freebsd* | i[34567]86-*-kfreebsd*-gnu) ;; i[34567]86-*-netbsd* | i[34567]86-*-knetbsd*-gnu) # Target: NetBSD/i386 - gdb_target_obs="i386-bsd-tdep.o i386-nbsd-tdep.o " + gdb_target_obs="i386-bsd-tdep.o i386-netbsd-tdep.o " ;; i[34567]86-*-openbsd*) # Target: OpenBSD/i386 @@ -418,7 +418,7 @@ mips*-*-linux*) ;; mips*-*-netbsd* | mips*-*-knetbsd*-gnu) # Target: MIPS running NetBSD - gdb_target_obs="mips-tdep.o mips-nbsd-tdep.o" + gdb_target_obs="mips-tdep.o mips-netbsd-tdep.o" gdb_sim=../sim/mips/libsim.a ;; mips*-*-freebsd*) @@ -495,7 +495,7 @@ powerpc*-*-freebsd*) powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu) # Target: NetBSD/powerpc - gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc-nbsd-tdep.o \ + gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc-netbsd-tdep.o \ ravenscar-thread.o ppc-ravenscar-thread.o" gdb_sim=../sim/ppc/libsim.a ;; @@ -581,12 +581,12 @@ sh*-*-linux*) ;; sh*-*-netbsdelf* | sh*-*-knetbsd*-gnu) # Target: NetBSD/sh - gdb_target_obs="sh-tdep.o sh-nbsd-tdep.o" + gdb_target_obs="sh-tdep.o sh-netbsd-tdep.o" gdb_sim=../sim/sh/libsim.a ;; sh*-*-openbsd*) # Target: OpenBSD/sh - gdb_target_obs="sh-tdep.o sh-nbsd-tdep.o" + gdb_target_obs="sh-tdep.o sh-netbsd-tdep.o" ;; sh*) # Target: Embedded Renesas Super-H processor @@ -620,25 +620,25 @@ sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu) ;; sparc-*-netbsd* | sparc-*-knetbsd*-gnu) # Target: NetBSD/sparc - gdb_target_obs="sparc-tdep.o sparc-nbsd-tdep.o \ + gdb_target_obs="sparc-tdep.o sparc-netbsd-tdep.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; sparc64-*-netbsd* | sparc64-*-knetbsd*-gnu) # Target: NetBSD/sparc64 - gdb_target_obs="sparc64-tdep.o sparc64-nbsd-tdep.o sparc-tdep.o \ - sparc-nbsd-tdep.o \ + gdb_target_obs="sparc64-tdep.o sparc64-netbsd-tdep.o sparc-tdep.o \ + sparc-netbsd-tdep.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; sparc-*-openbsd*) # Target: OpenBSD/sparc - gdb_target_obs="sparc-tdep.o sparc-nbsd-tdep.o sparc-obsd-tdep.o \ + gdb_target_obs="sparc-tdep.o sparc-netbsd-tdep.o sparc-obsd-tdep.o \ nbsd-tdep.o bsd-uthread.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; sparc64-*-openbsd*) # Target: OpenBSD/sparc64 - gdb_target_obs="sparc64-tdep.o sparc64-nbsd-tdep.o sparc64-obsd-tdep.o \ - sparc-tdep.o sparc-nbsd-tdep.o sparc-obsd-tdep.o \ + gdb_target_obs="sparc64-tdep.o sparc64-netbsd-tdep.o sparc64-obsd-tdep.o \ + sparc-tdep.o sparc-netbsd-tdep.o sparc-obsd-tdep.o \ nbsd-tdep.o bsd-uthread.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; @@ -746,7 +746,7 @@ x86_64-*-mingw* | x86_64-*-cygwin*) ;; x86_64-*-netbsd* | x86_64-*-knetbsd*-gnu) # Target: NetBSD/amd64 - gdb_target_obs="amd64-nbsd-tdep.o ${i386_tobjs}" + gdb_target_obs="amd64-netbsd-tdep.o ${i386_tobjs}" ;; x86_64-*-openbsd*) # Target: OpenBSD/amd64 diff --git a/gdb/hppa-nbsd-nat.c b/gdb/hppa-nbsd-nat.c deleted file mode 100644 index c35f30daa8e..00000000000 --- a/gdb/hppa-nbsd-nat.c +++ /dev/null @@ -1,238 +0,0 @@ -/* Native-dependent code for NetBSD/hppa. - - Copyright (C) 2008-2020 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 3 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, see . */ - -#include "defs.h" -#include "inferior.h" -#include "regcache.h" - -#include -#include -#include - -#include "hppa-tdep.h" -#include "inf-ptrace.h" - -#include "nbsd-nat.h" - -class hppa_nbsd_nat_target final : public nbsd_nat_target -{ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; -}; - -static hppa_nbsd_nat_target the_hppa_nbsd_nat_target; - -static int -hppanbsd_gregset_supplies_p (int regnum) -{ - return ((regnum >= HPPA_R0_REGNUM && regnum <= HPPA_R31_REGNUM) || - (regnum >= HPPA_SAR_REGNUM && regnum <= HPPA_PCSQ_TAIL_REGNUM) || - regnum == HPPA_IPSW_REGNUM || - (regnum >= HPPA_SR4_REGNUM && regnum <= HPPA_SR4_REGNUM + 5)); -} - -static int -hppanbsd_fpregset_supplies_p (int regnum) -{ - return (regnum >= HPPA_FP0_REGNUM && regnum <= HPPA_FP31R_REGNUM); -} - -/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ - -static void -hppanbsd_supply_gregset (struct regcache *regcache, const void *gregs) -{ - const char *regs = gregs; - const int *r = gregs; - int regnum; - - for (regnum = HPPA_R1_REGNUM; regnum <= HPPA_R31_REGNUM; regnum++) - regcache->raw_supply (regnum, regs + regnum * 4); - - regcache->raw_supply (HPPA_SAR_REGNUM, regs + 32 * 4); - regcache->raw_supply (HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); - regcache->raw_supply (HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); - regcache->raw_supply (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - regcache->raw_supply (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - regcache->raw_supply (HPPA_IPSW_REGNUM, regs); - regcache->raw_supply (HPPA_SR4_REGNUM, regs + 41 * 4); - regcache->raw_supply (HPPA_SR4_REGNUM + 1, regs + 37 * 4); - regcache->raw_supply (HPPA_SR4_REGNUM + 2, regs + 38 * 4); - regcache->raw_supply (HPPA_SR4_REGNUM + 3, regs + 39 * 4); - regcache->raw_supply (HPPA_SR4_REGNUM + 4, regs + 40 * 4); -} - -/* Supply the floating-point registers stored in FPREGS to REGCACHE. */ - -static void -hppanbsd_supply_fpregset (struct regcache *regcache, const void *fpregs) -{ - const char *regs = fpregs; - int regnum; - - for (regnum = HPPA_FP0_REGNUM; regnum <= HPPA_FP31R_REGNUM; - regnum += 2, regs += 8) - { - regcache->raw_supply (regnum, regs); - regcache->raw_supply (regnum + 1, regs + 4); - } -} - -/* Collect the general-purpose registers from REGCACHE and store them - in GREGS. */ - -static void -hppanbsd_collect_gregset (const struct regcache *regcache, - void *gregs, int regnum) -{ - char *regs = gregs; - int *r = gregs; - int i; - - for (i = HPPA_R1_REGNUM; i <= HPPA_R31_REGNUM; i++) - { - if (regnum == -1 || regnum == i) - regcache->raw_collect (i, regs + i * 4); - } - - if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) - regcache->raw_collect (HPPA_IPSW_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache->raw_collect (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache->raw_collect (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - - if (regnum == -1 || regnum == HPPA_SAR_REGNUM) - regcache->raw_collect (HPPA_SAR_REGNUM, regs + 32 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) - regcache->raw_collect (HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) - regcache->raw_collect (HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache->raw_collect (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache->raw_collect (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) - regcache->raw_collect (HPPA_IPSW_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM) - regcache->raw_collect (HPPA_SR4_REGNUM, regs + 41 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 1) - regcache->raw_collect (HPPA_SR4_REGNUM + 1, regs + 37 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 2) - regcache->raw_collect (HPPA_SR4_REGNUM + 2, regs + 38 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 3) - regcache->raw_collect (HPPA_SR4_REGNUM + 3, regs + 39 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 4) - regcache->raw_collect (HPPA_SR4_REGNUM + 4, regs + 40 * 4); -} - -/* Collect the floating-point registers from REGCACHE and store them - in FPREGS. */ - -static void -hppanbsd_collect_fpregset (struct regcache *regcache, - void *fpregs, int regnum) -{ - char *regs = fpregs; - int i; - - for (i = HPPA_FP0_REGNUM; i <= HPPA_FP31R_REGNUM; i += 2, regs += 8) - { - if (regnum == -1 || regnum == i || regnum == i + 1) - { - regcache->raw_collect (i, regs); - regcache->raw_collect (i + 1, regs + 4); - } - } -} - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers (including the floating-point registers). */ - -void -hppa_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum) - -{ - pid_t pid = regcache->ptid ().pid (); - int lwp = regcache->ptid ().lwp (); - - if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) - perror_with_name (_("Couldn't get registers")); - - hppanbsd_supply_gregset (regcache, ®s); - } - - if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) - perror_with_name (_("Couldn't get floating point status")); - - hppanbsd_supply_fpregset (regcache, &fpregs); - } -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers (including the floating-point registers). */ - -void -hppa_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum) -{ - pid_t pid = regcache->ptid ().pid (); - int lwp = regcache->ptid ().lwp (); - - if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) - perror_with_name (_("Couldn't get registers")); - - hppanbsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) - perror_with_name (_("Couldn't write registers")); - } - - if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) - perror_with_name (_("Couldn't get floating point status")); - - hppanbsd_collect_fpregset (regcache, &fpregs, regnum); - - if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - -void _initialize_hppanbsd_nat (); -void -_initialize_hppanbsd_nat () -{ - add_inf_child_target (&the_hppa_nbsd_nat_target); -} diff --git a/gdb/hppa-nbsd-tdep.c b/gdb/hppa-nbsd-tdep.c deleted file mode 100644 index 5309b1976fd..00000000000 --- a/gdb/hppa-nbsd-tdep.c +++ /dev/null @@ -1,220 +0,0 @@ -/* Target-dependent code for NetBSD/hppa - - Copyright (C) 2008-2020 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 3 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, see . */ - -#include "defs.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" - -#include "trad-frame.h" -#include "tramp-frame.h" - -#include "hppa-tdep.h" -#include "hppa-bsd-tdep.h" -#include "nbsd-tdep.h" -#include "gdbarch.h" - -/* From . */ -static int hppanbsd_mc_reg_offset[] = -{ - /* r0 ... r31 */ - -1, 1 * 4, 2 * 4, 3 * 4, - 4 * 4, 5 * 4, 6 * 4, 7 * 4, - 8 * 4, 9 * 4, 10 * 4, 11 * 4, - 12 * 4, 13 * 4, 14 * 4, 15 * 4, - 16 * 4, 17 * 4, 18 * 4, 19 * 4, - 20 * 4, 21 * 4, 22 * 4, 23 * 4, - 24 * 4, 25 * 4, 26 * 4, 27 * 4, - 28 * 4, 29 * 4, 30 * 4, 31 * 4, - - 32 * 4, /* HPPA_SAR_REGNUM */ - 35 * 4, /* HPPA_PCOQ_HEAD_REGNUM */ - 33 * 4, /* HPPA_PCSQ_HEAD_REGNUM */ - 36 * 4, /* HPPA_PCOQ_TAIL_REGNUM */ - 34 * 4, /* HPPA_PCSQ_TAIL_REGNUM */ - -1, /* HPPA_EIEM_REGNUM */ - -1, /* HPPA_IIR_REGNUM */ - -1, /* HPPA_ISR_REGNUM */ - -1, /* HPPA_IOR_REGNUM */ - 0 * 4, /* HPPA_IPSW_REGNUM */ - -1, /* spare? */ - 41 * 4, /* HPPA_SR4_REGNUM */ - 37 * 4, /* sr0 */ - 38 * 4, /* sr1 */ - 39 * 4, /* sr2 */ - 40 * 4, /* sr3 */ - - /* more tbd */ -}; - -static void hppanbsd_sigtramp_cache_init (const struct tramp_frame *, - struct frame_info *, - struct trad_frame_cache *, - CORE_ADDR); - -static const struct tramp_frame hppanbsd_sigtramp_si4 = -{ - SIGTRAMP_FRAME, - 4, - { - { 0xc7d7c012, ULONGEST_MAX }, /* bb,>=,n %arg3, 30, 1f */ - { 0xd6e01c1e, ULONGEST_MAX }, /* depwi 0,31,2,%arg3 */ - { 0x0ee81093, ULONGEST_MAX }, /* ldw 4(%arg3), %r19 */ - { 0x0ee01097, ULONGEST_MAX }, /* ldw 0(%arg3), %arg3 */ - /* 1: */ - { 0xe8404000, ULONGEST_MAX }, /* blr %r0, %rp */ - { 0xeae0c002, ULONGEST_MAX }, /* bv,n %r0(%arg3) */ - { 0x08000240, ULONGEST_MAX }, /* nop */ - - { 0x0803025a, ULONGEST_MAX }, /* copy %r3, %arg0 */ - { 0x20200801, ULONGEST_MAX }, /* ldil -40000000, %r1 */ - { 0xe420e008, ULONGEST_MAX }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ - { 0x34160268, ULONGEST_MAX }, /* ldi 134, %t1 ; SYS_setcontext */ - - { 0x081c025a, ULONGEST_MAX }, /* copy ret0, %arg0 */ - { 0x20200801, ULONGEST_MAX }, /* ldil -40000000, %r1 */ - { 0xe420e008, ULONGEST_MAX }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ - { 0x34160002, ULONGEST_MAX }, /* ldi 1, %t1 ; SYS_exit */ - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - hppanbsd_sigtramp_cache_init -}; - - -static void -hppanbsd_sigtramp_cache_init (const struct tramp_frame *self, - struct frame_info *this_frame, - struct trad_frame_cache *this_cache, - CORE_ADDR func) -{ - CORE_ADDR sp = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM); - CORE_ADDR base; - int *reg_offset; - int num_regs; - int i; - - reg_offset = hppanbsd_mc_reg_offset; - num_regs = ARRAY_SIZE (hppanbsd_mc_reg_offset); - - /* frame pointer */ - base = sp - 0x280; - /* offsetof(struct sigframe_siginfo, sf_uc) = 128 */ - base += 128; - /* offsetof(ucontext_t, uc_mcontext) == 40 */ - base += 40; - - for (i = 0; i < num_regs; i++) - if (reg_offset[i] != -1) - trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]); - - /* Construct the frame ID using the function start. */ - trad_frame_set_id (this_cache, frame_id_build (sp, func)); -} - -/* Core file support. */ - -/* Sizeof `struct reg' in . */ -#define HPPANBSD_SIZEOF_GREGS (44 * 4) - -static int hppanbsd_reg_offset[] = -{ - /* r0 ... r31 */ - -1, 1 * 4, 2 * 4, 3 * 4, - 4 * 4, 5 * 4, 6 * 4, 7 * 4, - 8 * 4, 9 * 4, 10 * 4, 11 * 4, - 12 * 4, 13 * 4, 14 * 4, 15 * 4, - 16 * 4, 17 * 4, 18 * 4, 19 * 4, - 20 * 4, 21 * 4, 22 * 4, 23 * 4, - 24 * 4, 25 * 4, 26 * 4, 27 * 4, - 28 * 4, 29 * 4, 30 * 4, 31 * 4, - - 32 * 4, /* HPPA_SAR_REGNUM */ - 35 * 4, /* HPPA_PCOQ_HEAD_REGNUM */ - 33 * 4, /* HPPA_PCSQ_HEAD_REGNUM */ - 36 * 4, /* HPPA_PCOQ_TAIL_REGNUM */ - 34 * 4, /* HPPA_PCSQ_TAIL_REGNUM */ - -1, /* HPPA_EIEM_REGNUM */ - -1, /* HPPA_IIR_REGNUM */ - -1, /* HPPA_ISR_REGNUM */ - -1, /* HPPA_IOR_REGNUM */ - 0 * 4, /* HPPA_IPSW_REGNUM */ -}; - -/* Supply register REGNUM from the buffer specified by GREGS and LEN - in the general-purpose register set REGSET to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -static void -hppanbsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - const gdb_byte *regs = (const gdb_byte *) gregs; - int i; - - gdb_assert (len >= HPPANBSD_SIZEOF_GREGS); - - for (i = 0; i < ARRAY_SIZE (hppanbsd_reg_offset); i++) - if (hppanbsd_reg_offset[i] != -1) - if (regnum == -1 || regnum == i) - regcache->raw_supply (i, regs + hppanbsd_reg_offset[i]); -} - -/* NetBSD/hppa register set. */ - -static const struct regset hppanbsd_gregset = -{ - NULL, - hppanbsd_supply_gregset -}; - -/* Iterate over supported core file register note sections. */ - -static void -hppanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", HPPANBSD_SIZEOF_GREGS, HPPANBSD_SIZEOF_GREGS, &hppanbsd_gregset, - NULL, cb_data); -} - -static void -hppanbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* Obviously NetBSD is BSD-based. */ - hppabsd_init_abi (info, gdbarch); - - nbsd_init_abi (info, gdbarch); - - /* Core file support. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, hppanbsd_iterate_over_regset_sections); - - tramp_frame_prepend_unwinder (gdbarch, &hppanbsd_sigtramp_si4); -} - -void _initialize_hppanbsd_tdep (); -void -_initialize_hppanbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD, - hppanbsd_init_abi); -} diff --git a/gdb/hppa-netbsd-nat.c b/gdb/hppa-netbsd-nat.c new file mode 100644 index 00000000000..a3a2e32a3a2 --- /dev/null +++ b/gdb/hppa-netbsd-nat.c @@ -0,0 +1,238 @@ +/* Native-dependent code for NetBSD/hppa. + + Copyright (C) 2008-2020 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 3 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, see . */ + +#include "defs.h" +#include "inferior.h" +#include "regcache.h" + +#include +#include +#include + +#include "hppa-tdep.h" +#include "inf-ptrace.h" + +#include "netbsd-nat.h" + +class hppa_nbsd_nat_target final : public nbsd_nat_target +{ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; +}; + +static hppa_nbsd_nat_target the_hppa_nbsd_nat_target; + +static int +hppanbsd_gregset_supplies_p (int regnum) +{ + return ((regnum >= HPPA_R0_REGNUM && regnum <= HPPA_R31_REGNUM) || + (regnum >= HPPA_SAR_REGNUM && regnum <= HPPA_PCSQ_TAIL_REGNUM) || + regnum == HPPA_IPSW_REGNUM || + (regnum >= HPPA_SR4_REGNUM && regnum <= HPPA_SR4_REGNUM + 5)); +} + +static int +hppanbsd_fpregset_supplies_p (int regnum) +{ + return (regnum >= HPPA_FP0_REGNUM && regnum <= HPPA_FP31R_REGNUM); +} + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +hppanbsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + const int *r = gregs; + int regnum; + + for (regnum = HPPA_R1_REGNUM; regnum <= HPPA_R31_REGNUM; regnum++) + regcache->raw_supply (regnum, regs + regnum * 4); + + regcache->raw_supply (HPPA_SAR_REGNUM, regs + 32 * 4); + regcache->raw_supply (HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); + regcache->raw_supply (HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); + regcache->raw_supply (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + regcache->raw_supply (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + regcache->raw_supply (HPPA_IPSW_REGNUM, regs); + regcache->raw_supply (HPPA_SR4_REGNUM, regs + 41 * 4); + regcache->raw_supply (HPPA_SR4_REGNUM + 1, regs + 37 * 4); + regcache->raw_supply (HPPA_SR4_REGNUM + 2, regs + 38 * 4); + regcache->raw_supply (HPPA_SR4_REGNUM + 3, regs + 39 * 4); + regcache->raw_supply (HPPA_SR4_REGNUM + 4, regs + 40 * 4); +} + +/* Supply the floating-point registers stored in FPREGS to REGCACHE. */ + +static void +hppanbsd_supply_fpregset (struct regcache *regcache, const void *fpregs) +{ + const char *regs = fpregs; + int regnum; + + for (regnum = HPPA_FP0_REGNUM; regnum <= HPPA_FP31R_REGNUM; + regnum += 2, regs += 8) + { + regcache->raw_supply (regnum, regs); + regcache->raw_supply (regnum + 1, regs + 4); + } +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +hppanbsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int *r = gregs; + int i; + + for (i = HPPA_R1_REGNUM; i <= HPPA_R31_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache->raw_collect (i, regs + i * 4); + } + + if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) + regcache->raw_collect (HPPA_IPSW_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache->raw_collect (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache->raw_collect (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache->raw_collect (HPPA_SAR_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) + regcache->raw_collect (HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) + regcache->raw_collect (HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache->raw_collect (HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache->raw_collect (HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) + regcache->raw_collect (HPPA_IPSW_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM) + regcache->raw_collect (HPPA_SR4_REGNUM, regs + 41 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 1) + regcache->raw_collect (HPPA_SR4_REGNUM + 1, regs + 37 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 2) + regcache->raw_collect (HPPA_SR4_REGNUM + 2, regs + 38 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 3) + regcache->raw_collect (HPPA_SR4_REGNUM + 3, regs + 39 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 4) + regcache->raw_collect (HPPA_SR4_REGNUM + 4, regs + 40 * 4); +} + +/* Collect the floating-point registers from REGCACHE and store them + in FPREGS. */ + +static void +hppanbsd_collect_fpregset (struct regcache *regcache, + void *fpregs, int regnum) +{ + char *regs = fpregs; + int i; + + for (i = HPPA_FP0_REGNUM; i <= HPPA_FP31R_REGNUM; i += 2, regs += 8) + { + if (regnum == -1 || regnum == i || regnum == i + 1) + { + regcache->raw_collect (i, regs); + regcache->raw_collect (i + 1, regs + 4); + } + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +void +hppa_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum) + +{ + pid_t pid = regcache->ptid ().pid (); + int lwp = regcache->ptid ().lwp (); + + if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) + perror_with_name (_("Couldn't get registers")); + + hppanbsd_supply_gregset (regcache, ®s); + } + + if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) + perror_with_name (_("Couldn't get floating point status")); + + hppanbsd_supply_fpregset (regcache, &fpregs); + } +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers (including the floating-point registers). */ + +void +hppa_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum) +{ + pid_t pid = regcache->ptid ().pid (); + int lwp = regcache->ptid ().lwp (); + + if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) + perror_with_name (_("Couldn't get registers")); + + hppanbsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) + perror_with_name (_("Couldn't get floating point status")); + + hppanbsd_collect_fpregset (regcache, &fpregs, regnum); + + if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + +void _initialize_hppanbsd_nat (); +void +_initialize_hppanbsd_nat () +{ + add_inf_child_target (&the_hppa_nbsd_nat_target); +} diff --git a/gdb/hppa-netbsd-tdep.c b/gdb/hppa-netbsd-tdep.c new file mode 100644 index 00000000000..5a5520744b4 --- /dev/null +++ b/gdb/hppa-netbsd-tdep.c @@ -0,0 +1,220 @@ +/* Target-dependent code for NetBSD/hppa + + Copyright (C) 2008-2020 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 3 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, see . */ + +#include "defs.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" + +#include "trad-frame.h" +#include "tramp-frame.h" + +#include "hppa-tdep.h" +#include "hppa-bsd-tdep.h" +#include "netbsd-tdep.h" +#include "gdbarch.h" + +/* From . */ +static int hppanbsd_mc_reg_offset[] = +{ + /* r0 ... r31 */ + -1, 1 * 4, 2 * 4, 3 * 4, + 4 * 4, 5 * 4, 6 * 4, 7 * 4, + 8 * 4, 9 * 4, 10 * 4, 11 * 4, + 12 * 4, 13 * 4, 14 * 4, 15 * 4, + 16 * 4, 17 * 4, 18 * 4, 19 * 4, + 20 * 4, 21 * 4, 22 * 4, 23 * 4, + 24 * 4, 25 * 4, 26 * 4, 27 * 4, + 28 * 4, 29 * 4, 30 * 4, 31 * 4, + + 32 * 4, /* HPPA_SAR_REGNUM */ + 35 * 4, /* HPPA_PCOQ_HEAD_REGNUM */ + 33 * 4, /* HPPA_PCSQ_HEAD_REGNUM */ + 36 * 4, /* HPPA_PCOQ_TAIL_REGNUM */ + 34 * 4, /* HPPA_PCSQ_TAIL_REGNUM */ + -1, /* HPPA_EIEM_REGNUM */ + -1, /* HPPA_IIR_REGNUM */ + -1, /* HPPA_ISR_REGNUM */ + -1, /* HPPA_IOR_REGNUM */ + 0 * 4, /* HPPA_IPSW_REGNUM */ + -1, /* spare? */ + 41 * 4, /* HPPA_SR4_REGNUM */ + 37 * 4, /* sr0 */ + 38 * 4, /* sr1 */ + 39 * 4, /* sr2 */ + 40 * 4, /* sr3 */ + + /* more tbd */ +}; + +static void hppanbsd_sigtramp_cache_init (const struct tramp_frame *, + struct frame_info *, + struct trad_frame_cache *, + CORE_ADDR); + +static const struct tramp_frame hppanbsd_sigtramp_si4 = +{ + SIGTRAMP_FRAME, + 4, + { + { 0xc7d7c012, ULONGEST_MAX }, /* bb,>=,n %arg3, 30, 1f */ + { 0xd6e01c1e, ULONGEST_MAX }, /* depwi 0,31,2,%arg3 */ + { 0x0ee81093, ULONGEST_MAX }, /* ldw 4(%arg3), %r19 */ + { 0x0ee01097, ULONGEST_MAX }, /* ldw 0(%arg3), %arg3 */ + /* 1: */ + { 0xe8404000, ULONGEST_MAX }, /* blr %r0, %rp */ + { 0xeae0c002, ULONGEST_MAX }, /* bv,n %r0(%arg3) */ + { 0x08000240, ULONGEST_MAX }, /* nop */ + + { 0x0803025a, ULONGEST_MAX }, /* copy %r3, %arg0 */ + { 0x20200801, ULONGEST_MAX }, /* ldil -40000000, %r1 */ + { 0xe420e008, ULONGEST_MAX }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ + { 0x34160268, ULONGEST_MAX }, /* ldi 134, %t1 ; SYS_setcontext */ + + { 0x081c025a, ULONGEST_MAX }, /* copy ret0, %arg0 */ + { 0x20200801, ULONGEST_MAX }, /* ldil -40000000, %r1 */ + { 0xe420e008, ULONGEST_MAX }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ + { 0x34160002, ULONGEST_MAX }, /* ldi 1, %t1 ; SYS_exit */ + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + hppanbsd_sigtramp_cache_init +}; + + +static void +hppanbsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + CORE_ADDR sp = get_frame_register_unsigned (this_frame, HPPA_SP_REGNUM); + CORE_ADDR base; + int *reg_offset; + int num_regs; + int i; + + reg_offset = hppanbsd_mc_reg_offset; + num_regs = ARRAY_SIZE (hppanbsd_mc_reg_offset); + + /* frame pointer */ + base = sp - 0x280; + /* offsetof(struct sigframe_siginfo, sf_uc) = 128 */ + base += 128; + /* offsetof(ucontext_t, uc_mcontext) == 40 */ + base += 40; + + for (i = 0; i < num_regs; i++) + if (reg_offset[i] != -1) + trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]); + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (this_cache, frame_id_build (sp, func)); +} + +/* Core file support. */ + +/* Sizeof `struct reg' in . */ +#define HPPANBSD_SIZEOF_GREGS (44 * 4) + +static int hppanbsd_reg_offset[] = +{ + /* r0 ... r31 */ + -1, 1 * 4, 2 * 4, 3 * 4, + 4 * 4, 5 * 4, 6 * 4, 7 * 4, + 8 * 4, 9 * 4, 10 * 4, 11 * 4, + 12 * 4, 13 * 4, 14 * 4, 15 * 4, + 16 * 4, 17 * 4, 18 * 4, 19 * 4, + 20 * 4, 21 * 4, 22 * 4, 23 * 4, + 24 * 4, 25 * 4, 26 * 4, 27 * 4, + 28 * 4, 29 * 4, 30 * 4, 31 * 4, + + 32 * 4, /* HPPA_SAR_REGNUM */ + 35 * 4, /* HPPA_PCOQ_HEAD_REGNUM */ + 33 * 4, /* HPPA_PCSQ_HEAD_REGNUM */ + 36 * 4, /* HPPA_PCOQ_TAIL_REGNUM */ + 34 * 4, /* HPPA_PCSQ_TAIL_REGNUM */ + -1, /* HPPA_EIEM_REGNUM */ + -1, /* HPPA_IIR_REGNUM */ + -1, /* HPPA_ISR_REGNUM */ + -1, /* HPPA_IOR_REGNUM */ + 0 * 4, /* HPPA_IPSW_REGNUM */ +}; + +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +hppanbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const gdb_byte *regs = (const gdb_byte *) gregs; + int i; + + gdb_assert (len >= HPPANBSD_SIZEOF_GREGS); + + for (i = 0; i < ARRAY_SIZE (hppanbsd_reg_offset); i++) + if (hppanbsd_reg_offset[i] != -1) + if (regnum == -1 || regnum == i) + regcache->raw_supply (i, regs + hppanbsd_reg_offset[i]); +} + +/* NetBSD/hppa register set. */ + +static const struct regset hppanbsd_gregset = +{ + NULL, + hppanbsd_supply_gregset +}; + +/* Iterate over supported core file register note sections. */ + +static void +hppanbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", HPPANBSD_SIZEOF_GREGS, HPPANBSD_SIZEOF_GREGS, &hppanbsd_gregset, + NULL, cb_data); +} + +static void +hppanbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* Obviously NetBSD is BSD-based. */ + hppabsd_init_abi (info, gdbarch); + + nbsd_init_abi (info, gdbarch); + + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, hppanbsd_iterate_over_regset_sections); + + tramp_frame_prepend_unwinder (gdbarch, &hppanbsd_sigtramp_si4); +} + +void _initialize_hppanbsd_tdep (); +void +_initialize_hppanbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD, + hppanbsd_init_abi); +} diff --git a/gdb/i386-nbsd-nat.c b/gdb/i386-nbsd-nat.c deleted file mode 100644 index ac775c1ff84..00000000000 --- a/gdb/i386-nbsd-nat.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Native-dependent code for NetBSD/i386. - - Copyright (C) 2004-2020 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 3 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, see . */ - -#include "defs.h" -#include "gdbcore.h" -#include "regcache.h" -#include "target.h" - -#include "i386-tdep.h" -#include "i386-bsd-nat.h" - -/* Support for debugging kernel virtual memory images. */ - -#include -#include -#include - -#include "nbsd-nat.h" -#include "bsd-kvm.h" - -static int -i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - struct switchframe sf; - - /* The following is true for NetBSD 1.6.2: - - The pcb contains %esp and %ebp at the point of the context switch - in cpu_switch(). At that point we have a stack frame as - described by `struct switchframe', which for NetBSD 1.6.2 has the - following layout: - - interrupt level - %edi - %esi - %ebx - %eip - - we reconstruct the register state as it would look when we just - returned from cpu_switch(). */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_esp == 0) - return 0; - - read_memory (pcb->pcb_esp, (gdb_byte *)&sf, sizeof sf); - pcb->pcb_esp += sizeof (struct switchframe); - regcache->raw_supply (I386_EDI_REGNUM, &sf.sf_edi); - regcache->raw_supply (I386_ESI_REGNUM, &sf.sf_esi); - regcache->raw_supply (I386_EBP_REGNUM, &pcb->pcb_ebp); - regcache->raw_supply (I386_ESP_REGNUM, &pcb->pcb_esp); - regcache->raw_supply (I386_EBX_REGNUM, &sf.sf_ebx); - regcache->raw_supply (I386_EIP_REGNUM, &sf.sf_eip); - - return 1; -} - -static i386_bsd_nat_target the_i386_nbsd_nat_target; - -void _initialize_i386nbsd_nat (); -void -_initialize_i386nbsd_nat () -{ - add_inf_child_target (&the_i386_nbsd_nat_target); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (i386nbsd_supply_pcb); -} diff --git a/gdb/i386-nbsd-tdep.c b/gdb/i386-nbsd-tdep.c deleted file mode 100644 index 82772b48064..00000000000 --- a/gdb/i386-nbsd-tdep.c +++ /dev/null @@ -1,432 +0,0 @@ -/* Target-dependent code for NetBSD/i386. - - Copyright (C) 1988-2020 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 3 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, see . */ - -#include "defs.h" -#include "arch-utils.h" -#include "frame.h" -#include "gdbcore.h" -#include "regcache.h" -#include "regset.h" -#include "osabi.h" -#include "symtab.h" -#include "trad-frame.h" -#include "tramp-frame.h" - -#include "i386-tdep.h" -#include "i387-tdep.h" -#include "nbsd-tdep.h" -#include "solib-svr4.h" - -/* From . */ -static int i386nbsd_r_reg_offset[] = -{ - 0 * 4, /* %eax */ - 1 * 4, /* %ecx */ - 2 * 4, /* %edx */ - 3 * 4, /* %ebx */ - 4 * 4, /* %esp */ - 5 * 4, /* %ebp */ - 6 * 4, /* %esi */ - 7 * 4, /* %edi */ - 8 * 4, /* %eip */ - 9 * 4, /* %eflags */ - 10 * 4, /* %cs */ - 11 * 4, /* %ss */ - 12 * 4, /* %ds */ - 13 * 4, /* %es */ - 14 * 4, /* %fs */ - 15 * 4 /* %gs */ -}; - -/* From . */ -static int i386nbsd_sc_reg_offset[] = -{ - 10 * 4, /* %eax */ - 9 * 4, /* %ecx */ - 8 * 4, /* %edx */ - 7 * 4, /* %ebx */ - 14 * 4, /* %esp */ - 6 * 4, /* %ebp */ - 5 * 4, /* %esi */ - 4 * 4, /* %edi */ - 11 * 4, /* %eip */ - 13 * 4, /* %eflags */ - 12 * 4, /* %cs */ - 15 * 4, /* %ss */ - 3 * 4, /* %ds */ - 2 * 4, /* %es */ - 1 * 4, /* %fs */ - 0 * 4 /* %gs */ -}; - -/* From . */ -int i386nbsd_mc_reg_offset[] = -{ - 11 * 4, /* %eax */ - 10 * 4, /* %ecx */ - 9 * 4, /* %edx */ - 8 * 4, /* %ebx */ - 7 * 4, /* %esp */ - 6 * 4, /* %ebp */ - 5 * 4, /* %esi */ - 4 * 4, /* %edi */ - 14 * 4, /* %eip */ - 16 * 4, /* %eflags */ - 15 * 4, /* %cs */ - 18 * 4, /* %ss */ - 3 * 4, /* %ds */ - 2 * 4, /* %es */ - 1 * 4, /* %fs */ - 0 * 4 /* %gs */ -}; - -static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *, - struct frame_info *, - struct trad_frame_cache *, - CORE_ADDR); - -static const struct tramp_frame i386nbsd_sigtramp_sc16 = -{ - SIGTRAMP_FRAME, - 1, - { - /* leal 0x10(%esp), %eax */ - { 0x8d, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x10, ULONGEST_MAX }, - - /* pushl %eax */ - { 0x50, ULONGEST_MAX }, - - /* pushl %eax */ - { 0x50, ULONGEST_MAX }, - - /* movl $0x127, %eax # __sigreturn14 */ - { 0xb8, ULONGEST_MAX }, - { 0x27, ULONGEST_MAX }, - {0x01, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - - /* movl $0x1, %eax # exit */ - { 0xb8, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_sc2 = -{ - SIGTRAMP_FRAME, - 1, - { - /* leal 0x0c(%esp), %eax */ - { 0x8d, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x0c, ULONGEST_MAX }, - /* movl %eax, 0x4(%esp) */ - { 0x89, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - /* movl $0x127, %eax # __sigreturn14 */ - { 0xb8, ULONGEST_MAX }, - { 0x27, ULONGEST_MAX }, - {0x01, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - /* movl %eax, 0x4(%esp) */ - { 0x89, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - /* movl $0x1, %eax */ - { 0xb8, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_si2 = -{ - SIGTRAMP_FRAME, - 1, - { - /* movl 8(%esp),%eax */ - { 0x8b, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x08, ULONGEST_MAX }, - /* movl %eax, 0x4(%esp) */ - { 0x89, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - /* movl $0x134, %eax # setcontext */ - { 0xb8, ULONGEST_MAX }, - { 0x34, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX }, - /* movl %eax, 0x4(%esp) */ - { 0x89, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - /* movl $0x1, %eax */ - { 0xb8, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX }, - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_si31 = -{ - SIGTRAMP_FRAME, - 1, - { - /* leal 0x8c(%esp), %eax */ - { 0x8d, ULONGEST_MAX }, - { 0x84, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x8c, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - /* movl %eax, 0x4(%esp) */ - { 0x89, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - /* movl $0x134, %eax # setcontext */ - { 0xb8, ULONGEST_MAX }, - { 0x34, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - /* movl %eax, 0x4(%esp) */ - { 0x89, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - /* movl $0x1, %eax */ - { 0xb8, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_si4 = -{ - SIGTRAMP_FRAME, - 1, - { - /* leal 0x8c(%esp), %eax */ - { 0x8d, ULONGEST_MAX }, - { 0x84, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x8c, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - /* movl %eax, 0x4(%esp) */ - { 0x89, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - /* movl $0x134, %eax # setcontext */ - { 0xb8, ULONGEST_MAX }, - { 0x34, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - { 0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - /* movl $0xffffffff,0x4(%esp) */ - { 0xc7, ULONGEST_MAX }, - { 0x44, ULONGEST_MAX }, - { 0x24, ULONGEST_MAX }, - { 0x04, ULONGEST_MAX }, - { 0xff, ULONGEST_MAX }, - { 0xff, ULONGEST_MAX }, - { 0xff, ULONGEST_MAX }, - { 0xff, ULONGEST_MAX }, - /* movl $0x1, %eax */ - { 0xb8, ULONGEST_MAX }, - { 0x01, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - {0x00, ULONGEST_MAX }, - /* int $0x80 */ - { 0xcd, ULONGEST_MAX }, - { 0x80, ULONGEST_MAX}, - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - i386nbsd_sigtramp_cache_init -}; - -static void -i386nbsd_sigtramp_cache_init (const struct tramp_frame *self, - struct frame_info *this_frame, - struct trad_frame_cache *this_cache, - CORE_ADDR func) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); - CORE_ADDR base; - int *reg_offset; - int num_regs; - int i; - - if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2) - { - reg_offset = i386nbsd_sc_reg_offset; - num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset); - - /* Read in the sigcontext address. */ - base = read_memory_unsigned_integer (sp + 8, 4, byte_order); - } - else - { - reg_offset = i386nbsd_mc_reg_offset; - num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset); - - /* Read in the ucontext address. */ - base = read_memory_unsigned_integer (sp + 8, 4, byte_order); - /* offsetof(ucontext_t, uc_mcontext) == 36 */ - base += 36; - } - - for (i = 0; i < num_regs; i++) - if (reg_offset[i] != -1) - trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]); - - /* Construct the frame ID using the function start. */ - trad_frame_set_id (this_cache, frame_id_build (sp, func)); -} - - -static void -i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Obviously NetBSD is BSD-based. */ - i386bsd_init_abi (info, gdbarch); - - nbsd_init_abi (info, gdbarch); - - /* NetBSD has a different `struct reg'. */ - tdep->gregset_reg_offset = i386nbsd_r_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset); - tdep->sizeof_gregset = 16 * 4; - - /* NetBSD uses -freg-struct-return by default. */ - tdep->struct_return = reg_struct_return; - - /* NetBSD uses tramp_frame sniffers for signal trampolines. */ - tdep->sigcontext_addr= 0; - tdep->sigtramp_start = 0; - tdep->sigtramp_end = 0; - tdep->sigtramp_p = 0; - tdep->sc_reg_offset = 0; - tdep->sc_num_regs = 0; - - tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16); - tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2); - tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2); - tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31); - tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4); -} - -/* NetBSD ELF. */ - -static void -i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* It's still NetBSD. */ - i386nbsd_init_abi (info, gdbarch); - - /* But ELF-based. */ - i386_elf_init_abi (info, gdbarch); - - /* NetBSD ELF uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); - - /* NetBSD ELF uses -fpcc-struct-return by default. */ - tdep->struct_return = pcc_struct_return; -} - -void _initialize_i386nbsd_tdep (); -void -_initialize_i386nbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD, - i386nbsdelf_init_abi); -} diff --git a/gdb/i386-netbsd-nat.c b/gdb/i386-netbsd-nat.c new file mode 100644 index 00000000000..4faa67f728a --- /dev/null +++ b/gdb/i386-netbsd-nat.c @@ -0,0 +1,84 @@ +/* Native-dependent code for NetBSD/i386. + + Copyright (C) 2004-2020 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 3 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, see . */ + +#include "defs.h" +#include "gdbcore.h" +#include "regcache.h" +#include "target.h" + +#include "i386-tdep.h" +#include "i386-bsd-nat.h" + +/* Support for debugging kernel virtual memory images. */ + +#include +#include +#include + +#include "netbsd-nat.h" +#include "bsd-kvm.h" + +static int +i386nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + struct switchframe sf; + + /* The following is true for NetBSD 1.6.2: + + The pcb contains %esp and %ebp at the point of the context switch + in cpu_switch(). At that point we have a stack frame as + described by `struct switchframe', which for NetBSD 1.6.2 has the + following layout: + + interrupt level + %edi + %esi + %ebx + %eip + + we reconstruct the register state as it would look when we just + returned from cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_esp == 0) + return 0; + + read_memory (pcb->pcb_esp, (gdb_byte *)&sf, sizeof sf); + pcb->pcb_esp += sizeof (struct switchframe); + regcache->raw_supply (I386_EDI_REGNUM, &sf.sf_edi); + regcache->raw_supply (I386_ESI_REGNUM, &sf.sf_esi); + regcache->raw_supply (I386_EBP_REGNUM, &pcb->pcb_ebp); + regcache->raw_supply (I386_ESP_REGNUM, &pcb->pcb_esp); + regcache->raw_supply (I386_EBX_REGNUM, &sf.sf_ebx); + regcache->raw_supply (I386_EIP_REGNUM, &sf.sf_eip); + + return 1; +} + +static i386_bsd_nat_target the_i386_nbsd_nat_target; + +void _initialize_i386nbsd_nat (); +void +_initialize_i386nbsd_nat () +{ + add_inf_child_target (&the_i386_nbsd_nat_target); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (i386nbsd_supply_pcb); +} diff --git a/gdb/i386-netbsd-tdep.c b/gdb/i386-netbsd-tdep.c new file mode 100644 index 00000000000..905c4ff6fe4 --- /dev/null +++ b/gdb/i386-netbsd-tdep.c @@ -0,0 +1,432 @@ +/* Target-dependent code for NetBSD/i386. + + Copyright (C) 1988-2020 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 3 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, see . */ + +#include "defs.h" +#include "arch-utils.h" +#include "frame.h" +#include "gdbcore.h" +#include "regcache.h" +#include "regset.h" +#include "osabi.h" +#include "symtab.h" +#include "trad-frame.h" +#include "tramp-frame.h" + +#include "i386-tdep.h" +#include "i387-tdep.h" +#include "netbsd-tdep.h" +#include "solib-svr4.h" + +/* From . */ +static int i386nbsd_r_reg_offset[] = +{ + 0 * 4, /* %eax */ + 1 * 4, /* %ecx */ + 2 * 4, /* %edx */ + 3 * 4, /* %ebx */ + 4 * 4, /* %esp */ + 5 * 4, /* %ebp */ + 6 * 4, /* %esi */ + 7 * 4, /* %edi */ + 8 * 4, /* %eip */ + 9 * 4, /* %eflags */ + 10 * 4, /* %cs */ + 11 * 4, /* %ss */ + 12 * 4, /* %ds */ + 13 * 4, /* %es */ + 14 * 4, /* %fs */ + 15 * 4 /* %gs */ +}; + +/* From . */ +static int i386nbsd_sc_reg_offset[] = +{ + 10 * 4, /* %eax */ + 9 * 4, /* %ecx */ + 8 * 4, /* %edx */ + 7 * 4, /* %ebx */ + 14 * 4, /* %esp */ + 6 * 4, /* %ebp */ + 5 * 4, /* %esi */ + 4 * 4, /* %edi */ + 11 * 4, /* %eip */ + 13 * 4, /* %eflags */ + 12 * 4, /* %cs */ + 15 * 4, /* %ss */ + 3 * 4, /* %ds */ + 2 * 4, /* %es */ + 1 * 4, /* %fs */ + 0 * 4 /* %gs */ +}; + +/* From . */ +int i386nbsd_mc_reg_offset[] = +{ + 11 * 4, /* %eax */ + 10 * 4, /* %ecx */ + 9 * 4, /* %edx */ + 8 * 4, /* %ebx */ + 7 * 4, /* %esp */ + 6 * 4, /* %ebp */ + 5 * 4, /* %esi */ + 4 * 4, /* %edi */ + 14 * 4, /* %eip */ + 16 * 4, /* %eflags */ + 15 * 4, /* %cs */ + 18 * 4, /* %ss */ + 3 * 4, /* %ds */ + 2 * 4, /* %es */ + 1 * 4, /* %fs */ + 0 * 4 /* %gs */ +}; + +static void i386nbsd_sigtramp_cache_init (const struct tramp_frame *, + struct frame_info *, + struct trad_frame_cache *, + CORE_ADDR); + +static const struct tramp_frame i386nbsd_sigtramp_sc16 = +{ + SIGTRAMP_FRAME, + 1, + { + /* leal 0x10(%esp), %eax */ + { 0x8d, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x10, ULONGEST_MAX }, + + /* pushl %eax */ + { 0x50, ULONGEST_MAX }, + + /* pushl %eax */ + { 0x50, ULONGEST_MAX }, + + /* movl $0x127, %eax # __sigreturn14 */ + { 0xb8, ULONGEST_MAX }, + { 0x27, ULONGEST_MAX }, + {0x01, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + + /* movl $0x1, %eax # exit */ + { 0xb8, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_sc2 = +{ + SIGTRAMP_FRAME, + 1, + { + /* leal 0x0c(%esp), %eax */ + { 0x8d, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x0c, ULONGEST_MAX }, + /* movl %eax, 0x4(%esp) */ + { 0x89, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + /* movl $0x127, %eax # __sigreturn14 */ + { 0xb8, ULONGEST_MAX }, + { 0x27, ULONGEST_MAX }, + {0x01, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + /* movl %eax, 0x4(%esp) */ + { 0x89, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + /* movl $0x1, %eax */ + { 0xb8, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_si2 = +{ + SIGTRAMP_FRAME, + 1, + { + /* movl 8(%esp),%eax */ + { 0x8b, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x08, ULONGEST_MAX }, + /* movl %eax, 0x4(%esp) */ + { 0x89, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + /* movl $0x134, %eax # setcontext */ + { 0xb8, ULONGEST_MAX }, + { 0x34, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX }, + /* movl %eax, 0x4(%esp) */ + { 0x89, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + /* movl $0x1, %eax */ + { 0xb8, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX }, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_si31 = +{ + SIGTRAMP_FRAME, + 1, + { + /* leal 0x8c(%esp), %eax */ + { 0x8d, ULONGEST_MAX }, + { 0x84, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x8c, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + /* movl %eax, 0x4(%esp) */ + { 0x89, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + /* movl $0x134, %eax # setcontext */ + { 0xb8, ULONGEST_MAX }, + { 0x34, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + /* movl %eax, 0x4(%esp) */ + { 0x89, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + /* movl $0x1, %eax */ + { 0xb8, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_si4 = +{ + SIGTRAMP_FRAME, + 1, + { + /* leal 0x8c(%esp), %eax */ + { 0x8d, ULONGEST_MAX }, + { 0x84, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x8c, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + /* movl %eax, 0x4(%esp) */ + { 0x89, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + /* movl $0x134, %eax # setcontext */ + { 0xb8, ULONGEST_MAX }, + { 0x34, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + { 0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + /* movl $0xffffffff,0x4(%esp) */ + { 0xc7, ULONGEST_MAX }, + { 0x44, ULONGEST_MAX }, + { 0x24, ULONGEST_MAX }, + { 0x04, ULONGEST_MAX }, + { 0xff, ULONGEST_MAX }, + { 0xff, ULONGEST_MAX }, + { 0xff, ULONGEST_MAX }, + { 0xff, ULONGEST_MAX }, + /* movl $0x1, %eax */ + { 0xb8, ULONGEST_MAX }, + { 0x01, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + {0x00, ULONGEST_MAX }, + /* int $0x80 */ + { 0xcd, ULONGEST_MAX }, + { 0x80, ULONGEST_MAX}, + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + i386nbsd_sigtramp_cache_init +}; + +static void +i386nbsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); + CORE_ADDR base; + int *reg_offset; + int num_regs; + int i; + + if (self == &i386nbsd_sigtramp_sc16 || self == &i386nbsd_sigtramp_sc2) + { + reg_offset = i386nbsd_sc_reg_offset; + num_regs = ARRAY_SIZE (i386nbsd_sc_reg_offset); + + /* Read in the sigcontext address. */ + base = read_memory_unsigned_integer (sp + 8, 4, byte_order); + } + else + { + reg_offset = i386nbsd_mc_reg_offset; + num_regs = ARRAY_SIZE (i386nbsd_mc_reg_offset); + + /* Read in the ucontext address. */ + base = read_memory_unsigned_integer (sp + 8, 4, byte_order); + /* offsetof(ucontext_t, uc_mcontext) == 36 */ + base += 36; + } + + for (i = 0; i < num_regs; i++) + if (reg_offset[i] != -1) + trad_frame_set_reg_addr (this_cache, i, base + reg_offset[i]); + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (this_cache, frame_id_build (sp, func)); +} + + +static void +i386nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Obviously NetBSD is BSD-based. */ + i386bsd_init_abi (info, gdbarch); + + nbsd_init_abi (info, gdbarch); + + /* NetBSD has a different `struct reg'. */ + tdep->gregset_reg_offset = i386nbsd_r_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (i386nbsd_r_reg_offset); + tdep->sizeof_gregset = 16 * 4; + + /* NetBSD uses -freg-struct-return by default. */ + tdep->struct_return = reg_struct_return; + + /* NetBSD uses tramp_frame sniffers for signal trampolines. */ + tdep->sigcontext_addr= 0; + tdep->sigtramp_start = 0; + tdep->sigtramp_end = 0; + tdep->sigtramp_p = 0; + tdep->sc_reg_offset = 0; + tdep->sc_num_regs = 0; + + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc16); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_sc2); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si2); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si31); + tramp_frame_prepend_unwinder (gdbarch, &i386nbsd_sigtramp_si4); +} + +/* NetBSD ELF. */ + +static void +i386nbsdelf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* It's still NetBSD. */ + i386nbsd_init_abi (info, gdbarch); + + /* But ELF-based. */ + i386_elf_init_abi (info, gdbarch); + + /* NetBSD ELF uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + /* NetBSD ELF uses -fpcc-struct-return by default. */ + tdep->struct_return = pcc_struct_return; +} + +void _initialize_i386nbsd_tdep (); +void +_initialize_i386nbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD, + i386nbsdelf_init_abi); +} diff --git a/gdb/m68k-bsd-nat.c b/gdb/m68k-bsd-nat.c index 9c42da5ca77..731aaf0e3ea 100644 --- a/gdb/m68k-bsd-nat.c +++ b/gdb/m68k-bsd-nat.c @@ -30,7 +30,7 @@ #include "m68k-tdep.h" #include "inf-ptrace.h" -#include "nbsd-nat.h" +#include "netbsd-nat.h" struct m68k_bsd_nat_target final : public nbsd_nat_target { diff --git a/gdb/mips-nbsd-nat.c b/gdb/mips-nbsd-nat.c deleted file mode 100644 index 461304a7e6c..00000000000 --- a/gdb/mips-nbsd-nat.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Native-dependent code for MIPS systems running NetBSD. - - Copyright (C) 2000-2020 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 3 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, see . */ - -/* We define this to get types like register_t. */ -#define _KERNTYPES -#include "defs.h" -#include "inferior.h" -#include "regcache.h" -#include "target.h" - -#include -#include -#include - -#include "mips-tdep.h" -#include "mips-nbsd-tdep.h" -#include "inf-ptrace.h" - -class mips_nbsd_nat_target final : public inf_ptrace_target -{ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; -}; - -static mips_nbsd_nat_target the_mips_nbsd_nat_target; - -/* Determine if PT_GETREGS fetches this register. */ -static int -getregs_supplies (struct gdbarch *gdbarch, int regno) -{ - return ((regno) >= MIPS_ZERO_REGNUM - && (regno) <= gdbarch_pc_regnum (gdbarch)); -} - -void -mips_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) -{ - pid_t pid = regcache->ptid ().pid (); - - struct gdbarch *gdbarch = regcache->arch (); - if (regno == -1 || getregs_supplies (gdbarch, regno)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - mipsnbsd_supply_reg (regcache, (char *) ®s, regno); - if (regno != -1) - return; - } - - if (regno == -1 - || regno >= gdbarch_fp0_regnum (regcache->arch ())) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - mipsnbsd_supply_fpreg (regcache, (char *) &fpregs, regno); - } -} - -void -mips_nbsd_nat_target::store_registers (struct regcache *regcache, int regno) -{ - pid_t pid = regcache->ptid ().pid (); - - struct gdbarch *gdbarch = regcache->arch (); - if (regno == -1 || getregs_supplies (gdbarch, regno)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - mipsnbsd_fill_reg (regcache, (char *) ®s, regno); - - if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - - if (regno != -1) - return; - } - - if (regno == -1 - || regno >= gdbarch_fp0_regnum (regcache->arch ())) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - mipsnbsd_fill_fpreg (regcache, (char *) &fpregs, regno); - - if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - -void _initialize_mipsnbsd_nat (); -void -_initialize_mipsnbsd_nat () -{ - add_inf_child_target (&the_mips_nbsd_nat_target); -} diff --git a/gdb/mips-nbsd-tdep.c b/gdb/mips-nbsd-tdep.c deleted file mode 100644 index 524990a8097..00000000000 --- a/gdb/mips-nbsd-tdep.c +++ /dev/null @@ -1,382 +0,0 @@ -/* Target-dependent code for NetBSD/mips. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "gdbcore.h" -#include "regcache.h" -#include "regset.h" -#include "target.h" -#include "value.h" -#include "osabi.h" - -#include "nbsd-tdep.h" -#include "mips-nbsd-tdep.h" -#include "mips-tdep.h" - -#include "solib-svr4.h" - -/* Shorthand for some register numbers used below. */ -#define MIPS_PC_REGNUM MIPS_EMBED_PC_REGNUM -#define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM -#define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32 - -/* Core file support. */ - -/* Number of registers in `struct reg' from . */ -#define MIPSNBSD_NUM_GREGS 38 - -/* Number of registers in `struct fpreg' from . */ -#define MIPSNBSD_NUM_FPREGS 33 - -/* Supply register REGNUM from the buffer specified by FPREGS and LEN - in the floating-point register set REGSET to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -static void -mipsnbsd_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *fpregs, size_t len) -{ - size_t regsize = mips_isa_regsize (regcache->arch ()); - const char *regs = (const char *) fpregs; - int i; - - gdb_assert (len >= MIPSNBSD_NUM_FPREGS * regsize); - - for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache->raw_supply (i, regs + (i - MIPS_FP0_REGNUM) * regsize); - } -} - -/* Supply register REGNUM from the buffer specified by GREGS and LEN - in the general-purpose register set REGSET to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -static void -mipsnbsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *gregs, size_t len) -{ - size_t regsize = mips_isa_regsize (regcache->arch ()); - const char *regs = (const char *) gregs; - int i; - - gdb_assert (len >= MIPSNBSD_NUM_GREGS * regsize); - - for (i = 0; i <= MIPS_PC_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache->raw_supply (i, regs + i * regsize); - } - - if (len >= (MIPSNBSD_NUM_GREGS + MIPSNBSD_NUM_FPREGS) * regsize) - { - regs += MIPSNBSD_NUM_GREGS * regsize; - len -= MIPSNBSD_NUM_GREGS * regsize; - mipsnbsd_supply_fpregset (regset, regcache, regnum, regs, len); - } -} - -/* NetBSD/mips register sets. */ - -static const struct regset mipsnbsd_gregset = -{ - NULL, - mipsnbsd_supply_gregset, - NULL, - REGSET_VARIABLE_SIZE -}; - -static const struct regset mipsnbsd_fpregset = -{ - NULL, - mipsnbsd_supply_fpregset -}; - -/* Iterate over core file register note sections. */ - -static void -mipsnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - size_t regsize = mips_isa_regsize (gdbarch); - - cb (".reg", MIPSNBSD_NUM_GREGS * regsize, MIPSNBSD_NUM_GREGS * regsize, - &mipsnbsd_gregset, NULL, cb_data); - cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, MIPSNBSD_NUM_FPREGS * regsize, - &mipsnbsd_fpregset, NULL, cb_data); -} - - -/* Conveniently, GDB uses the same register numbering as the - ptrace register structure used by NetBSD/mips. */ - -void -mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno) -{ - struct gdbarch *gdbarch = regcache->arch (); - int i; - - for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++) - { - if (regno == i || regno == -1) - { - if (gdbarch_cannot_fetch_register (gdbarch, i)) - regcache->raw_supply (i, NULL); - else - regcache->raw_supply - (i, regs + (i * mips_isa_regsize (gdbarch))); - } - } -} - -void -mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno) -{ - struct gdbarch *gdbarch = regcache->arch (); - int i; - - for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++) - if ((regno == i || regno == -1) - && ! gdbarch_cannot_store_register (gdbarch, i)) - regcache->raw_collect (i, regs + (i * mips_isa_regsize (gdbarch))); -} - -void -mipsnbsd_supply_fpreg (struct regcache *regcache, - const char *fpregs, int regno) -{ - struct gdbarch *gdbarch = regcache->arch (); - int i; - - for (i = gdbarch_fp0_regnum (gdbarch); - i <= mips_regnum (gdbarch)->fp_implementation_revision; - i++) - { - if (regno == i || regno == -1) - { - if (gdbarch_cannot_fetch_register (gdbarch, i)) - regcache->raw_supply (i, NULL); - else - regcache->raw_supply (i, - fpregs - + ((i - gdbarch_fp0_regnum (gdbarch)) - * mips_isa_regsize (gdbarch))); - } - } -} - -void -mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno) -{ - struct gdbarch *gdbarch = regcache->arch (); - int i; - - for (i = gdbarch_fp0_regnum (gdbarch); - i <= mips_regnum (gdbarch)->fp_control_status; - i++) - if ((regno == i || regno == -1) - && ! gdbarch_cannot_store_register (gdbarch, i)) - regcache->raw_collect - (i, (fpregs + ((i - gdbarch_fp0_regnum (gdbarch)) - * mips_isa_regsize (gdbarch)))); -} - -#if 0 - -/* 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 */ -}; - -#endif - -/* 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. MIPS_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(gdbarch) mips_isa_regsize (gdbarch) -#define NBSD_MIPS_JB_OFFSET(gdbarch) (NBSD_MIPS_JB_PC * \ - NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)) - -static int -mipsnbsd_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) -{ - struct gdbarch *gdbarch = get_frame_arch (frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR jb_addr; - gdb_byte *buf; - - buf = (gdb_byte *) alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)); - - jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM); - - if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf, - NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch))) - return 0; - - *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch), - byte_order); - return 1; -} - -static int -mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno) -{ - return (regno == MIPS_ZERO_REGNUM - || regno == mips_regnum (gdbarch)->fp_implementation_revision); -} - -static int -mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno) -{ - return (regno == MIPS_ZERO_REGNUM - || regno == mips_regnum (gdbarch)->fp_implementation_revision); -} - -/* Shared library support. */ - -/* NetBSD/mips uses a slightly different `struct link_map' than the - other NetBSD platforms. */ - -static struct link_map_offsets * -mipsnbsd_ilp32_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_version_offset = 0; - lmo.r_version_size = 4; - lmo.r_map_offset = 4; - lmo.r_brk_offset = 8; - lmo.r_ldsomap_offset = -1; - - /* Everything we need is in the first 24 bytes. */ - lmo.link_map_size = 24; - lmo.l_addr_offset = 4; - lmo.l_name_offset = 8; - lmo.l_ld_offset = 12; - lmo.l_next_offset = 16; - lmo.l_prev_offset = 20; - } - - return lmp; -} - -static struct link_map_offsets * -mipsnbsd_lp64_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_version_offset = 0; - lmo.r_version_size = 4; - lmo.r_map_offset = 8; - lmo.r_brk_offset = 16; - lmo.r_ldsomap_offset = -1; - - /* Everything we need is in the first 40 bytes. */ - lmo.link_map_size = 48; - lmo.l_addr_offset = 0; - lmo.l_name_offset = 16; - lmo.l_ld_offset = 24; - lmo.l_next_offset = 32; - lmo.l_prev_offset = 40; - } - - return lmp; -} - - -static void -mipsnbsd_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - nbsd_init_abi (info, gdbarch); - - set_gdbarch_iterate_over_regset_sections - (gdbarch, mipsnbsd_iterate_over_regset_sections); - - 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); - - /* NetBSD/mips has SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ? - mipsnbsd_ilp32_fetch_link_map_offsets : - mipsnbsd_lp64_fetch_link_map_offsets)); -} - -void _initialize_mipsnbsd_tdep (); -void -_initialize_mipsnbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD, - mipsnbsd_init_abi); -} diff --git a/gdb/mips-nbsd-tdep.h b/gdb/mips-nbsd-tdep.h deleted file mode 100644 index 588f1685b51..00000000000 --- a/gdb/mips-nbsd-tdep.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Common target dependent code for GDB on MIPS systems running NetBSD. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#ifndef MIPS_NBSD_TDEP_H -#define MIPS_NBSD_TDEP_H - -void mipsnbsd_supply_reg (struct regcache *, const char *, int); -void mipsnbsd_fill_reg (const struct regcache *, char *, int); - -void mipsnbsd_supply_fpreg (struct regcache *, const char *, int); -void mipsnbsd_fill_fpreg (const struct regcache *, char *, int); - -#endif /* MIPS_NBSD_TDEP_H */ diff --git a/gdb/mips-netbsd-nat.c b/gdb/mips-netbsd-nat.c new file mode 100644 index 00000000000..51ea1cb7f0d --- /dev/null +++ b/gdb/mips-netbsd-nat.c @@ -0,0 +1,123 @@ +/* Native-dependent code for MIPS systems running NetBSD. + + Copyright (C) 2000-2020 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 3 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, see . */ + +/* We define this to get types like register_t. */ +#define _KERNTYPES +#include "defs.h" +#include "inferior.h" +#include "regcache.h" +#include "target.h" + +#include +#include +#include + +#include "mips-tdep.h" +#include "mips-netbsd-tdep.h" +#include "inf-ptrace.h" + +class mips_nbsd_nat_target final : public inf_ptrace_target +{ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; +}; + +static mips_nbsd_nat_target the_mips_nbsd_nat_target; + +/* Determine if PT_GETREGS fetches this register. */ +static int +getregs_supplies (struct gdbarch *gdbarch, int regno) +{ + return ((regno) >= MIPS_ZERO_REGNUM + && (regno) <= gdbarch_pc_regnum (gdbarch)); +} + +void +mips_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) +{ + pid_t pid = regcache->ptid ().pid (); + + struct gdbarch *gdbarch = regcache->arch (); + if (regno == -1 || getregs_supplies (gdbarch, regno)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + mipsnbsd_supply_reg (regcache, (char *) ®s, regno); + if (regno != -1) + return; + } + + if (regno == -1 + || regno >= gdbarch_fp0_regnum (regcache->arch ())) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + mipsnbsd_supply_fpreg (regcache, (char *) &fpregs, regno); + } +} + +void +mips_nbsd_nat_target::store_registers (struct regcache *regcache, int regno) +{ + pid_t pid = regcache->ptid ().pid (); + + struct gdbarch *gdbarch = regcache->arch (); + if (regno == -1 || getregs_supplies (gdbarch, regno)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + mipsnbsd_fill_reg (regcache, (char *) ®s, regno); + + if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + + if (regno != -1) + return; + } + + if (regno == -1 + || regno >= gdbarch_fp0_regnum (regcache->arch ())) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + mipsnbsd_fill_fpreg (regcache, (char *) &fpregs, regno); + + if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + +void _initialize_mipsnbsd_nat (); +void +_initialize_mipsnbsd_nat () +{ + add_inf_child_target (&the_mips_nbsd_nat_target); +} diff --git a/gdb/mips-netbsd-tdep.c b/gdb/mips-netbsd-tdep.c new file mode 100644 index 00000000000..b6f87731002 --- /dev/null +++ b/gdb/mips-netbsd-tdep.c @@ -0,0 +1,382 @@ +/* Target-dependent code for NetBSD/mips. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "gdbcore.h" +#include "regcache.h" +#include "regset.h" +#include "target.h" +#include "value.h" +#include "osabi.h" + +#include "netbsd-tdep.h" +#include "mips-netbsd-tdep.h" +#include "mips-tdep.h" + +#include "solib-svr4.h" + +/* Shorthand for some register numbers used below. */ +#define MIPS_PC_REGNUM MIPS_EMBED_PC_REGNUM +#define MIPS_FP0_REGNUM MIPS_EMBED_FP0_REGNUM +#define MIPS_FSR_REGNUM MIPS_EMBED_FP0_REGNUM + 32 + +/* Core file support. */ + +/* Number of registers in `struct reg' from . */ +#define MIPSNBSD_NUM_GREGS 38 + +/* Number of registers in `struct fpreg' from . */ +#define MIPSNBSD_NUM_FPREGS 33 + +/* Supply register REGNUM from the buffer specified by FPREGS and LEN + in the floating-point register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +mipsnbsd_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + size_t regsize = mips_isa_regsize (regcache->arch ()); + const char *regs = (const char *) fpregs; + int i; + + gdb_assert (len >= MIPSNBSD_NUM_FPREGS * regsize); + + for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache->raw_supply (i, regs + (i - MIPS_FP0_REGNUM) * regsize); + } +} + +/* Supply register REGNUM from the buffer specified by GREGS and LEN + in the general-purpose register set REGSET to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +static void +mipsnbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t len) +{ + size_t regsize = mips_isa_regsize (regcache->arch ()); + const char *regs = (const char *) gregs; + int i; + + gdb_assert (len >= MIPSNBSD_NUM_GREGS * regsize); + + for (i = 0; i <= MIPS_PC_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache->raw_supply (i, regs + i * regsize); + } + + if (len >= (MIPSNBSD_NUM_GREGS + MIPSNBSD_NUM_FPREGS) * regsize) + { + regs += MIPSNBSD_NUM_GREGS * regsize; + len -= MIPSNBSD_NUM_GREGS * regsize; + mipsnbsd_supply_fpregset (regset, regcache, regnum, regs, len); + } +} + +/* NetBSD/mips register sets. */ + +static const struct regset mipsnbsd_gregset = +{ + NULL, + mipsnbsd_supply_gregset, + NULL, + REGSET_VARIABLE_SIZE +}; + +static const struct regset mipsnbsd_fpregset = +{ + NULL, + mipsnbsd_supply_fpregset +}; + +/* Iterate over core file register note sections. */ + +static void +mipsnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + size_t regsize = mips_isa_regsize (gdbarch); + + cb (".reg", MIPSNBSD_NUM_GREGS * regsize, MIPSNBSD_NUM_GREGS * regsize, + &mipsnbsd_gregset, NULL, cb_data); + cb (".reg2", MIPSNBSD_NUM_FPREGS * regsize, MIPSNBSD_NUM_FPREGS * regsize, + &mipsnbsd_fpregset, NULL, cb_data); +} + + +/* Conveniently, GDB uses the same register numbering as the + ptrace register structure used by NetBSD/mips. */ + +void +mipsnbsd_supply_reg (struct regcache *regcache, const char *regs, int regno) +{ + struct gdbarch *gdbarch = regcache->arch (); + int i; + + for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++) + { + if (regno == i || regno == -1) + { + if (gdbarch_cannot_fetch_register (gdbarch, i)) + regcache->raw_supply (i, NULL); + else + regcache->raw_supply + (i, regs + (i * mips_isa_regsize (gdbarch))); + } + } +} + +void +mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno) +{ + struct gdbarch *gdbarch = regcache->arch (); + int i; + + for (i = 0; i <= gdbarch_pc_regnum (gdbarch); i++) + if ((regno == i || regno == -1) + && ! gdbarch_cannot_store_register (gdbarch, i)) + regcache->raw_collect (i, regs + (i * mips_isa_regsize (gdbarch))); +} + +void +mipsnbsd_supply_fpreg (struct regcache *regcache, + const char *fpregs, int regno) +{ + struct gdbarch *gdbarch = regcache->arch (); + int i; + + for (i = gdbarch_fp0_regnum (gdbarch); + i <= mips_regnum (gdbarch)->fp_implementation_revision; + i++) + { + if (regno == i || regno == -1) + { + if (gdbarch_cannot_fetch_register (gdbarch, i)) + regcache->raw_supply (i, NULL); + else + regcache->raw_supply (i, + fpregs + + ((i - gdbarch_fp0_regnum (gdbarch)) + * mips_isa_regsize (gdbarch))); + } + } +} + +void +mipsnbsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno) +{ + struct gdbarch *gdbarch = regcache->arch (); + int i; + + for (i = gdbarch_fp0_regnum (gdbarch); + i <= mips_regnum (gdbarch)->fp_control_status; + i++) + if ((regno == i || regno == -1) + && ! gdbarch_cannot_store_register (gdbarch, i)) + regcache->raw_collect + (i, (fpregs + ((i - gdbarch_fp0_regnum (gdbarch)) + * mips_isa_regsize (gdbarch)))); +} + +#if 0 + +/* 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 */ +}; + +#endif + +/* 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. MIPS_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(gdbarch) mips_isa_regsize (gdbarch) +#define NBSD_MIPS_JB_OFFSET(gdbarch) (NBSD_MIPS_JB_PC * \ + NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)) + +static int +mipsnbsd_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) +{ + struct gdbarch *gdbarch = get_frame_arch (frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR jb_addr; + gdb_byte *buf; + + buf = (gdb_byte *) alloca (NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch)); + + jb_addr = get_frame_register_unsigned (frame, MIPS_A0_REGNUM); + + if (target_read_memory (jb_addr + NBSD_MIPS_JB_OFFSET (gdbarch), buf, + NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch))) + return 0; + + *pc = extract_unsigned_integer (buf, NBSD_MIPS_JB_ELEMENT_SIZE (gdbarch), + byte_order); + return 1; +} + +static int +mipsnbsd_cannot_fetch_register (struct gdbarch *gdbarch, int regno) +{ + return (regno == MIPS_ZERO_REGNUM + || regno == mips_regnum (gdbarch)->fp_implementation_revision); +} + +static int +mipsnbsd_cannot_store_register (struct gdbarch *gdbarch, int regno) +{ + return (regno == MIPS_ZERO_REGNUM + || regno == mips_regnum (gdbarch)->fp_implementation_revision); +} + +/* Shared library support. */ + +/* NetBSD/mips uses a slightly different `struct link_map' than the + other NetBSD platforms. */ + +static struct link_map_offsets * +mipsnbsd_ilp32_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_version_offset = 0; + lmo.r_version_size = 4; + lmo.r_map_offset = 4; + lmo.r_brk_offset = 8; + lmo.r_ldsomap_offset = -1; + + /* Everything we need is in the first 24 bytes. */ + lmo.link_map_size = 24; + lmo.l_addr_offset = 4; + lmo.l_name_offset = 8; + lmo.l_ld_offset = 12; + lmo.l_next_offset = 16; + lmo.l_prev_offset = 20; + } + + return lmp; +} + +static struct link_map_offsets * +mipsnbsd_lp64_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_version_offset = 0; + lmo.r_version_size = 4; + lmo.r_map_offset = 8; + lmo.r_brk_offset = 16; + lmo.r_ldsomap_offset = -1; + + /* Everything we need is in the first 40 bytes. */ + lmo.link_map_size = 48; + lmo.l_addr_offset = 0; + lmo.l_name_offset = 16; + lmo.l_ld_offset = 24; + lmo.l_next_offset = 32; + lmo.l_prev_offset = 40; + } + + return lmp; +} + + +static void +mipsnbsd_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + nbsd_init_abi (info, gdbarch); + + set_gdbarch_iterate_over_regset_sections + (gdbarch, mipsnbsd_iterate_over_regset_sections); + + 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); + + /* NetBSD/mips has SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ? + mipsnbsd_ilp32_fetch_link_map_offsets : + mipsnbsd_lp64_fetch_link_map_offsets)); +} + +void _initialize_mipsnbsd_tdep (); +void +_initialize_mipsnbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD, + mipsnbsd_init_abi); +} diff --git a/gdb/mips-netbsd-tdep.h b/gdb/mips-netbsd-tdep.h new file mode 100644 index 00000000000..588f1685b51 --- /dev/null +++ b/gdb/mips-netbsd-tdep.h @@ -0,0 +1,29 @@ +/* Common target dependent code for GDB on MIPS systems running NetBSD. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#ifndef MIPS_NBSD_TDEP_H +#define MIPS_NBSD_TDEP_H + +void mipsnbsd_supply_reg (struct regcache *, const char *, int); +void mipsnbsd_fill_reg (const struct regcache *, char *, int); + +void mipsnbsd_supply_fpreg (struct regcache *, const char *, int); +void mipsnbsd_fill_fpreg (const struct regcache *, char *, int); + +#endif /* MIPS_NBSD_TDEP_H */ diff --git a/gdb/nbsd-nat.c b/gdb/nbsd-nat.c deleted file mode 100644 index 46dcfac2cf6..00000000000 --- a/gdb/nbsd-nat.c +++ /dev/null @@ -1,815 +0,0 @@ -/* Native-dependent code for NetBSD. - - Copyright (C) 2006-2020 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 3 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, see . */ - -#include "defs.h" - -#include "nbsd-nat.h" -#include "nat/netbsd-nat.h" -#include "gdbthread.h" -#include "nbsd-tdep.h" -#include "inferior.h" -#include "gdbarch.h" - -#include -#include -#include -#include - -/* Return the name of a file that can be opened to get the symbols for - the child process identified by PID. */ - -char * -nbsd_nat_target::pid_to_exec_file (int pid) -{ - return const_cast (netbsd_nat::pid_to_exec_file (pid)); -} - -/* Return the current directory for the process identified by PID. */ - -static std::string -nbsd_pid_to_cwd (int pid) -{ - char buf[PATH_MAX]; - size_t buflen; - int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD}; - buflen = sizeof (buf); - if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0)) - return ""; - return buf; -} - -/* Return the kinfo_proc2 structure for the process identified by PID. */ - -static bool -nbsd_pid_to_kinfo_proc2 (pid_t pid, struct kinfo_proc2 *kp) -{ - gdb_assert (kp != nullptr); - - size_t size = sizeof (*kp); - int mib[6] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID, pid, - static_cast (size), 1}; - return !sysctl (mib, ARRAY_SIZE (mib), kp, &size, NULL, 0); -} - -/* Return the command line for the process identified by PID. */ - -static gdb::unique_xmalloc_ptr -nbsd_pid_to_cmdline (int pid) -{ - int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; - - size_t size = 0; - if (::sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) - return nullptr; - - gdb::unique_xmalloc_ptr args (XNEWVAR (char, size)); - - if (::sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1 - || size == 0) - return nullptr; - - /* Arguments are returned as a flattened string with NUL separators. - Join the arguments with spaces to form a single string. */ - for (size_t i = 0; i < size - 1; i++) - if (args[i] == '\0') - args[i] = ' '; - args[size - 1] = '\0'; - - return args; -} - -/* Return true if PTID is still active in the inferior. */ - -bool -nbsd_nat_target::thread_alive (ptid_t ptid) -{ - return netbsd_nat::thread_alive (ptid); -} - -/* Return the name assigned to a thread by an application. Returns - the string in a static buffer. */ - -const char * -nbsd_nat_target::thread_name (struct thread_info *thr) -{ - ptid_t ptid = thr->ptid; - return netbsd_nat::thread_name (ptid); -} - -/* Implement the "post_attach" target_ops method. */ - -static void -nbsd_add_threads (nbsd_nat_target *target, pid_t pid) -{ - auto fn - = [&target] (ptid_t ptid) - { - if (!in_thread_list (target, ptid)) - { - if (inferior_ptid.lwp () == 0) - thread_change_ptid (target, inferior_ptid, ptid); - else - add_thread (target, ptid); - } - }; - - netbsd_nat::for_each_thread (pid, fn); -} - -/* Implement the "post_startup_inferior" target_ops method. */ - -void -nbsd_nat_target::post_startup_inferior (ptid_t ptid) -{ - netbsd_nat::enable_proc_events (ptid.pid ()); -} - -/* Implement the "post_attach" target_ops method. */ - -void -nbsd_nat_target::post_attach (int pid) -{ - netbsd_nat::enable_proc_events (pid); - nbsd_add_threads (this, pid); -} - -/* Implement the "update_thread_list" target_ops method. */ - -void -nbsd_nat_target::update_thread_list () -{ - delete_exited_threads (); -} - -/* Convert PTID to a string. */ - -std::string -nbsd_nat_target::pid_to_str (ptid_t ptid) -{ - int lwp = ptid.lwp (); - - if (lwp != 0) - { - pid_t pid = ptid.pid (); - - return string_printf ("LWP %d of process %d", lwp, pid); - } - - return normal_pid_to_str (ptid); -} - -/* Retrieve all the memory regions in the specified process. */ - -static gdb::unique_xmalloc_ptr -nbsd_kinfo_get_vmmap (pid_t pid, size_t *size) -{ - int mib[5] = {CTL_VM, VM_PROC, VM_PROC_MAP, pid, - sizeof (struct kinfo_vmentry)}; - - size_t length = 0; - if (sysctl (mib, ARRAY_SIZE (mib), NULL, &length, NULL, 0)) - { - *size = 0; - return NULL; - } - - /* Prereserve more space. The length argument is volatile and can change - between the sysctl(3) calls as this function can be called against a - running process. */ - length = length * 5 / 3; - - gdb::unique_xmalloc_ptr kiv - (XNEWVAR (kinfo_vmentry, length)); - - if (sysctl (mib, ARRAY_SIZE (mib), kiv.get (), &length, NULL, 0)) - { - *size = 0; - return NULL; - } - - *size = length / sizeof (struct kinfo_vmentry); - return kiv; -} - -/* Iterate over all the memory regions in the current inferior, - calling FUNC for each memory region. OBFD is passed as the last - argument to FUNC. */ - -int -nbsd_nat_target::find_memory_regions (find_memory_region_ftype func, - void *data) -{ - pid_t pid = inferior_ptid.pid (); - - size_t nitems; - gdb::unique_xmalloc_ptr vmentl - = nbsd_kinfo_get_vmmap (pid, &nitems); - if (vmentl == NULL) - perror_with_name (_("Couldn't fetch VM map entries.")); - - for (size_t i = 0; i < nitems; i++) - { - struct kinfo_vmentry *kve = &vmentl[i]; - - /* Skip unreadable segments and those where MAP_NOCORE has been set. */ - if (!(kve->kve_protection & KVME_PROT_READ) - || kve->kve_flags & KVME_FLAG_NOCOREDUMP) - continue; - - /* Skip segments with an invalid type. */ - switch (kve->kve_type) - { - case KVME_TYPE_VNODE: - case KVME_TYPE_ANON: - case KVME_TYPE_SUBMAP: - case KVME_TYPE_OBJECT: - break; - default: - continue; - } - - size_t size = kve->kve_end - kve->kve_start; - if (info_verbose) - { - fprintf_filtered (gdb_stdout, - "Save segment, %ld bytes at %s (%c%c%c)\n", - (long) size, - paddress (target_gdbarch (), kve->kve_start), - kve->kve_protection & KVME_PROT_READ ? 'r' : '-', - kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-', - kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-'); - } - - /* Invoke the callback function to create the corefile segment. - Pass MODIFIED as true, we do not know the real modification state. */ - func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ, - kve->kve_protection & KVME_PROT_WRITE, - kve->kve_protection & KVME_PROT_EXEC, 1, data); - } - return 0; -} - -/* Implement the "info_proc" target_ops method. */ - -bool -nbsd_nat_target::info_proc (const char *args, enum info_proc_what what) -{ - pid_t pid; - bool do_cmdline = false; - bool do_cwd = false; - bool do_exe = false; - bool do_mappings = false; - bool do_status = false; - - switch (what) - { - case IP_MINIMAL: - do_cmdline = true; - do_cwd = true; - do_exe = true; - break; - case IP_STAT: - case IP_STATUS: - do_status = true; - break; - case IP_MAPPINGS: - do_mappings = true; - break; - case IP_CMDLINE: - do_cmdline = true; - break; - case IP_EXE: - do_exe = true; - break; - case IP_CWD: - do_cwd = true; - break; - case IP_ALL: - do_cmdline = true; - do_cwd = true; - do_exe = true; - do_mappings = true; - do_status = true; - break; - default: - error (_("Not supported on this target.")); - } - - gdb_argv built_argv (args); - if (built_argv.count () == 0) - { - pid = inferior_ptid.pid (); - if (pid == 0) - error (_("No current process: you must name one.")); - } - else if (built_argv.count () == 1 && isdigit (built_argv[0][0])) - pid = strtol (built_argv[0], NULL, 10); - else - error (_("Invalid arguments.")); - - printf_filtered (_("process %d\n"), pid); - - if (do_cmdline) - { - gdb::unique_xmalloc_ptr cmdline = nbsd_pid_to_cmdline (pid); - if (cmdline != nullptr) - printf_filtered ("cmdline = '%s'\n", cmdline.get ()); - else - warning (_("unable to fetch command line")); - } - if (do_cwd) - { - std::string cwd = nbsd_pid_to_cwd (pid); - if (cwd != "") - printf_filtered ("cwd = '%s'\n", cwd.c_str ()); - else - warning (_("unable to fetch current working directory")); - } - if (do_exe) - { - const char *exe = pid_to_exec_file (pid); - if (exe != nullptr) - printf_filtered ("exe = '%s'\n", exe); - else - warning (_("unable to fetch executable path name")); - } - if (do_mappings) - { - size_t nvment; - gdb::unique_xmalloc_ptr vmentl - = nbsd_kinfo_get_vmmap (pid, &nvment); - - if (vmentl != nullptr) - { - int addr_bit = TARGET_CHAR_BIT * sizeof (void *); - nbsd_info_proc_mappings_header (addr_bit); - - struct kinfo_vmentry *kve = vmentl.get (); - for (int i = 0; i < nvment; i++, kve++) - nbsd_info_proc_mappings_entry (addr_bit, kve->kve_start, - kve->kve_end, kve->kve_offset, - kve->kve_flags, kve->kve_protection, - kve->kve_path); - } - else - warning (_("unable to fetch virtual memory map")); - } - if (do_status) - { - struct kinfo_proc2 kp; - if (!nbsd_pid_to_kinfo_proc2 (pid, &kp)) - warning (_("Failed to fetch process information")); - else - { - auto process_status - = [] (int8_t stat) - { - switch (stat) - { - case SIDL: - return "IDL"; - case SACTIVE: - return "ACTIVE"; - case SDYING: - return "DYING"; - case SSTOP: - return "STOP"; - case SZOMB: - return "ZOMB"; - case SDEAD: - return "DEAD"; - default: - return "? (unknown)"; - } - }; - - printf_filtered ("Name: %s\n", kp.p_comm); - printf_filtered ("State: %s\n", process_status(kp.p_realstat)); - printf_filtered ("Parent process: %" PRId32 "\n", kp.p_ppid); - printf_filtered ("Process group: %" PRId32 "\n", kp.p__pgid); - printf_filtered ("Session id: %" PRId32 "\n", kp.p_sid); - printf_filtered ("TTY: %" PRId32 "\n", kp.p_tdev); - printf_filtered ("TTY owner process group: %" PRId32 "\n", kp.p_tpgid); - printf_filtered ("User IDs (real, effective, saved): " - "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n", - kp.p_ruid, kp.p_uid, kp.p_svuid); - printf_filtered ("Group IDs (real, effective, saved): " - "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n", - kp.p_rgid, kp.p_gid, kp.p_svgid); - - printf_filtered ("Groups:"); - for (int i = 0; i < kp.p_ngroups; i++) - printf_filtered (" %" PRIu32, kp.p_groups[i]); - printf_filtered ("\n"); - printf_filtered ("Minor faults (no memory page): %" PRIu64 "\n", - kp.p_uru_minflt); - printf_filtered ("Major faults (memory page faults): %" PRIu64 "\n", - kp.p_uru_majflt); - printf_filtered ("utime: %" PRIu32 ".%06" PRIu32 "\n", - kp.p_uutime_sec, kp.p_uutime_usec); - printf_filtered ("stime: %" PRIu32 ".%06" PRIu32 "\n", - kp.p_ustime_sec, kp.p_ustime_usec); - printf_filtered ("utime+stime, children: %" PRIu32 ".%06" PRIu32 "\n", - kp.p_uctime_sec, kp.p_uctime_usec); - printf_filtered ("'nice' value: %" PRIu8 "\n", kp.p_nice); - printf_filtered ("Start time: %" PRIu32 ".%06" PRIu32 "\n", - kp.p_ustart_sec, kp.p_ustart_usec); - int pgtok = getpagesize () / 1024; - printf_filtered ("Data size: %" PRIuMAX " kB\n", - (uintmax_t) kp.p_vm_dsize * pgtok); - printf_filtered ("Stack size: %" PRIuMAX " kB\n", - (uintmax_t) kp.p_vm_ssize * pgtok); - printf_filtered ("Text size: %" PRIuMAX " kB\n", - (uintmax_t) kp.p_vm_tsize * pgtok); - printf_filtered ("Resident set size: %" PRIuMAX " kB\n", - (uintmax_t) kp.p_vm_rssize * pgtok); - printf_filtered ("Maximum RSS: %" PRIu64 " kB\n", kp.p_uru_maxrss); - printf_filtered ("Pending Signals:"); - for (size_t i = 0; i < ARRAY_SIZE (kp.p_siglist.__bits); i++) - printf_filtered (" %08" PRIx32, kp.p_siglist.__bits[i]); - printf_filtered ("\n"); - printf_filtered ("Ignored Signals:"); - for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigignore.__bits); i++) - printf_filtered (" %08" PRIx32, kp.p_sigignore.__bits[i]); - printf_filtered ("\n"); - printf_filtered ("Caught Signals:"); - for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigcatch.__bits); i++) - printf_filtered (" %08" PRIx32, kp.p_sigcatch.__bits[i]); - printf_filtered ("\n"); - } - } - - return true; -} - -/* Resume execution of a specified PTID, that points to a process or a thread - within a process. If one thread is specified, all other threads are - suspended. If STEP is nonzero, single-step it. If SIGNAL is nonzero, - give it that signal. */ - -static void -nbsd_resume(nbsd_nat_target *target, ptid_t ptid, int step, - enum gdb_signal signal) -{ - int request; - - gdb_assert (minus_one_ptid != ptid); - - if (ptid.lwp_p ()) - { - /* If ptid is a specific LWP, suspend all other LWPs in the process. */ - inferior *inf = find_inferior_ptid (target, ptid); - - for (thread_info *tp : inf->non_exited_threads ()) - { - if (tp->ptid.lwp () == ptid.lwp ()) - request = PT_RESUME; - else - request = PT_SUSPEND; - - if (ptrace (request, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) - perror_with_name (("ptrace")); - } - } - else - { - /* If ptid is a wildcard, resume all matching threads (they won't run - until the process is continued however). */ - for (thread_info *tp : all_non_exited_threads (target, ptid)) - if (ptrace (PT_RESUME, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) - perror_with_name (("ptrace")); - } - - if (step) - { - for (thread_info *tp : all_non_exited_threads (target, ptid)) - if (ptrace (PT_SETSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) - perror_with_name (("ptrace")); - } - else - { - for (thread_info *tp : all_non_exited_threads (target, ptid)) - if (ptrace (PT_CLEARSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) - perror_with_name (("ptrace")); - } - - if (catch_syscall_enabled () > 0) - request = PT_SYSCALL; - else - request = PT_CONTINUE; - - /* An address of (void *)1 tells ptrace to continue from - where it was. If GDB wanted it to start some other way, we have - already written a new program counter value to the child. */ - if (ptrace (request, ptid.pid (), (void *)1, gdb_signal_to_host (signal)) == -1) - perror_with_name (("ptrace")); -} - -/* Resume execution of thread PTID, or all threads of all inferiors - if PTID is -1. If STEP is nonzero, single-step it. If SIGNAL is nonzero, - give it that signal. */ - -void -nbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal) -{ - if (minus_one_ptid != ptid) - nbsd_resume (this, ptid, step, signal); - else - { - for (inferior *inf : all_non_exited_inferiors (this)) - nbsd_resume (this, ptid_t (inf->pid, 0, 0), step, signal); - } -} - -/* Implement a safe wrapper around waitpid(). */ - -static pid_t -nbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus, - target_wait_flags options) -{ - pid_t pid; - int status; - - set_sigint_trap (); - - do - { - /* The common code passes WNOHANG that leads to crashes, overwrite it. */ - pid = waitpid (ptid.pid (), &status, 0); - } - while (pid == -1 && errno == EINTR); - - clear_sigint_trap (); - - if (pid == -1) - perror_with_name (_("Child process unexpectedly missing")); - - store_waitstatus (ourstatus, status); - return pid; -} - -/* Wait for the child specified by PTID to do something. Return the - process ID of the child, or MINUS_ONE_PTID in case of error; store - the status in *OURSTATUS. */ - -ptid_t -nbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, - target_wait_flags target_options) -{ - pid_t pid = nbsd_wait (ptid, ourstatus, target_options); - ptid_t wptid = ptid_t (pid); - - /* If the child stopped, keep investigating its status. */ - if (ourstatus->kind != TARGET_WAITKIND_STOPPED) - return wptid; - - /* Extract the event and thread that received a signal. */ - ptrace_siginfo_t psi; - if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1) - perror_with_name (("ptrace")); - - /* Pick child's siginfo_t. */ - siginfo_t *si = &psi.psi_siginfo; - - int lwp = psi.psi_lwpid; - - int signo = si->si_signo; - const int code = si->si_code; - - /* Construct PTID with a specified thread that received the event. - If a signal was targeted to the whole process, lwp is 0. */ - wptid = ptid_t (pid, lwp, 0); - - /* Bail out on non-debugger oriented signals.. */ - if (signo != SIGTRAP) - return wptid; - - /* Stop examining non-debugger oriented SIGTRAP codes. */ - if (code <= SI_USER || code == SI_NOINFO) - return wptid; - - /* Process state for threading events */ - ptrace_state_t pst = {}; - if (code == TRAP_LWP) - { - if (ptrace (PT_GET_PROCESS_STATE, pid, &pst, sizeof (pst)) == -1) - perror_with_name (("ptrace")); - } - - if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_EXIT) - { - /* If GDB attaches to a multi-threaded process, exiting - threads might be skipped during post_attach that - have not yet reported their PTRACE_LWP_EXIT event. - Ignore exited events for an unknown LWP. */ - thread_info *thr = find_thread_ptid (this, wptid); - if (thr == nullptr) - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - else - { - ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED; - /* NetBSD does not store an LWP exit status. */ - ourstatus->value.integer = 0; - - if (print_thread_events) - printf_unfiltered (_("[%s exited]\n"), - target_pid_to_str (wptid).c_str ()); - delete_thread (thr); - } - - /* The GDB core expects that the rest of the threads are running. */ - if (ptrace (PT_CONTINUE, pid, (void *) 1, 0) == -1) - perror_with_name (("ptrace")); - - return wptid; - } - - if (in_thread_list (this, ptid_t (pid))) - thread_change_ptid (this, ptid_t (pid), wptid); - - if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_CREATE) - { - /* If GDB attaches to a multi-threaded process, newborn - threads might be added by nbsd_add_threads that have - not yet reported their PTRACE_LWP_CREATE event. Ignore - born events for an already-known LWP. */ - if (in_thread_list (this, wptid)) - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - else - { - add_thread (this, wptid); - ourstatus->kind = TARGET_WAITKIND_THREAD_CREATED; - } - return wptid; - } - - if (code == TRAP_EXEC) - { - ourstatus->kind = TARGET_WAITKIND_EXECD; - ourstatus->value.execd_pathname = xstrdup (pid_to_exec_file (pid)); - return wptid; - } - - if (code == TRAP_TRACE) - { - /* Unhandled at this level. */ - return wptid; - } - - if (code == TRAP_SCE || code == TRAP_SCX) - { - int sysnum = si->si_sysnum; - - if (!catch_syscall_enabled () || !catching_syscall_number (sysnum)) - { - /* If the core isn't interested in this event, ignore it. */ - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - return wptid; - } - - ourstatus->kind = - (code == TRAP_SCE) ? TARGET_WAITKIND_SYSCALL_ENTRY : - TARGET_WAITKIND_SYSCALL_RETURN; - ourstatus->value.syscall_number = sysnum; - return wptid; - } - - if (code == TRAP_BRKPT) - { - /* Unhandled at this level. */ - return wptid; - } - - /* Unclassified SIGTRAP event. */ - ourstatus->kind = TARGET_WAITKIND_SPURIOUS; - return wptid; -} - -/* Implement the "insert_exec_catchpoint" target_ops method. */ - -int -nbsd_nat_target::insert_exec_catchpoint (int pid) -{ - /* Nothing to do. */ - return 0; -} - -/* Implement the "remove_exec_catchpoint" target_ops method. */ - -int -nbsd_nat_target::remove_exec_catchpoint (int pid) -{ - /* Nothing to do. */ - return 0; -} - -/* Implement the "set_syscall_catchpoint" target_ops method. */ - -int -nbsd_nat_target::set_syscall_catchpoint (int pid, bool needed, - int any_count, - gdb::array_view syscall_counts) -{ - /* Ignore the arguments. inf-ptrace.c will use PT_SYSCALL which - will catch all system call entries and exits. The system calls - are filtered by GDB rather than the kernel. */ - return 0; -} - -/* Implement the "supports_multi_process" target_ops method. */ - -bool -nbsd_nat_target::supports_multi_process () -{ - return true; -} - -/* Implement the "xfer_partial" target_ops method. */ - -enum target_xfer_status -nbsd_nat_target::xfer_partial (enum target_object object, - const char *annex, gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) -{ - pid_t pid = inferior_ptid.pid (); - - switch (object) - { - case TARGET_OBJECT_SIGNAL_INFO: - { - len = netbsd_nat::qxfer_siginfo(pid, annex, readbuf, writebuf, offset, - len); - - if (len == -1) - return TARGET_XFER_E_IO; - - *xfered_len = len; - return TARGET_XFER_OK; - } - case TARGET_OBJECT_MEMORY: - { - size_t xfered; - int res; - if (writebuf != nullptr) - res = netbsd_nat::write_memory (pid, writebuf, offset, len, &xfered); - else - res = netbsd_nat::read_memory (pid, readbuf, offset, len, &xfered); - if (res != 0) - { - if (res == EACCES) - fprintf_unfiltered (gdb_stderr, "Cannot %s process at %s (%s). " - "Is PaX MPROTECT active? See security(7), " - "sysctl(7), paxctl(8)\n", - (writebuf ? "write to" : "read from"), - pulongest (offset), safe_strerror (errno)); - return TARGET_XFER_E_IO; - } - if (xfered == 0) - return TARGET_XFER_EOF; - *xfered_len = (ULONGEST) xfered; - return TARGET_XFER_OK; - } - default: - return inf_ptrace_target::xfer_partial (object, annex, - readbuf, writebuf, offset, - len, xfered_len); - } -} - -/* Implement the "supports_dumpcore" target_ops method. */ - -bool -nbsd_nat_target::supports_dumpcore () -{ - return true; -} - -/* Implement the "dumpcore" target_ops method. */ - -void -nbsd_nat_target::dumpcore (const char *filename) -{ - pid_t pid = inferior_ptid.pid (); - - if (ptrace (PT_DUMPCORE, pid, const_cast(filename), - strlen (filename)) == -1) - perror_with_name (("ptrace")); -} diff --git a/gdb/nbsd-nat.h b/gdb/nbsd-nat.h deleted file mode 100644 index 7461667cefb..00000000000 --- a/gdb/nbsd-nat.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Native-dependent code for NetBSD. - - Copyright (C) 2006-2020 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 3 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, see . */ - -#ifndef NBSD_NAT_H -#define NBSD_NAT_H - -#include "inf-ptrace.h" - -struct thread_info; - -/* A prototype NetBSD target. */ - -struct nbsd_nat_target : public inf_ptrace_target -{ - char *pid_to_exec_file (int pid) override; - - bool thread_alive (ptid_t ptid) override; - const char *thread_name (struct thread_info *thr) override; - void post_startup_inferior (ptid_t ptid) override; - void post_attach (int pid) override; - void update_thread_list () override; - std::string pid_to_str (ptid_t ptid) override; - - int find_memory_regions (find_memory_region_ftype func, void *data) override; - bool info_proc (const char *, enum info_proc_what) override; - - void resume (ptid_t, int, enum gdb_signal) override; - ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override; - int insert_exec_catchpoint (int pid) override; - int remove_exec_catchpoint (int pid) override; - int set_syscall_catchpoint (int pid, bool needed, int any_count, - gdb::array_view syscall_counts) - override; - - bool supports_multi_process () override; - enum target_xfer_status xfer_partial (enum target_object object, - const char *annex, - gdb_byte *readbuf, - const gdb_byte *writebuf, - ULONGEST offset, ULONGEST len, - ULONGEST *xfered_len) override; - bool supports_dumpcore () override; - void dumpcore (const char *filename) override; -}; - -#endif /* nbsd-nat.h */ diff --git a/gdb/nbsd-tdep.c b/gdb/nbsd-tdep.c deleted file mode 100644 index 2db994af218..00000000000 --- a/gdb/nbsd-tdep.c +++ /dev/null @@ -1,632 +0,0 @@ -/* Common target-dependent code for NetBSD systems. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "auxv.h" -#include "solib-svr4.h" -#include "nbsd-tdep.h" -#include "gdbarch.h" -#include "objfiles.h" -#include "xml-syscall.h" - -/* Flags in the 'kve_protection' field in struct kinfo_vmentry. These - match the KVME_PROT_* constants in . */ - -#define KINFO_VME_PROT_READ 0x00000001 -#define KINFO_VME_PROT_WRITE 0x00000002 -#define KINFO_VME_PROT_EXEC 0x00000004 - -/* Flags in the 'kve_flags' field in struct kinfo_vmentry. These - match the KVME_FLAG_* constants in . */ - -#define KINFO_VME_FLAG_COW 0x00000001 -#define KINFO_VME_FLAG_NEEDS_COPY 0x00000002 -#define KINFO_VME_FLAG_NOCOREDUMP 0x00000004 -#define KINFO_VME_FLAG_PAGEABLE 0x00000008 -#define KINFO_VME_FLAG_GROWS_UP 0x00000010 -#define KINFO_VME_FLAG_GROWS_DOWN 0x00000020 - -/* FIXME: kettenis/20060115: We should really eliminate the next two - functions completely. */ - -struct link_map_offsets * -nbsd_ilp32_solib_svr4_fetch_link_map_offsets (void) -{ - return svr4_ilp32_fetch_link_map_offsets (); -} - -struct link_map_offsets * -nbsd_lp64_solib_svr4_fetch_link_map_offsets (void) -{ - return svr4_lp64_fetch_link_map_offsets (); -} - -int -nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *func_name) -{ - /* Check for libc-provided signal trampoline. All such trampolines - have function names which begin with "__sigtramp". */ - - return (func_name != NULL - && startswith (func_name, "__sigtramp")); -} - -/* This enum is derived from NETBSD's . */ - -enum - { - NBSD_SIGHUP = 1, - NBSD_SIGINT = 2, - NBSD_SIGQUIT = 3, - NBSD_SIGILL = 4, - NBSD_SIGTRAP = 5, - NBSD_SIGABRT = 6, - NBSD_SIGEMT = 7, - NBSD_SIGFPE = 8, - NBSD_SIGKILL = 9, - NBSD_SIGBUS = 10, - NBSD_SIGSEGV = 11, - NBSD_SIGSYS = 12, - NBSD_SIGPIPE = 13, - NBSD_SIGALRM = 14, - NBSD_SIGTERM = 15, - NBSD_SIGURG = 16, - NBSD_SIGSTOP = 17, - NBSD_SIGTSTP = 18, - NBSD_SIGCONT = 19, - NBSD_SIGCHLD = 20, - NBSD_SIGTTIN = 21, - NBSD_SIGTTOU = 22, - NBSD_SIGIO = 23, - NBSD_SIGXCPU = 24, - NBSD_SIGXFSZ = 25, - NBSD_SIGVTALRM = 26, - NBSD_SIGPROF = 27, - NBSD_SIGWINCH = 28, - NBSD_SIGINFO = 29, - NBSD_SIGUSR1 = 30, - NBSD_SIGUSR2 = 31, - NBSD_SIGPWR = 32, - NBSD_SIGRTMIN = 33, - NBSD_SIGRTMAX = 63, - }; - -/* Implement the "gdb_signal_from_target" gdbarch method. */ - -static enum gdb_signal -nbsd_gdb_signal_from_target (struct gdbarch *gdbarch, int signal) -{ - switch (signal) - { - case 0: - return GDB_SIGNAL_0; - - case NBSD_SIGHUP: - return GDB_SIGNAL_HUP; - - case NBSD_SIGINT: - return GDB_SIGNAL_INT; - - case NBSD_SIGQUIT: - return GDB_SIGNAL_QUIT; - - case NBSD_SIGILL: - return GDB_SIGNAL_ILL; - - case NBSD_SIGTRAP: - return GDB_SIGNAL_TRAP; - - case NBSD_SIGABRT: - return GDB_SIGNAL_ABRT; - - case NBSD_SIGEMT: - return GDB_SIGNAL_EMT; - - case NBSD_SIGFPE: - return GDB_SIGNAL_FPE; - - case NBSD_SIGKILL: - return GDB_SIGNAL_KILL; - - case NBSD_SIGBUS: - return GDB_SIGNAL_BUS; - - case NBSD_SIGSEGV: - return GDB_SIGNAL_SEGV; - - case NBSD_SIGSYS: - return GDB_SIGNAL_SYS; - - case NBSD_SIGPIPE: - return GDB_SIGNAL_PIPE; - - case NBSD_SIGALRM: - return GDB_SIGNAL_ALRM; - - case NBSD_SIGTERM: - return GDB_SIGNAL_TERM; - - case NBSD_SIGURG: - return GDB_SIGNAL_URG; - - case NBSD_SIGSTOP: - return GDB_SIGNAL_STOP; - - case NBSD_SIGTSTP: - return GDB_SIGNAL_TSTP; - - case NBSD_SIGCONT: - return GDB_SIGNAL_CONT; - - case NBSD_SIGCHLD: - return GDB_SIGNAL_CHLD; - - case NBSD_SIGTTIN: - return GDB_SIGNAL_TTIN; - - case NBSD_SIGTTOU: - return GDB_SIGNAL_TTOU; - - case NBSD_SIGIO: - return GDB_SIGNAL_IO; - - case NBSD_SIGXCPU: - return GDB_SIGNAL_XCPU; - - case NBSD_SIGXFSZ: - return GDB_SIGNAL_XFSZ; - - case NBSD_SIGVTALRM: - return GDB_SIGNAL_VTALRM; - - case NBSD_SIGPROF: - return GDB_SIGNAL_PROF; - - case NBSD_SIGWINCH: - return GDB_SIGNAL_WINCH; - - case NBSD_SIGINFO: - return GDB_SIGNAL_INFO; - - case NBSD_SIGUSR1: - return GDB_SIGNAL_USR1; - - case NBSD_SIGUSR2: - return GDB_SIGNAL_USR2; - - case NBSD_SIGPWR: - return GDB_SIGNAL_PWR; - - /* SIGRTMIN and SIGRTMAX are not continuous in , - therefore we have to handle them here. */ - case NBSD_SIGRTMIN: - return GDB_SIGNAL_REALTIME_33; - - case NBSD_SIGRTMAX: - return GDB_SIGNAL_REALTIME_63; - } - - if (signal >= NBSD_SIGRTMIN + 1 && signal <= NBSD_SIGRTMAX - 1) - { - int offset = signal - NBSD_SIGRTMIN + 1; - - return (enum gdb_signal) ((int) GDB_SIGNAL_REALTIME_34 + offset); - } - - return GDB_SIGNAL_UNKNOWN; -} - -/* Implement the "gdb_signal_to_target" gdbarch method. */ - -static int -nbsd_gdb_signal_to_target (struct gdbarch *gdbarch, - enum gdb_signal signal) -{ - switch (signal) - { - case GDB_SIGNAL_0: - return 0; - - case GDB_SIGNAL_HUP: - return NBSD_SIGHUP; - - case GDB_SIGNAL_INT: - return NBSD_SIGINT; - - case GDB_SIGNAL_QUIT: - return NBSD_SIGQUIT; - - case GDB_SIGNAL_ILL: - return NBSD_SIGILL; - - case GDB_SIGNAL_TRAP: - return NBSD_SIGTRAP; - - case GDB_SIGNAL_ABRT: - return NBSD_SIGABRT; - - case GDB_SIGNAL_EMT: - return NBSD_SIGEMT; - - case GDB_SIGNAL_FPE: - return NBSD_SIGFPE; - - case GDB_SIGNAL_KILL: - return NBSD_SIGKILL; - - case GDB_SIGNAL_BUS: - return NBSD_SIGBUS; - - case GDB_SIGNAL_SEGV: - return NBSD_SIGSEGV; - - case GDB_SIGNAL_SYS: - return NBSD_SIGSYS; - - case GDB_SIGNAL_PIPE: - return NBSD_SIGPIPE; - - case GDB_SIGNAL_ALRM: - return NBSD_SIGALRM; - - case GDB_SIGNAL_TERM: - return NBSD_SIGTERM; - - case GDB_SIGNAL_URG: - return NBSD_SIGSTOP; - - case GDB_SIGNAL_TSTP: - return NBSD_SIGTSTP; - - case GDB_SIGNAL_CONT: - return NBSD_SIGCONT; - - case GDB_SIGNAL_CHLD: - return NBSD_SIGCHLD; - - case GDB_SIGNAL_TTIN: - return NBSD_SIGTTIN; - - case GDB_SIGNAL_TTOU: - return NBSD_SIGTTOU; - - case GDB_SIGNAL_IO: - return NBSD_SIGIO; - - case GDB_SIGNAL_XCPU: - return NBSD_SIGXCPU; - - case GDB_SIGNAL_XFSZ: - return NBSD_SIGXFSZ; - - case GDB_SIGNAL_VTALRM: - return NBSD_SIGVTALRM; - - case GDB_SIGNAL_PROF: - return NBSD_SIGPROF; - - case GDB_SIGNAL_WINCH: - return NBSD_SIGWINCH; - - case GDB_SIGNAL_INFO: - return NBSD_SIGINFO; - - case GDB_SIGNAL_USR1: - return NBSD_SIGUSR1; - - case GDB_SIGNAL_USR2: - return NBSD_SIGUSR2; - - case GDB_SIGNAL_PWR: - return NBSD_SIGPWR; - - /* GDB_SIGNAL_REALTIME_33 is not continuous in , - therefore we have to handle it here. */ - case GDB_SIGNAL_REALTIME_33: - return NBSD_SIGRTMIN; - - /* Same comment applies to _64. */ - case GDB_SIGNAL_REALTIME_63: - return NBSD_SIGRTMAX; - } - - if (signal >= GDB_SIGNAL_REALTIME_34 - && signal <= GDB_SIGNAL_REALTIME_62) - { - int offset = signal - GDB_SIGNAL_REALTIME_32; - - return NBSD_SIGRTMIN + 1 + offset; - } - - return -1; -} - -/* Shared library resolver handling. */ - -static CORE_ADDR -nbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc) -{ - struct bound_minimal_symbol msym; - - msym = lookup_minimal_symbol ("_rtld_bind_start", NULL, NULL); - if (msym.minsym && BMSYMBOL_VALUE_ADDRESS (msym) == pc) - return frame_unwind_caller_pc (get_current_frame ()); - else - return find_solib_trampoline_target (get_current_frame (), pc); -} - -static struct gdbarch_data *nbsd_gdbarch_data_handle; - -struct nbsd_gdbarch_data -{ - struct type *siginfo_type; -}; - -static void * -init_nbsd_gdbarch_data (struct gdbarch *gdbarch) -{ - return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct nbsd_gdbarch_data); -} - -static struct nbsd_gdbarch_data * -get_nbsd_gdbarch_data (struct gdbarch *gdbarch) -{ - return ((struct nbsd_gdbarch_data *) - gdbarch_data (gdbarch, nbsd_gdbarch_data_handle)); -} - -/* Implement the "get_siginfo_type" gdbarch method. */ - -static struct type * -nbsd_get_siginfo_type (struct gdbarch *gdbarch) -{ - nbsd_gdbarch_data *nbsd_gdbarch_data = get_nbsd_gdbarch_data (gdbarch); - if (nbsd_gdbarch_data->siginfo_type != NULL) - return nbsd_gdbarch_data->siginfo_type; - - type *char_type = builtin_type (gdbarch)->builtin_char; - type *int_type = builtin_type (gdbarch)->builtin_int; - type *long_type = builtin_type (gdbarch)->builtin_long; - - type *void_ptr_type - = lookup_pointer_type (builtin_type (gdbarch)->builtin_void); - - type *int32_type = builtin_type (gdbarch)->builtin_int32; - type *uint32_type = builtin_type (gdbarch)->builtin_uint32; - type *uint64_type = builtin_type (gdbarch)->builtin_uint64; - - bool lp64 = TYPE_LENGTH (void_ptr_type) == 8; - size_t char_bits = gdbarch_addressable_memory_unit_size (gdbarch) * 8; - - /* pid_t */ - type *pid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, - TYPE_LENGTH (int32_type) * char_bits, "pid_t"); - TYPE_TARGET_TYPE (pid_type) = int32_type; - - /* uid_t */ - type *uid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, - TYPE_LENGTH (uint32_type) * char_bits, "uid_t"); - TYPE_TARGET_TYPE (uid_type) = uint32_type; - - /* clock_t */ - type *clock_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, - TYPE_LENGTH (int_type) * char_bits, "clock_t"); - TYPE_TARGET_TYPE (clock_type) = int_type; - - /* lwpid_t */ - type *lwpid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, - TYPE_LENGTH (int32_type) * char_bits, - "lwpid_t"); - TYPE_TARGET_TYPE (lwpid_type) = int32_type; - - /* union sigval */ - type *sigval_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); - sigval_type->set_name (gdbarch_obstack_strdup (gdbarch, "sigval")); - append_composite_type_field (sigval_type, "sival_int", int_type); - append_composite_type_field (sigval_type, "sival_ptr", void_ptr_type); - - /* union _option */ - type *option_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); - option_type->set_name (gdbarch_obstack_strdup (gdbarch, "_option")); - append_composite_type_field (option_type, "_pe_other_pid", pid_type); - append_composite_type_field (option_type, "_pe_lwp", lwpid_type); - - /* union _reason */ - type *reason_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); - - /* _rt */ - type *t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); - append_composite_type_field (t, "_pid", pid_type); - append_composite_type_field (t, "_uid", uid_type); - append_composite_type_field (t, "_value", sigval_type); - append_composite_type_field (reason_type, "_rt", t); - - /* _child */ - t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); - append_composite_type_field (t, "_pid", pid_type); - append_composite_type_field (t, "_uid", uid_type); - append_composite_type_field (t, "_status", int_type); - append_composite_type_field (t, "_utime", clock_type); - append_composite_type_field (t, "_stime", clock_type); - append_composite_type_field (reason_type, "_child", t); - - /* _fault */ - t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); - append_composite_type_field (t, "_addr", void_ptr_type); - append_composite_type_field (t, "_trap", int_type); - append_composite_type_field (t, "_trap2", int_type); - append_composite_type_field (t, "_trap3", int_type); - append_composite_type_field (reason_type, "_fault", t); - - /* _poll */ - t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); - append_composite_type_field (t, "_band", long_type); - append_composite_type_field (t, "_fd", int_type); - append_composite_type_field (reason_type, "_poll", t); - - /* _syscall */ - t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); - append_composite_type_field (t, "_sysnum", int_type); - append_composite_type_field (t, "_retval", - init_vector_type (int_type, 2)); - append_composite_type_field (t, "_error", int_type); - append_composite_type_field (t, "_args", - init_vector_type (uint64_type, 8)); - append_composite_type_field (reason_type, "_syscall", t); - - /* _ptrace_state */ - t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); - append_composite_type_field (t, "_pe_report_event", int_type); - append_composite_type_field (t, "_option", option_type); - append_composite_type_field (reason_type, "_ptrace_state", t); - - /* struct _ksiginfo */ - type *ksiginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); - ksiginfo_type->set_name (gdbarch_obstack_strdup (gdbarch, "_ksiginfo")); - append_composite_type_field (ksiginfo_type, "_signo", int_type); - append_composite_type_field (ksiginfo_type, "_code", int_type); - append_composite_type_field (ksiginfo_type, "_errno", int_type); - if (lp64) - append_composite_type_field (ksiginfo_type, "_pad", int_type); - append_composite_type_field (ksiginfo_type, "_reason", reason_type); - - /* union siginfo */ - type *siginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); - siginfo_type->set_name (gdbarch_obstack_strdup (gdbarch, "siginfo")); - append_composite_type_field (siginfo_type, "si_pad", - init_vector_type (char_type, 128)); - append_composite_type_field (siginfo_type, "_info", ksiginfo_type); - - nbsd_gdbarch_data->siginfo_type = siginfo_type; - - return siginfo_type; -} - -/* See nbsd-tdep.h. */ - -void -nbsd_info_proc_mappings_header (int addr_bit) -{ - printf_filtered (_("Mapped address spaces:\n\n")); - if (addr_bit == 64) - { - printf_filtered (" %18s %18s %10s %10s %9s %s\n", - "Start Addr", - " End Addr", - " Size", " Offset", "Flags ", "File"); - } - else - { - printf_filtered ("\t%10s %10s %10s %10s %9s %s\n", - "Start Addr", - " End Addr", - " Size", " Offset", "Flags ", "File"); - } -} - -/* Helper function to generate mappings flags for a single VM map - entry in 'info proc mappings'. */ - -static const char * -nbsd_vm_map_entry_flags (int kve_flags, int kve_protection) -{ - static char vm_flags[9]; - - vm_flags[0] = (kve_protection & KINFO_VME_PROT_READ) ? 'r' : '-'; - vm_flags[1] = (kve_protection & KINFO_VME_PROT_WRITE) ? 'w' : '-'; - vm_flags[2] = (kve_protection & KINFO_VME_PROT_EXEC) ? 'x' : '-'; - vm_flags[3] = ' '; - vm_flags[4] = (kve_flags & KINFO_VME_FLAG_COW) ? 'C' : '-'; - vm_flags[5] = (kve_flags & KINFO_VME_FLAG_NEEDS_COPY) ? 'N' : '-'; - vm_flags[6] = (kve_flags & KINFO_VME_FLAG_PAGEABLE) ? 'P' : '-'; - vm_flags[7] = (kve_flags & KINFO_VME_FLAG_GROWS_UP) ? 'U' - : (kve_flags & KINFO_VME_FLAG_GROWS_DOWN) ? 'D' : '-'; - vm_flags[8] = '\0'; - - return vm_flags; -} - -void -nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start, - ULONGEST kve_end, ULONGEST kve_offset, - int kve_flags, int kve_protection, - const char *kve_path) -{ - if (addr_bit == 64) - { - printf_filtered (" %18s %18s %10s %10s %9s %s\n", - hex_string (kve_start), - hex_string (kve_end), - hex_string (kve_end - kve_start), - hex_string (kve_offset), - nbsd_vm_map_entry_flags (kve_flags, kve_protection), - kve_path); - } - else - { - printf_filtered ("\t%10s %10s %10s %10s %9s %s\n", - hex_string (kve_start), - hex_string (kve_end), - hex_string (kve_end - kve_start), - hex_string (kve_offset), - nbsd_vm_map_entry_flags (kve_flags, kve_protection), - kve_path); - } -} - -/* Implement the "get_syscall_number" gdbarch method. */ - -static LONGEST -nbsd_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread) -{ - - /* NetBSD doesn't use gdbarch_get_syscall_number since NetBSD - native targets fetch the system call number from the - 'si_sysnum' member of siginfo_t in nbsd_nat_target::wait. - However, system call catching requires this function to be - set. */ - - internal_error (__FILE__, __LINE__, _("nbsd_get_sycall_number called")); -} - -/* See nbsd-tdep.h. */ - -void -nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - set_gdbarch_gdb_signal_from_target (gdbarch, nbsd_gdb_signal_from_target); - set_gdbarch_gdb_signal_to_target (gdbarch, nbsd_gdb_signal_to_target); - set_gdbarch_skip_solib_resolver (gdbarch, nbsd_skip_solib_resolver); - set_gdbarch_auxv_parse (gdbarch, svr4_auxv_parse); - set_gdbarch_get_siginfo_type (gdbarch, nbsd_get_siginfo_type); - - /* `catch syscall' */ - set_xml_syscall_file_name (gdbarch, "syscalls/netbsd.xml"); - set_gdbarch_get_syscall_number (gdbarch, nbsd_get_syscall_number); -} - -void _initialize_nbsd_tdep (); -void -_initialize_nbsd_tdep () -{ - nbsd_gdbarch_data_handle - = gdbarch_data_register_post_init (init_nbsd_gdbarch_data); -} diff --git a/gdb/nbsd-tdep.h b/gdb/nbsd-tdep.h deleted file mode 100644 index a6e3a8f0f3f..00000000000 --- a/gdb/nbsd-tdep.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Common target-dependent definitions for NetBSD systems. - Copyright (C) 2002-2020 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 3 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, see . */ - -#ifndef NBSD_TDEP_H -#define NBSD_TDEP_H - -struct link_map_offsets *nbsd_ilp32_solib_svr4_fetch_link_map_offsets (void); -struct link_map_offsets *nbsd_lp64_solib_svr4_fetch_link_map_offsets (void); - -int nbsd_pc_in_sigtramp (CORE_ADDR, const char *); - -/* NetBSD specific set of ABI-related routines. */ - -void nbsd_init_abi (struct gdbarch_info, struct gdbarch *); - -/* Output the header for "info proc mappings". ADDR_BIT is the size - of a virtual address in bits. */ - -extern void nbsd_info_proc_mappings_header (int addr_bit); - -/* Output description of a single memory range for "info proc - mappings". ADDR_BIT is the size of a virtual address in bits. The - KVE_START, KVE_END, KVE_OFFSET, KVE_FLAGS, and KVE_PROTECTION - parameters should contain the value of the corresponding fields in - a 'struct kinfo_vmentry'. The KVE_PATH parameter should contain a - pointer to the 'kve_path' field in a 'struct kinfo_vmentry'. */ - -extern void nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start, - ULONGEST kve_end, - ULONGEST kve_offset, - int kve_flags, int kve_protection, - const char *kve_path); - -#endif /* NBSD_TDEP_H */ diff --git a/gdb/netbsd-nat.c b/gdb/netbsd-nat.c new file mode 100644 index 00000000000..e7962e09e57 --- /dev/null +++ b/gdb/netbsd-nat.c @@ -0,0 +1,815 @@ +/* Native-dependent code for NetBSD. + + Copyright (C) 2006-2020 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 3 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, see . */ + +#include "defs.h" + +#include "netbsd-nat.h" +#include "nat/netbsd-nat.h" +#include "gdbthread.h" +#include "netbsd-tdep.h" +#include "inferior.h" +#include "gdbarch.h" + +#include +#include +#include +#include + +/* Return the name of a file that can be opened to get the symbols for + the child process identified by PID. */ + +char * +nbsd_nat_target::pid_to_exec_file (int pid) +{ + return const_cast (netbsd_nat::pid_to_exec_file (pid)); +} + +/* Return the current directory for the process identified by PID. */ + +static std::string +nbsd_pid_to_cwd (int pid) +{ + char buf[PATH_MAX]; + size_t buflen; + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_CWD}; + buflen = sizeof (buf); + if (sysctl (mib, ARRAY_SIZE (mib), buf, &buflen, NULL, 0)) + return ""; + return buf; +} + +/* Return the kinfo_proc2 structure for the process identified by PID. */ + +static bool +nbsd_pid_to_kinfo_proc2 (pid_t pid, struct kinfo_proc2 *kp) +{ + gdb_assert (kp != nullptr); + + size_t size = sizeof (*kp); + int mib[6] = {CTL_KERN, KERN_PROC2, KERN_PROC_PID, pid, + static_cast (size), 1}; + return !sysctl (mib, ARRAY_SIZE (mib), kp, &size, NULL, 0); +} + +/* Return the command line for the process identified by PID. */ + +static gdb::unique_xmalloc_ptr +nbsd_pid_to_cmdline (int pid) +{ + int mib[4] = {CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV}; + + size_t size = 0; + if (::sysctl (mib, ARRAY_SIZE (mib), NULL, &size, NULL, 0) == -1 || size == 0) + return nullptr; + + gdb::unique_xmalloc_ptr args (XNEWVAR (char, size)); + + if (::sysctl (mib, ARRAY_SIZE (mib), args.get (), &size, NULL, 0) == -1 + || size == 0) + return nullptr; + + /* Arguments are returned as a flattened string with NUL separators. + Join the arguments with spaces to form a single string. */ + for (size_t i = 0; i < size - 1; i++) + if (args[i] == '\0') + args[i] = ' '; + args[size - 1] = '\0'; + + return args; +} + +/* Return true if PTID is still active in the inferior. */ + +bool +nbsd_nat_target::thread_alive (ptid_t ptid) +{ + return netbsd_nat::thread_alive (ptid); +} + +/* Return the name assigned to a thread by an application. Returns + the string in a static buffer. */ + +const char * +nbsd_nat_target::thread_name (struct thread_info *thr) +{ + ptid_t ptid = thr->ptid; + return netbsd_nat::thread_name (ptid); +} + +/* Implement the "post_attach" target_ops method. */ + +static void +nbsd_add_threads (nbsd_nat_target *target, pid_t pid) +{ + auto fn + = [&target] (ptid_t ptid) + { + if (!in_thread_list (target, ptid)) + { + if (inferior_ptid.lwp () == 0) + thread_change_ptid (target, inferior_ptid, ptid); + else + add_thread (target, ptid); + } + }; + + netbsd_nat::for_each_thread (pid, fn); +} + +/* Implement the "post_startup_inferior" target_ops method. */ + +void +nbsd_nat_target::post_startup_inferior (ptid_t ptid) +{ + netbsd_nat::enable_proc_events (ptid.pid ()); +} + +/* Implement the "post_attach" target_ops method. */ + +void +nbsd_nat_target::post_attach (int pid) +{ + netbsd_nat::enable_proc_events (pid); + nbsd_add_threads (this, pid); +} + +/* Implement the "update_thread_list" target_ops method. */ + +void +nbsd_nat_target::update_thread_list () +{ + delete_exited_threads (); +} + +/* Convert PTID to a string. */ + +std::string +nbsd_nat_target::pid_to_str (ptid_t ptid) +{ + int lwp = ptid.lwp (); + + if (lwp != 0) + { + pid_t pid = ptid.pid (); + + return string_printf ("LWP %d of process %d", lwp, pid); + } + + return normal_pid_to_str (ptid); +} + +/* Retrieve all the memory regions in the specified process. */ + +static gdb::unique_xmalloc_ptr +nbsd_kinfo_get_vmmap (pid_t pid, size_t *size) +{ + int mib[5] = {CTL_VM, VM_PROC, VM_PROC_MAP, pid, + sizeof (struct kinfo_vmentry)}; + + size_t length = 0; + if (sysctl (mib, ARRAY_SIZE (mib), NULL, &length, NULL, 0)) + { + *size = 0; + return NULL; + } + + /* Prereserve more space. The length argument is volatile and can change + between the sysctl(3) calls as this function can be called against a + running process. */ + length = length * 5 / 3; + + gdb::unique_xmalloc_ptr kiv + (XNEWVAR (kinfo_vmentry, length)); + + if (sysctl (mib, ARRAY_SIZE (mib), kiv.get (), &length, NULL, 0)) + { + *size = 0; + return NULL; + } + + *size = length / sizeof (struct kinfo_vmentry); + return kiv; +} + +/* Iterate over all the memory regions in the current inferior, + calling FUNC for each memory region. OBFD is passed as the last + argument to FUNC. */ + +int +nbsd_nat_target::find_memory_regions (find_memory_region_ftype func, + void *data) +{ + pid_t pid = inferior_ptid.pid (); + + size_t nitems; + gdb::unique_xmalloc_ptr vmentl + = nbsd_kinfo_get_vmmap (pid, &nitems); + if (vmentl == NULL) + perror_with_name (_("Couldn't fetch VM map entries.")); + + for (size_t i = 0; i < nitems; i++) + { + struct kinfo_vmentry *kve = &vmentl[i]; + + /* Skip unreadable segments and those where MAP_NOCORE has been set. */ + if (!(kve->kve_protection & KVME_PROT_READ) + || kve->kve_flags & KVME_FLAG_NOCOREDUMP) + continue; + + /* Skip segments with an invalid type. */ + switch (kve->kve_type) + { + case KVME_TYPE_VNODE: + case KVME_TYPE_ANON: + case KVME_TYPE_SUBMAP: + case KVME_TYPE_OBJECT: + break; + default: + continue; + } + + size_t size = kve->kve_end - kve->kve_start; + if (info_verbose) + { + fprintf_filtered (gdb_stdout, + "Save segment, %ld bytes at %s (%c%c%c)\n", + (long) size, + paddress (target_gdbarch (), kve->kve_start), + kve->kve_protection & KVME_PROT_READ ? 'r' : '-', + kve->kve_protection & KVME_PROT_WRITE ? 'w' : '-', + kve->kve_protection & KVME_PROT_EXEC ? 'x' : '-'); + } + + /* Invoke the callback function to create the corefile segment. + Pass MODIFIED as true, we do not know the real modification state. */ + func (kve->kve_start, size, kve->kve_protection & KVME_PROT_READ, + kve->kve_protection & KVME_PROT_WRITE, + kve->kve_protection & KVME_PROT_EXEC, 1, data); + } + return 0; +} + +/* Implement the "info_proc" target_ops method. */ + +bool +nbsd_nat_target::info_proc (const char *args, enum info_proc_what what) +{ + pid_t pid; + bool do_cmdline = false; + bool do_cwd = false; + bool do_exe = false; + bool do_mappings = false; + bool do_status = false; + + switch (what) + { + case IP_MINIMAL: + do_cmdline = true; + do_cwd = true; + do_exe = true; + break; + case IP_STAT: + case IP_STATUS: + do_status = true; + break; + case IP_MAPPINGS: + do_mappings = true; + break; + case IP_CMDLINE: + do_cmdline = true; + break; + case IP_EXE: + do_exe = true; + break; + case IP_CWD: + do_cwd = true; + break; + case IP_ALL: + do_cmdline = true; + do_cwd = true; + do_exe = true; + do_mappings = true; + do_status = true; + break; + default: + error (_("Not supported on this target.")); + } + + gdb_argv built_argv (args); + if (built_argv.count () == 0) + { + pid = inferior_ptid.pid (); + if (pid == 0) + error (_("No current process: you must name one.")); + } + else if (built_argv.count () == 1 && isdigit (built_argv[0][0])) + pid = strtol (built_argv[0], NULL, 10); + else + error (_("Invalid arguments.")); + + printf_filtered (_("process %d\n"), pid); + + if (do_cmdline) + { + gdb::unique_xmalloc_ptr cmdline = nbsd_pid_to_cmdline (pid); + if (cmdline != nullptr) + printf_filtered ("cmdline = '%s'\n", cmdline.get ()); + else + warning (_("unable to fetch command line")); + } + if (do_cwd) + { + std::string cwd = nbsd_pid_to_cwd (pid); + if (cwd != "") + printf_filtered ("cwd = '%s'\n", cwd.c_str ()); + else + warning (_("unable to fetch current working directory")); + } + if (do_exe) + { + const char *exe = pid_to_exec_file (pid); + if (exe != nullptr) + printf_filtered ("exe = '%s'\n", exe); + else + warning (_("unable to fetch executable path name")); + } + if (do_mappings) + { + size_t nvment; + gdb::unique_xmalloc_ptr vmentl + = nbsd_kinfo_get_vmmap (pid, &nvment); + + if (vmentl != nullptr) + { + int addr_bit = TARGET_CHAR_BIT * sizeof (void *); + nbsd_info_proc_mappings_header (addr_bit); + + struct kinfo_vmentry *kve = vmentl.get (); + for (int i = 0; i < nvment; i++, kve++) + nbsd_info_proc_mappings_entry (addr_bit, kve->kve_start, + kve->kve_end, kve->kve_offset, + kve->kve_flags, kve->kve_protection, + kve->kve_path); + } + else + warning (_("unable to fetch virtual memory map")); + } + if (do_status) + { + struct kinfo_proc2 kp; + if (!nbsd_pid_to_kinfo_proc2 (pid, &kp)) + warning (_("Failed to fetch process information")); + else + { + auto process_status + = [] (int8_t stat) + { + switch (stat) + { + case SIDL: + return "IDL"; + case SACTIVE: + return "ACTIVE"; + case SDYING: + return "DYING"; + case SSTOP: + return "STOP"; + case SZOMB: + return "ZOMB"; + case SDEAD: + return "DEAD"; + default: + return "? (unknown)"; + } + }; + + printf_filtered ("Name: %s\n", kp.p_comm); + printf_filtered ("State: %s\n", process_status(kp.p_realstat)); + printf_filtered ("Parent process: %" PRId32 "\n", kp.p_ppid); + printf_filtered ("Process group: %" PRId32 "\n", kp.p__pgid); + printf_filtered ("Session id: %" PRId32 "\n", kp.p_sid); + printf_filtered ("TTY: %" PRId32 "\n", kp.p_tdev); + printf_filtered ("TTY owner process group: %" PRId32 "\n", kp.p_tpgid); + printf_filtered ("User IDs (real, effective, saved): " + "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n", + kp.p_ruid, kp.p_uid, kp.p_svuid); + printf_filtered ("Group IDs (real, effective, saved): " + "%" PRIu32 " %" PRIu32 " %" PRIu32 "\n", + kp.p_rgid, kp.p_gid, kp.p_svgid); + + printf_filtered ("Groups:"); + for (int i = 0; i < kp.p_ngroups; i++) + printf_filtered (" %" PRIu32, kp.p_groups[i]); + printf_filtered ("\n"); + printf_filtered ("Minor faults (no memory page): %" PRIu64 "\n", + kp.p_uru_minflt); + printf_filtered ("Major faults (memory page faults): %" PRIu64 "\n", + kp.p_uru_majflt); + printf_filtered ("utime: %" PRIu32 ".%06" PRIu32 "\n", + kp.p_uutime_sec, kp.p_uutime_usec); + printf_filtered ("stime: %" PRIu32 ".%06" PRIu32 "\n", + kp.p_ustime_sec, kp.p_ustime_usec); + printf_filtered ("utime+stime, children: %" PRIu32 ".%06" PRIu32 "\n", + kp.p_uctime_sec, kp.p_uctime_usec); + printf_filtered ("'nice' value: %" PRIu8 "\n", kp.p_nice); + printf_filtered ("Start time: %" PRIu32 ".%06" PRIu32 "\n", + kp.p_ustart_sec, kp.p_ustart_usec); + int pgtok = getpagesize () / 1024; + printf_filtered ("Data size: %" PRIuMAX " kB\n", + (uintmax_t) kp.p_vm_dsize * pgtok); + printf_filtered ("Stack size: %" PRIuMAX " kB\n", + (uintmax_t) kp.p_vm_ssize * pgtok); + printf_filtered ("Text size: %" PRIuMAX " kB\n", + (uintmax_t) kp.p_vm_tsize * pgtok); + printf_filtered ("Resident set size: %" PRIuMAX " kB\n", + (uintmax_t) kp.p_vm_rssize * pgtok); + printf_filtered ("Maximum RSS: %" PRIu64 " kB\n", kp.p_uru_maxrss); + printf_filtered ("Pending Signals:"); + for (size_t i = 0; i < ARRAY_SIZE (kp.p_siglist.__bits); i++) + printf_filtered (" %08" PRIx32, kp.p_siglist.__bits[i]); + printf_filtered ("\n"); + printf_filtered ("Ignored Signals:"); + for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigignore.__bits); i++) + printf_filtered (" %08" PRIx32, kp.p_sigignore.__bits[i]); + printf_filtered ("\n"); + printf_filtered ("Caught Signals:"); + for (size_t i = 0; i < ARRAY_SIZE (kp.p_sigcatch.__bits); i++) + printf_filtered (" %08" PRIx32, kp.p_sigcatch.__bits[i]); + printf_filtered ("\n"); + } + } + + return true; +} + +/* Resume execution of a specified PTID, that points to a process or a thread + within a process. If one thread is specified, all other threads are + suspended. If STEP is nonzero, single-step it. If SIGNAL is nonzero, + give it that signal. */ + +static void +nbsd_resume(nbsd_nat_target *target, ptid_t ptid, int step, + enum gdb_signal signal) +{ + int request; + + gdb_assert (minus_one_ptid != ptid); + + if (ptid.lwp_p ()) + { + /* If ptid is a specific LWP, suspend all other LWPs in the process. */ + inferior *inf = find_inferior_ptid (target, ptid); + + for (thread_info *tp : inf->non_exited_threads ()) + { + if (tp->ptid.lwp () == ptid.lwp ()) + request = PT_RESUME; + else + request = PT_SUSPEND; + + if (ptrace (request, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) + perror_with_name (("ptrace")); + } + } + else + { + /* If ptid is a wildcard, resume all matching threads (they won't run + until the process is continued however). */ + for (thread_info *tp : all_non_exited_threads (target, ptid)) + if (ptrace (PT_RESUME, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) + perror_with_name (("ptrace")); + } + + if (step) + { + for (thread_info *tp : all_non_exited_threads (target, ptid)) + if (ptrace (PT_SETSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) + perror_with_name (("ptrace")); + } + else + { + for (thread_info *tp : all_non_exited_threads (target, ptid)) + if (ptrace (PT_CLEARSTEP, tp->ptid.pid (), NULL, tp->ptid.lwp ()) == -1) + perror_with_name (("ptrace")); + } + + if (catch_syscall_enabled () > 0) + request = PT_SYSCALL; + else + request = PT_CONTINUE; + + /* An address of (void *)1 tells ptrace to continue from + where it was. If GDB wanted it to start some other way, we have + already written a new program counter value to the child. */ + if (ptrace (request, ptid.pid (), (void *)1, gdb_signal_to_host (signal)) == -1) + perror_with_name (("ptrace")); +} + +/* Resume execution of thread PTID, or all threads of all inferiors + if PTID is -1. If STEP is nonzero, single-step it. If SIGNAL is nonzero, + give it that signal. */ + +void +nbsd_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal) +{ + if (minus_one_ptid != ptid) + nbsd_resume (this, ptid, step, signal); + else + { + for (inferior *inf : all_non_exited_inferiors (this)) + nbsd_resume (this, ptid_t (inf->pid, 0, 0), step, signal); + } +} + +/* Implement a safe wrapper around waitpid(). */ + +static pid_t +nbsd_wait (ptid_t ptid, struct target_waitstatus *ourstatus, + target_wait_flags options) +{ + pid_t pid; + int status; + + set_sigint_trap (); + + do + { + /* The common code passes WNOHANG that leads to crashes, overwrite it. */ + pid = waitpid (ptid.pid (), &status, 0); + } + while (pid == -1 && errno == EINTR); + + clear_sigint_trap (); + + if (pid == -1) + perror_with_name (_("Child process unexpectedly missing")); + + store_waitstatus (ourstatus, status); + return pid; +} + +/* Wait for the child specified by PTID to do something. Return the + process ID of the child, or MINUS_ONE_PTID in case of error; store + the status in *OURSTATUS. */ + +ptid_t +nbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, + target_wait_flags target_options) +{ + pid_t pid = nbsd_wait (ptid, ourstatus, target_options); + ptid_t wptid = ptid_t (pid); + + /* If the child stopped, keep investigating its status. */ + if (ourstatus->kind != TARGET_WAITKIND_STOPPED) + return wptid; + + /* Extract the event and thread that received a signal. */ + ptrace_siginfo_t psi; + if (ptrace (PT_GET_SIGINFO, pid, &psi, sizeof (psi)) == -1) + perror_with_name (("ptrace")); + + /* Pick child's siginfo_t. */ + siginfo_t *si = &psi.psi_siginfo; + + int lwp = psi.psi_lwpid; + + int signo = si->si_signo; + const int code = si->si_code; + + /* Construct PTID with a specified thread that received the event. + If a signal was targeted to the whole process, lwp is 0. */ + wptid = ptid_t (pid, lwp, 0); + + /* Bail out on non-debugger oriented signals.. */ + if (signo != SIGTRAP) + return wptid; + + /* Stop examining non-debugger oriented SIGTRAP codes. */ + if (code <= SI_USER || code == SI_NOINFO) + return wptid; + + /* Process state for threading events */ + ptrace_state_t pst = {}; + if (code == TRAP_LWP) + { + if (ptrace (PT_GET_PROCESS_STATE, pid, &pst, sizeof (pst)) == -1) + perror_with_name (("ptrace")); + } + + if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_EXIT) + { + /* If GDB attaches to a multi-threaded process, exiting + threads might be skipped during post_attach that + have not yet reported their PTRACE_LWP_EXIT event. + Ignore exited events for an unknown LWP. */ + thread_info *thr = find_thread_ptid (this, wptid); + if (thr == nullptr) + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + else + { + ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED; + /* NetBSD does not store an LWP exit status. */ + ourstatus->value.integer = 0; + + if (print_thread_events) + printf_unfiltered (_("[%s exited]\n"), + target_pid_to_str (wptid).c_str ()); + delete_thread (thr); + } + + /* The GDB core expects that the rest of the threads are running. */ + if (ptrace (PT_CONTINUE, pid, (void *) 1, 0) == -1) + perror_with_name (("ptrace")); + + return wptid; + } + + if (in_thread_list (this, ptid_t (pid))) + thread_change_ptid (this, ptid_t (pid), wptid); + + if (code == TRAP_LWP && pst.pe_report_event == PTRACE_LWP_CREATE) + { + /* If GDB attaches to a multi-threaded process, newborn + threads might be added by nbsd_add_threads that have + not yet reported their PTRACE_LWP_CREATE event. Ignore + born events for an already-known LWP. */ + if (in_thread_list (this, wptid)) + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + else + { + add_thread (this, wptid); + ourstatus->kind = TARGET_WAITKIND_THREAD_CREATED; + } + return wptid; + } + + if (code == TRAP_EXEC) + { + ourstatus->kind = TARGET_WAITKIND_EXECD; + ourstatus->value.execd_pathname = xstrdup (pid_to_exec_file (pid)); + return wptid; + } + + if (code == TRAP_TRACE) + { + /* Unhandled at this level. */ + return wptid; + } + + if (code == TRAP_SCE || code == TRAP_SCX) + { + int sysnum = si->si_sysnum; + + if (!catch_syscall_enabled () || !catching_syscall_number (sysnum)) + { + /* If the core isn't interested in this event, ignore it. */ + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return wptid; + } + + ourstatus->kind = + (code == TRAP_SCE) ? TARGET_WAITKIND_SYSCALL_ENTRY : + TARGET_WAITKIND_SYSCALL_RETURN; + ourstatus->value.syscall_number = sysnum; + return wptid; + } + + if (code == TRAP_BRKPT) + { + /* Unhandled at this level. */ + return wptid; + } + + /* Unclassified SIGTRAP event. */ + ourstatus->kind = TARGET_WAITKIND_SPURIOUS; + return wptid; +} + +/* Implement the "insert_exec_catchpoint" target_ops method. */ + +int +nbsd_nat_target::insert_exec_catchpoint (int pid) +{ + /* Nothing to do. */ + return 0; +} + +/* Implement the "remove_exec_catchpoint" target_ops method. */ + +int +nbsd_nat_target::remove_exec_catchpoint (int pid) +{ + /* Nothing to do. */ + return 0; +} + +/* Implement the "set_syscall_catchpoint" target_ops method. */ + +int +nbsd_nat_target::set_syscall_catchpoint (int pid, bool needed, + int any_count, + gdb::array_view syscall_counts) +{ + /* Ignore the arguments. inf-ptrace.c will use PT_SYSCALL which + will catch all system call entries and exits. The system calls + are filtered by GDB rather than the kernel. */ + return 0; +} + +/* Implement the "supports_multi_process" target_ops method. */ + +bool +nbsd_nat_target::supports_multi_process () +{ + return true; +} + +/* Implement the "xfer_partial" target_ops method. */ + +enum target_xfer_status +nbsd_nat_target::xfer_partial (enum target_object object, + const char *annex, gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, + ULONGEST *xfered_len) +{ + pid_t pid = inferior_ptid.pid (); + + switch (object) + { + case TARGET_OBJECT_SIGNAL_INFO: + { + len = netbsd_nat::qxfer_siginfo(pid, annex, readbuf, writebuf, offset, + len); + + if (len == -1) + return TARGET_XFER_E_IO; + + *xfered_len = len; + return TARGET_XFER_OK; + } + case TARGET_OBJECT_MEMORY: + { + size_t xfered; + int res; + if (writebuf != nullptr) + res = netbsd_nat::write_memory (pid, writebuf, offset, len, &xfered); + else + res = netbsd_nat::read_memory (pid, readbuf, offset, len, &xfered); + if (res != 0) + { + if (res == EACCES) + fprintf_unfiltered (gdb_stderr, "Cannot %s process at %s (%s). " + "Is PaX MPROTECT active? See security(7), " + "sysctl(7), paxctl(8)\n", + (writebuf ? "write to" : "read from"), + pulongest (offset), safe_strerror (errno)); + return TARGET_XFER_E_IO; + } + if (xfered == 0) + return TARGET_XFER_EOF; + *xfered_len = (ULONGEST) xfered; + return TARGET_XFER_OK; + } + default: + return inf_ptrace_target::xfer_partial (object, annex, + readbuf, writebuf, offset, + len, xfered_len); + } +} + +/* Implement the "supports_dumpcore" target_ops method. */ + +bool +nbsd_nat_target::supports_dumpcore () +{ + return true; +} + +/* Implement the "dumpcore" target_ops method. */ + +void +nbsd_nat_target::dumpcore (const char *filename) +{ + pid_t pid = inferior_ptid.pid (); + + if (ptrace (PT_DUMPCORE, pid, const_cast(filename), + strlen (filename)) == -1) + perror_with_name (("ptrace")); +} diff --git a/gdb/netbsd-nat.h b/gdb/netbsd-nat.h new file mode 100644 index 00000000000..7a55094a8fc --- /dev/null +++ b/gdb/netbsd-nat.h @@ -0,0 +1,62 @@ +/* Native-dependent code for NetBSD. + + Copyright (C) 2006-2020 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 3 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, see . */ + +#ifndef NBSD_NAT_H +#define NBSD_NAT_H + +#include "inf-ptrace.h" + +struct thread_info; + +/* A prototype NetBSD target. */ + +struct nbsd_nat_target : public inf_ptrace_target +{ + char *pid_to_exec_file (int pid) override; + + bool thread_alive (ptid_t ptid) override; + const char *thread_name (struct thread_info *thr) override; + void post_startup_inferior (ptid_t ptid) override; + void post_attach (int pid) override; + void update_thread_list () override; + std::string pid_to_str (ptid_t ptid) override; + + int find_memory_regions (find_memory_region_ftype func, void *data) override; + bool info_proc (const char *, enum info_proc_what) override; + + void resume (ptid_t, int, enum gdb_signal) override; + ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override; + int insert_exec_catchpoint (int pid) override; + int remove_exec_catchpoint (int pid) override; + int set_syscall_catchpoint (int pid, bool needed, int any_count, + gdb::array_view syscall_counts) + override; + + bool supports_multi_process () override; + enum target_xfer_status xfer_partial (enum target_object object, + const char *annex, + gdb_byte *readbuf, + const gdb_byte *writebuf, + ULONGEST offset, ULONGEST len, + ULONGEST *xfered_len) override; + bool supports_dumpcore () override; + void dumpcore (const char *filename) override; +}; + +#endif /* netbsd-nat.h */ diff --git a/gdb/netbsd-tdep.c b/gdb/netbsd-tdep.c new file mode 100644 index 00000000000..0fa2d97b04a --- /dev/null +++ b/gdb/netbsd-tdep.c @@ -0,0 +1,632 @@ +/* Common target-dependent code for NetBSD systems. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "auxv.h" +#include "solib-svr4.h" +#include "netbsd-tdep.h" +#include "gdbarch.h" +#include "objfiles.h" +#include "xml-syscall.h" + +/* Flags in the 'kve_protection' field in struct kinfo_vmentry. These + match the KVME_PROT_* constants in . */ + +#define KINFO_VME_PROT_READ 0x00000001 +#define KINFO_VME_PROT_WRITE 0x00000002 +#define KINFO_VME_PROT_EXEC 0x00000004 + +/* Flags in the 'kve_flags' field in struct kinfo_vmentry. These + match the KVME_FLAG_* constants in . */ + +#define KINFO_VME_FLAG_COW 0x00000001 +#define KINFO_VME_FLAG_NEEDS_COPY 0x00000002 +#define KINFO_VME_FLAG_NOCOREDUMP 0x00000004 +#define KINFO_VME_FLAG_PAGEABLE 0x00000008 +#define KINFO_VME_FLAG_GROWS_UP 0x00000010 +#define KINFO_VME_FLAG_GROWS_DOWN 0x00000020 + +/* FIXME: kettenis/20060115: We should really eliminate the next two + functions completely. */ + +struct link_map_offsets * +nbsd_ilp32_solib_svr4_fetch_link_map_offsets (void) +{ + return svr4_ilp32_fetch_link_map_offsets (); +} + +struct link_map_offsets * +nbsd_lp64_solib_svr4_fetch_link_map_offsets (void) +{ + return svr4_lp64_fetch_link_map_offsets (); +} + +int +nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *func_name) +{ + /* Check for libc-provided signal trampoline. All such trampolines + have function names which begin with "__sigtramp". */ + + return (func_name != NULL + && startswith (func_name, "__sigtramp")); +} + +/* This enum is derived from NETBSD's . */ + +enum + { + NBSD_SIGHUP = 1, + NBSD_SIGINT = 2, + NBSD_SIGQUIT = 3, + NBSD_SIGILL = 4, + NBSD_SIGTRAP = 5, + NBSD_SIGABRT = 6, + NBSD_SIGEMT = 7, + NBSD_SIGFPE = 8, + NBSD_SIGKILL = 9, + NBSD_SIGBUS = 10, + NBSD_SIGSEGV = 11, + NBSD_SIGSYS = 12, + NBSD_SIGPIPE = 13, + NBSD_SIGALRM = 14, + NBSD_SIGTERM = 15, + NBSD_SIGURG = 16, + NBSD_SIGSTOP = 17, + NBSD_SIGTSTP = 18, + NBSD_SIGCONT = 19, + NBSD_SIGCHLD = 20, + NBSD_SIGTTIN = 21, + NBSD_SIGTTOU = 22, + NBSD_SIGIO = 23, + NBSD_SIGXCPU = 24, + NBSD_SIGXFSZ = 25, + NBSD_SIGVTALRM = 26, + NBSD_SIGPROF = 27, + NBSD_SIGWINCH = 28, + NBSD_SIGINFO = 29, + NBSD_SIGUSR1 = 30, + NBSD_SIGUSR2 = 31, + NBSD_SIGPWR = 32, + NBSD_SIGRTMIN = 33, + NBSD_SIGRTMAX = 63, + }; + +/* Implement the "gdb_signal_from_target" gdbarch method. */ + +static enum gdb_signal +nbsd_gdb_signal_from_target (struct gdbarch *gdbarch, int signal) +{ + switch (signal) + { + case 0: + return GDB_SIGNAL_0; + + case NBSD_SIGHUP: + return GDB_SIGNAL_HUP; + + case NBSD_SIGINT: + return GDB_SIGNAL_INT; + + case NBSD_SIGQUIT: + return GDB_SIGNAL_QUIT; + + case NBSD_SIGILL: + return GDB_SIGNAL_ILL; + + case NBSD_SIGTRAP: + return GDB_SIGNAL_TRAP; + + case NBSD_SIGABRT: + return GDB_SIGNAL_ABRT; + + case NBSD_SIGEMT: + return GDB_SIGNAL_EMT; + + case NBSD_SIGFPE: + return GDB_SIGNAL_FPE; + + case NBSD_SIGKILL: + return GDB_SIGNAL_KILL; + + case NBSD_SIGBUS: + return GDB_SIGNAL_BUS; + + case NBSD_SIGSEGV: + return GDB_SIGNAL_SEGV; + + case NBSD_SIGSYS: + return GDB_SIGNAL_SYS; + + case NBSD_SIGPIPE: + return GDB_SIGNAL_PIPE; + + case NBSD_SIGALRM: + return GDB_SIGNAL_ALRM; + + case NBSD_SIGTERM: + return GDB_SIGNAL_TERM; + + case NBSD_SIGURG: + return GDB_SIGNAL_URG; + + case NBSD_SIGSTOP: + return GDB_SIGNAL_STOP; + + case NBSD_SIGTSTP: + return GDB_SIGNAL_TSTP; + + case NBSD_SIGCONT: + return GDB_SIGNAL_CONT; + + case NBSD_SIGCHLD: + return GDB_SIGNAL_CHLD; + + case NBSD_SIGTTIN: + return GDB_SIGNAL_TTIN; + + case NBSD_SIGTTOU: + return GDB_SIGNAL_TTOU; + + case NBSD_SIGIO: + return GDB_SIGNAL_IO; + + case NBSD_SIGXCPU: + return GDB_SIGNAL_XCPU; + + case NBSD_SIGXFSZ: + return GDB_SIGNAL_XFSZ; + + case NBSD_SIGVTALRM: + return GDB_SIGNAL_VTALRM; + + case NBSD_SIGPROF: + return GDB_SIGNAL_PROF; + + case NBSD_SIGWINCH: + return GDB_SIGNAL_WINCH; + + case NBSD_SIGINFO: + return GDB_SIGNAL_INFO; + + case NBSD_SIGUSR1: + return GDB_SIGNAL_USR1; + + case NBSD_SIGUSR2: + return GDB_SIGNAL_USR2; + + case NBSD_SIGPWR: + return GDB_SIGNAL_PWR; + + /* SIGRTMIN and SIGRTMAX are not continuous in , + therefore we have to handle them here. */ + case NBSD_SIGRTMIN: + return GDB_SIGNAL_REALTIME_33; + + case NBSD_SIGRTMAX: + return GDB_SIGNAL_REALTIME_63; + } + + if (signal >= NBSD_SIGRTMIN + 1 && signal <= NBSD_SIGRTMAX - 1) + { + int offset = signal - NBSD_SIGRTMIN + 1; + + return (enum gdb_signal) ((int) GDB_SIGNAL_REALTIME_34 + offset); + } + + return GDB_SIGNAL_UNKNOWN; +} + +/* Implement the "gdb_signal_to_target" gdbarch method. */ + +static int +nbsd_gdb_signal_to_target (struct gdbarch *gdbarch, + enum gdb_signal signal) +{ + switch (signal) + { + case GDB_SIGNAL_0: + return 0; + + case GDB_SIGNAL_HUP: + return NBSD_SIGHUP; + + case GDB_SIGNAL_INT: + return NBSD_SIGINT; + + case GDB_SIGNAL_QUIT: + return NBSD_SIGQUIT; + + case GDB_SIGNAL_ILL: + return NBSD_SIGILL; + + case GDB_SIGNAL_TRAP: + return NBSD_SIGTRAP; + + case GDB_SIGNAL_ABRT: + return NBSD_SIGABRT; + + case GDB_SIGNAL_EMT: + return NBSD_SIGEMT; + + case GDB_SIGNAL_FPE: + return NBSD_SIGFPE; + + case GDB_SIGNAL_KILL: + return NBSD_SIGKILL; + + case GDB_SIGNAL_BUS: + return NBSD_SIGBUS; + + case GDB_SIGNAL_SEGV: + return NBSD_SIGSEGV; + + case GDB_SIGNAL_SYS: + return NBSD_SIGSYS; + + case GDB_SIGNAL_PIPE: + return NBSD_SIGPIPE; + + case GDB_SIGNAL_ALRM: + return NBSD_SIGALRM; + + case GDB_SIGNAL_TERM: + return NBSD_SIGTERM; + + case GDB_SIGNAL_URG: + return NBSD_SIGSTOP; + + case GDB_SIGNAL_TSTP: + return NBSD_SIGTSTP; + + case GDB_SIGNAL_CONT: + return NBSD_SIGCONT; + + case GDB_SIGNAL_CHLD: + return NBSD_SIGCHLD; + + case GDB_SIGNAL_TTIN: + return NBSD_SIGTTIN; + + case GDB_SIGNAL_TTOU: + return NBSD_SIGTTOU; + + case GDB_SIGNAL_IO: + return NBSD_SIGIO; + + case GDB_SIGNAL_XCPU: + return NBSD_SIGXCPU; + + case GDB_SIGNAL_XFSZ: + return NBSD_SIGXFSZ; + + case GDB_SIGNAL_VTALRM: + return NBSD_SIGVTALRM; + + case GDB_SIGNAL_PROF: + return NBSD_SIGPROF; + + case GDB_SIGNAL_WINCH: + return NBSD_SIGWINCH; + + case GDB_SIGNAL_INFO: + return NBSD_SIGINFO; + + case GDB_SIGNAL_USR1: + return NBSD_SIGUSR1; + + case GDB_SIGNAL_USR2: + return NBSD_SIGUSR2; + + case GDB_SIGNAL_PWR: + return NBSD_SIGPWR; + + /* GDB_SIGNAL_REALTIME_33 is not continuous in , + therefore we have to handle it here. */ + case GDB_SIGNAL_REALTIME_33: + return NBSD_SIGRTMIN; + + /* Same comment applies to _64. */ + case GDB_SIGNAL_REALTIME_63: + return NBSD_SIGRTMAX; + } + + if (signal >= GDB_SIGNAL_REALTIME_34 + && signal <= GDB_SIGNAL_REALTIME_62) + { + int offset = signal - GDB_SIGNAL_REALTIME_32; + + return NBSD_SIGRTMIN + 1 + offset; + } + + return -1; +} + +/* Shared library resolver handling. */ + +static CORE_ADDR +nbsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + struct bound_minimal_symbol msym; + + msym = lookup_minimal_symbol ("_rtld_bind_start", NULL, NULL); + if (msym.minsym && BMSYMBOL_VALUE_ADDRESS (msym) == pc) + return frame_unwind_caller_pc (get_current_frame ()); + else + return find_solib_trampoline_target (get_current_frame (), pc); +} + +static struct gdbarch_data *nbsd_gdbarch_data_handle; + +struct nbsd_gdbarch_data +{ + struct type *siginfo_type; +}; + +static void * +init_nbsd_gdbarch_data (struct gdbarch *gdbarch) +{ + return GDBARCH_OBSTACK_ZALLOC (gdbarch, struct nbsd_gdbarch_data); +} + +static struct nbsd_gdbarch_data * +get_nbsd_gdbarch_data (struct gdbarch *gdbarch) +{ + return ((struct nbsd_gdbarch_data *) + gdbarch_data (gdbarch, nbsd_gdbarch_data_handle)); +} + +/* Implement the "get_siginfo_type" gdbarch method. */ + +static struct type * +nbsd_get_siginfo_type (struct gdbarch *gdbarch) +{ + nbsd_gdbarch_data *nbsd_gdbarch_data = get_nbsd_gdbarch_data (gdbarch); + if (nbsd_gdbarch_data->siginfo_type != NULL) + return nbsd_gdbarch_data->siginfo_type; + + type *char_type = builtin_type (gdbarch)->builtin_char; + type *int_type = builtin_type (gdbarch)->builtin_int; + type *long_type = builtin_type (gdbarch)->builtin_long; + + type *void_ptr_type + = lookup_pointer_type (builtin_type (gdbarch)->builtin_void); + + type *int32_type = builtin_type (gdbarch)->builtin_int32; + type *uint32_type = builtin_type (gdbarch)->builtin_uint32; + type *uint64_type = builtin_type (gdbarch)->builtin_uint64; + + bool lp64 = TYPE_LENGTH (void_ptr_type) == 8; + size_t char_bits = gdbarch_addressable_memory_unit_size (gdbarch) * 8; + + /* pid_t */ + type *pid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, + TYPE_LENGTH (int32_type) * char_bits, "pid_t"); + TYPE_TARGET_TYPE (pid_type) = int32_type; + + /* uid_t */ + type *uid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, + TYPE_LENGTH (uint32_type) * char_bits, "uid_t"); + TYPE_TARGET_TYPE (uid_type) = uint32_type; + + /* clock_t */ + type *clock_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, + TYPE_LENGTH (int_type) * char_bits, "clock_t"); + TYPE_TARGET_TYPE (clock_type) = int_type; + + /* lwpid_t */ + type *lwpid_type = arch_type (gdbarch, TYPE_CODE_TYPEDEF, + TYPE_LENGTH (int32_type) * char_bits, + "lwpid_t"); + TYPE_TARGET_TYPE (lwpid_type) = int32_type; + + /* union sigval */ + type *sigval_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); + sigval_type->set_name (gdbarch_obstack_strdup (gdbarch, "sigval")); + append_composite_type_field (sigval_type, "sival_int", int_type); + append_composite_type_field (sigval_type, "sival_ptr", void_ptr_type); + + /* union _option */ + type *option_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); + option_type->set_name (gdbarch_obstack_strdup (gdbarch, "_option")); + append_composite_type_field (option_type, "_pe_other_pid", pid_type); + append_composite_type_field (option_type, "_pe_lwp", lwpid_type); + + /* union _reason */ + type *reason_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); + + /* _rt */ + type *t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); + append_composite_type_field (t, "_pid", pid_type); + append_composite_type_field (t, "_uid", uid_type); + append_composite_type_field (t, "_value", sigval_type); + append_composite_type_field (reason_type, "_rt", t); + + /* _child */ + t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); + append_composite_type_field (t, "_pid", pid_type); + append_composite_type_field (t, "_uid", uid_type); + append_composite_type_field (t, "_status", int_type); + append_composite_type_field (t, "_utime", clock_type); + append_composite_type_field (t, "_stime", clock_type); + append_composite_type_field (reason_type, "_child", t); + + /* _fault */ + t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); + append_composite_type_field (t, "_addr", void_ptr_type); + append_composite_type_field (t, "_trap", int_type); + append_composite_type_field (t, "_trap2", int_type); + append_composite_type_field (t, "_trap3", int_type); + append_composite_type_field (reason_type, "_fault", t); + + /* _poll */ + t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); + append_composite_type_field (t, "_band", long_type); + append_composite_type_field (t, "_fd", int_type); + append_composite_type_field (reason_type, "_poll", t); + + /* _syscall */ + t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); + append_composite_type_field (t, "_sysnum", int_type); + append_composite_type_field (t, "_retval", + init_vector_type (int_type, 2)); + append_composite_type_field (t, "_error", int_type); + append_composite_type_field (t, "_args", + init_vector_type (uint64_type, 8)); + append_composite_type_field (reason_type, "_syscall", t); + + /* _ptrace_state */ + t = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); + append_composite_type_field (t, "_pe_report_event", int_type); + append_composite_type_field (t, "_option", option_type); + append_composite_type_field (reason_type, "_ptrace_state", t); + + /* struct _ksiginfo */ + type *ksiginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_STRUCT); + ksiginfo_type->set_name (gdbarch_obstack_strdup (gdbarch, "_ksiginfo")); + append_composite_type_field (ksiginfo_type, "_signo", int_type); + append_composite_type_field (ksiginfo_type, "_code", int_type); + append_composite_type_field (ksiginfo_type, "_errno", int_type); + if (lp64) + append_composite_type_field (ksiginfo_type, "_pad", int_type); + append_composite_type_field (ksiginfo_type, "_reason", reason_type); + + /* union siginfo */ + type *siginfo_type = arch_composite_type (gdbarch, NULL, TYPE_CODE_UNION); + siginfo_type->set_name (gdbarch_obstack_strdup (gdbarch, "siginfo")); + append_composite_type_field (siginfo_type, "si_pad", + init_vector_type (char_type, 128)); + append_composite_type_field (siginfo_type, "_info", ksiginfo_type); + + nbsd_gdbarch_data->siginfo_type = siginfo_type; + + return siginfo_type; +} + +/* See nbsd-tdep.h. */ + +void +nbsd_info_proc_mappings_header (int addr_bit) +{ + printf_filtered (_("Mapped address spaces:\n\n")); + if (addr_bit == 64) + { + printf_filtered (" %18s %18s %10s %10s %9s %s\n", + "Start Addr", + " End Addr", + " Size", " Offset", "Flags ", "File"); + } + else + { + printf_filtered ("\t%10s %10s %10s %10s %9s %s\n", + "Start Addr", + " End Addr", + " Size", " Offset", "Flags ", "File"); + } +} + +/* Helper function to generate mappings flags for a single VM map + entry in 'info proc mappings'. */ + +static const char * +nbsd_vm_map_entry_flags (int kve_flags, int kve_protection) +{ + static char vm_flags[9]; + + vm_flags[0] = (kve_protection & KINFO_VME_PROT_READ) ? 'r' : '-'; + vm_flags[1] = (kve_protection & KINFO_VME_PROT_WRITE) ? 'w' : '-'; + vm_flags[2] = (kve_protection & KINFO_VME_PROT_EXEC) ? 'x' : '-'; + vm_flags[3] = ' '; + vm_flags[4] = (kve_flags & KINFO_VME_FLAG_COW) ? 'C' : '-'; + vm_flags[5] = (kve_flags & KINFO_VME_FLAG_NEEDS_COPY) ? 'N' : '-'; + vm_flags[6] = (kve_flags & KINFO_VME_FLAG_PAGEABLE) ? 'P' : '-'; + vm_flags[7] = (kve_flags & KINFO_VME_FLAG_GROWS_UP) ? 'U' + : (kve_flags & KINFO_VME_FLAG_GROWS_DOWN) ? 'D' : '-'; + vm_flags[8] = '\0'; + + return vm_flags; +} + +void +nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start, + ULONGEST kve_end, ULONGEST kve_offset, + int kve_flags, int kve_protection, + const char *kve_path) +{ + if (addr_bit == 64) + { + printf_filtered (" %18s %18s %10s %10s %9s %s\n", + hex_string (kve_start), + hex_string (kve_end), + hex_string (kve_end - kve_start), + hex_string (kve_offset), + nbsd_vm_map_entry_flags (kve_flags, kve_protection), + kve_path); + } + else + { + printf_filtered ("\t%10s %10s %10s %10s %9s %s\n", + hex_string (kve_start), + hex_string (kve_end), + hex_string (kve_end - kve_start), + hex_string (kve_offset), + nbsd_vm_map_entry_flags (kve_flags, kve_protection), + kve_path); + } +} + +/* Implement the "get_syscall_number" gdbarch method. */ + +static LONGEST +nbsd_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread) +{ + + /* NetBSD doesn't use gdbarch_get_syscall_number since NetBSD + native targets fetch the system call number from the + 'si_sysnum' member of siginfo_t in nbsd_nat_target::wait. + However, system call catching requires this function to be + set. */ + + internal_error (__FILE__, __LINE__, _("nbsd_get_sycall_number called")); +} + +/* See nbsd-tdep.h. */ + +void +nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + set_gdbarch_gdb_signal_from_target (gdbarch, nbsd_gdb_signal_from_target); + set_gdbarch_gdb_signal_to_target (gdbarch, nbsd_gdb_signal_to_target); + set_gdbarch_skip_solib_resolver (gdbarch, nbsd_skip_solib_resolver); + set_gdbarch_auxv_parse (gdbarch, svr4_auxv_parse); + set_gdbarch_get_siginfo_type (gdbarch, nbsd_get_siginfo_type); + + /* `catch syscall' */ + set_xml_syscall_file_name (gdbarch, "syscalls/netbsd.xml"); + set_gdbarch_get_syscall_number (gdbarch, nbsd_get_syscall_number); +} + +void _initialize_nbsd_tdep (); +void +_initialize_nbsd_tdep () +{ + nbsd_gdbarch_data_handle + = gdbarch_data_register_post_init (init_nbsd_gdbarch_data); +} diff --git a/gdb/netbsd-tdep.h b/gdb/netbsd-tdep.h new file mode 100644 index 00000000000..a6e3a8f0f3f --- /dev/null +++ b/gdb/netbsd-tdep.h @@ -0,0 +1,50 @@ +/* Common target-dependent definitions for NetBSD systems. + Copyright (C) 2002-2020 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 3 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, see . */ + +#ifndef NBSD_TDEP_H +#define NBSD_TDEP_H + +struct link_map_offsets *nbsd_ilp32_solib_svr4_fetch_link_map_offsets (void); +struct link_map_offsets *nbsd_lp64_solib_svr4_fetch_link_map_offsets (void); + +int nbsd_pc_in_sigtramp (CORE_ADDR, const char *); + +/* NetBSD specific set of ABI-related routines. */ + +void nbsd_init_abi (struct gdbarch_info, struct gdbarch *); + +/* Output the header for "info proc mappings". ADDR_BIT is the size + of a virtual address in bits. */ + +extern void nbsd_info_proc_mappings_header (int addr_bit); + +/* Output description of a single memory range for "info proc + mappings". ADDR_BIT is the size of a virtual address in bits. The + KVE_START, KVE_END, KVE_OFFSET, KVE_FLAGS, and KVE_PROTECTION + parameters should contain the value of the corresponding fields in + a 'struct kinfo_vmentry'. The KVE_PATH parameter should contain a + pointer to the 'kve_path' field in a 'struct kinfo_vmentry'. */ + +extern void nbsd_info_proc_mappings_entry (int addr_bit, ULONGEST kve_start, + ULONGEST kve_end, + ULONGEST kve_offset, + int kve_flags, int kve_protection, + const char *kve_path); + +#endif /* NBSD_TDEP_H */ diff --git a/gdb/ppc-nbsd-nat.c b/gdb/ppc-nbsd-nat.c deleted file mode 100644 index 8111f3ed0b7..00000000000 --- a/gdb/ppc-nbsd-nat.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Native-dependent code for NetBSD/powerpc. - - Copyright (C) 2002-2020 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 3 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, see . */ - -/* We define this to get types like register_t. */ -#define _KERNTYPES -#include "defs.h" - -#include -#include -#include -#include -#include - -#include "gdbcore.h" -#include "inferior.h" -#include "regcache.h" - -#include "ppc-tdep.h" -#include "ppc-nbsd-tdep.h" -#include "bsd-kvm.h" -#include "inf-ptrace.h" -#include "nbsd-nat.h" - -struct ppc_nbsd_nat_target final : public nbsd_nat_target -{ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; -}; - -static ppc_nbsd_nat_target the_ppc_nbsd_nat_target; - -/* Returns true if PT_GETREGS fetches this register. */ - -static int -getregs_supplies (struct gdbarch *gdbarch, int regnum) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - return ((regnum >= tdep->ppc_gp0_regnum - && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs) - || regnum == tdep->ppc_lr_regnum - || regnum == tdep->ppc_cr_regnum - || regnum == tdep->ppc_xer_regnum - || regnum == tdep->ppc_ctr_regnum - || regnum == gdbarch_pc_regnum (gdbarch)); -} - -/* Like above, but for PT_GETFPREGS. */ - -static int -getfpregs_supplies (struct gdbarch *gdbarch, int regnum) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating - point registers. Traditionally, GDB's register set has still - listed the floating point registers for such machines, so this - code is harmless. However, the new E500 port actually omits the - floating point registers entirely from the register set --- they - don't even have register numbers assigned to them. - - It's not clear to me how best to update this code, so this assert - will alert the first person to encounter the NetBSD/E500 - combination to the problem. */ - gdb_assert (ppc_floating_point_unit_p (gdbarch)); - - return ((regnum >= tdep->ppc_fp0_regnum - && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs) - || regnum == tdep->ppc_fpscr_regnum); -} - -void -ppc_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - pid_t pid = regcache->ptid ().pid (); - int lwp = regcache->ptid ().lwp (); - - if (regnum == -1 || getregs_supplies (gdbarch, regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) - perror_with_name (_("Couldn't get registers")); - - ppc_supply_gregset (&ppcnbsd_gregset, regcache, - regnum, ®s, sizeof regs); - } - - if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) - perror_with_name (_("Couldn't get FP registers")); - - ppc_supply_fpregset (&ppcnbsd_fpregset, regcache, - regnum, &fpregs, sizeof fpregs); - } -} - -void -ppc_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = regcache->arch (); - pid_t pid = regcache->ptid ().pid (); - int lwp = regcache->ptid ().lwp (); - - if (regnum == -1 || getregs_supplies (gdbarch, regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) - perror_with_name (_("Couldn't get registers")); - - ppc_collect_gregset (&ppcnbsd_gregset, regcache, - regnum, ®s, sizeof regs); - - if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) - perror_with_name (_("Couldn't write registers")); - } - - if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) - perror_with_name (_("Couldn't get FP registers")); - - ppc_collect_fpregset (&ppcnbsd_fpregset, regcache, - regnum, &fpregs, sizeof fpregs); - - if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) - perror_with_name (_("Couldn't set FP registers")); - } -} - -static int -ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - struct switchframe sf; - struct callframe cf; - struct gdbarch *gdbarch = regcache->arch (); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - int i; - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_sp == 0) - return 0; - - read_memory (pcb->pcb_sp, (gdb_byte *)&sf, sizeof sf); - regcache->raw_supply (tdep->ppc_cr_regnum, &sf.cr); - regcache->raw_supply (tdep->ppc_gp0_regnum + 2, &sf.fixreg2); - for (i = 0 ; i < 19 ; i++) - regcache->raw_supply (tdep->ppc_gp0_regnum + 13 + i, &sf.fixreg[i]); - - read_memory(sf.sp, (gdb_byte *)&cf, sizeof(cf)); - regcache->raw_supply (tdep->ppc_gp0_regnum + 30, &cf.r30); - regcache->raw_supply (tdep->ppc_gp0_regnum + 31, &cf.r31); - regcache->raw_supply (tdep->ppc_gp0_regnum + 1, &cf.sp); - - read_memory(cf.sp, (gdb_byte *)&cf, sizeof(cf)); - regcache->raw_supply (tdep->ppc_lr_regnum, &cf.lr); - regcache->raw_supply (gdbarch_pc_regnum (gdbarch), &cf.lr); - - return 1; -} - -void _initialize_ppcnbsd_nat (); -void -_initialize_ppcnbsd_nat () -{ - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (ppcnbsd_supply_pcb); - - add_inf_child_target (&the_ppc_nbsd_nat_target); -} diff --git a/gdb/ppc-nbsd-tdep.c b/gdb/ppc-nbsd-tdep.c deleted file mode 100644 index fa90243d964..00000000000 --- a/gdb/ppc-nbsd-tdep.c +++ /dev/null @@ -1,223 +0,0 @@ -/* Target-dependent code for NetBSD/powerpc. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "gdbtypes.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "trad-frame.h" -#include "tramp-frame.h" - -#include "ppc-tdep.h" -#include "nbsd-tdep.h" -#include "ppc-tdep.h" -#include "solib-svr4.h" - -/* Register offsets from . */ -struct ppc_reg_offsets ppcnbsd_reg_offsets; - - -/* Core file support. */ - -/* NetBSD/powerpc register sets. */ - -const struct regset ppcnbsd_gregset = -{ - &ppcnbsd_reg_offsets, - ppc_supply_gregset -}; - -const struct regset ppcnbsd_fpregset = -{ - &ppcnbsd_reg_offsets, - ppc_supply_fpregset -}; - -/* Iterate over core file register note sections. */ - -static void -ppcnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", 148, 148, &ppcnbsd_gregset, NULL, cb_data); - cb (".reg2", 264, 264, &ppcnbsd_fpregset, NULL, cb_data); -} - - -/* NetBSD is confused. It appears that 1.5 was using the correct SVR4 - convention but, 1.6 switched to the below broken convention. For - the moment use the broken convention. Ulgh! */ - -static enum return_value_convention -ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function, - struct type *valtype, struct regcache *regcache, - gdb_byte *readbuf, const gdb_byte *writebuf) -{ -#if 0 - if ((valtype->code () == TYPE_CODE_STRUCT - || valtype->code () == TYPE_CODE_UNION) - && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8) - && valtype->is_vector ()) - && !(TYPE_LENGTH (valtype) == 1 - || TYPE_LENGTH (valtype) == 2 - || TYPE_LENGTH (valtype) == 4 - || TYPE_LENGTH (valtype) == 8)) - return RETURN_VALUE_STRUCT_CONVENTION; - else -#endif - return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, - regcache, readbuf, writebuf); -} - - -/* Signal trampolines. */ - -extern const struct tramp_frame ppcnbsd2_sigtramp; - -static void -ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self, - struct frame_info *this_frame, - struct trad_frame_cache *this_cache, - CORE_ADDR func) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - CORE_ADDR addr, base; - int i; - - base = get_frame_register_unsigned (this_frame, - gdbarch_sp_regnum (gdbarch)); - if (self == &ppcnbsd2_sigtramp) - addr = base + 0x10 + 2 * tdep->wordsize; - else - addr = base + 0x18 + 2 * tdep->wordsize; - for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize) - { - int regnum = i + tdep->ppc_gp0_regnum; - trad_frame_set_reg_addr (this_cache, regnum, addr); - } - trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch), - addr); /* SRR0? */ - addr += tdep->wordsize; - - /* Construct the frame ID using the function start. */ - trad_frame_set_id (this_cache, frame_id_build (base, func)); -} - -static const struct tramp_frame ppcnbsd_sigtramp = -{ - SIGTRAMP_FRAME, - 4, - { - { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */ - { 0x4e800021, ULONGEST_MAX }, /* blrl */ - { 0x38610018, ULONGEST_MAX }, /* addi r3,r1,24 */ - { 0x38000127, ULONGEST_MAX }, /* li r0,295 */ - { 0x44000002, ULONGEST_MAX }, /* sc */ - { 0x38000001, ULONGEST_MAX }, /* li r0,1 */ - { 0x44000002, ULONGEST_MAX }, /* sc */ - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - ppcnbsd_sigtramp_cache_init -}; - -/* NetBSD 2.0 introduced a slightly different signal trampoline. */ - -const struct tramp_frame ppcnbsd2_sigtramp = -{ - SIGTRAMP_FRAME, - 4, - { - { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */ - { 0x4e800021, ULONGEST_MAX }, /* blrl */ - { 0x38610010, ULONGEST_MAX }, /* addi r3,r1,16 */ - { 0x38000127, ULONGEST_MAX }, /* li r0,295 */ - { 0x44000002, ULONGEST_MAX }, /* sc */ - { 0x38000001, ULONGEST_MAX }, /* li r0,1 */ - { 0x44000002, ULONGEST_MAX }, /* sc */ - { TRAMP_SENTINEL_INSN, ULONGEST_MAX } - }, - ppcnbsd_sigtramp_cache_init -}; - - -static void -ppcnbsd_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - nbsd_init_abi (info, gdbarch); - - /* For NetBSD, this is an on again, off again thing. Some systems - do use the broken struct convention, and some don't. */ - set_gdbarch_return_value (gdbarch, ppcnbsd_return_value); - - /* NetBSD uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); - - set_gdbarch_iterate_over_regset_sections - (gdbarch, ppcnbsd_iterate_over_regset_sections); - - tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd_sigtramp); - tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd2_sigtramp); -} - -void _initialize_ppcnbsd_tdep (); -void -_initialize_ppcnbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD, - ppcnbsd_init_abi); - - /* Avoid initializing the register offsets again if they were - already initialized by ppcnbsd-nat.c. */ - if (ppcnbsd_reg_offsets.pc_offset == 0) - { - /* General-purpose registers. */ - ppcnbsd_reg_offsets.r0_offset = 0; - ppcnbsd_reg_offsets.gpr_size = 4; - ppcnbsd_reg_offsets.xr_size = 4; - ppcnbsd_reg_offsets.lr_offset = 128; - ppcnbsd_reg_offsets.cr_offset = 132; - ppcnbsd_reg_offsets.xer_offset = 136; - ppcnbsd_reg_offsets.ctr_offset = 140; - ppcnbsd_reg_offsets.pc_offset = 144; - ppcnbsd_reg_offsets.ps_offset = -1; - ppcnbsd_reg_offsets.mq_offset = -1; - - /* Floating-point registers. */ - ppcnbsd_reg_offsets.f0_offset = 0; - ppcnbsd_reg_offsets.fpscr_offset = 256; - ppcnbsd_reg_offsets.fpscr_size = 4; - - } -} diff --git a/gdb/ppc-nbsd-tdep.h b/gdb/ppc-nbsd-tdep.h deleted file mode 100644 index efbed9ea002..00000000000 --- a/gdb/ppc-nbsd-tdep.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Target-dependent code for NetBSD/powerpc. - - Copyright (C) 2004-2020 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 3 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, see . */ - -#ifndef PPC_NBSD_TDEP_H -#define PPC_NBSD_TDEP_H - -struct regset; - -/* Register offsets for NetBSD/powerpc. */ -extern struct ppc_reg_offsets ppcnbsd_reg_offsets; - -/* Register sets for NetBSD/powerpc. */ -extern const struct regset ppcnbsd_gregset; -extern const struct regset ppcnbsd_fpregset; - -#endif /* PPC_NBSD_TDEP_H */ diff --git a/gdb/ppc-netbsd-nat.c b/gdb/ppc-netbsd-nat.c new file mode 100644 index 00000000000..6ecff118238 --- /dev/null +++ b/gdb/ppc-netbsd-nat.c @@ -0,0 +1,195 @@ +/* Native-dependent code for NetBSD/powerpc. + + Copyright (C) 2002-2020 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 3 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, see . */ + +/* We define this to get types like register_t. */ +#define _KERNTYPES +#include "defs.h" + +#include +#include +#include +#include +#include + +#include "gdbcore.h" +#include "inferior.h" +#include "regcache.h" + +#include "ppc-tdep.h" +#include "ppc-netbsd-tdep.h" +#include "bsd-kvm.h" +#include "inf-ptrace.h" +#include "netbsd-nat.h" + +struct ppc_nbsd_nat_target final : public nbsd_nat_target +{ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; +}; + +static ppc_nbsd_nat_target the_ppc_nbsd_nat_target; + +/* Returns true if PT_GETREGS fetches this register. */ + +static int +getregs_supplies (struct gdbarch *gdbarch, int regnum) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + return ((regnum >= tdep->ppc_gp0_regnum + && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs) + || regnum == tdep->ppc_lr_regnum + || regnum == tdep->ppc_cr_regnum + || regnum == tdep->ppc_xer_regnum + || regnum == tdep->ppc_ctr_regnum + || regnum == gdbarch_pc_regnum (gdbarch)); +} + +/* Like above, but for PT_GETFPREGS. */ + +static int +getfpregs_supplies (struct gdbarch *gdbarch, int regnum) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating + point registers. Traditionally, GDB's register set has still + listed the floating point registers for such machines, so this + code is harmless. However, the new E500 port actually omits the + floating point registers entirely from the register set --- they + don't even have register numbers assigned to them. + + It's not clear to me how best to update this code, so this assert + will alert the first person to encounter the NetBSD/E500 + combination to the problem. */ + gdb_assert (ppc_floating_point_unit_p (gdbarch)); + + return ((regnum >= tdep->ppc_fp0_regnum + && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs) + || regnum == tdep->ppc_fpscr_regnum); +} + +void +ppc_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = regcache->arch (); + pid_t pid = regcache->ptid ().pid (); + int lwp = regcache->ptid ().lwp (); + + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) + perror_with_name (_("Couldn't get registers")); + + ppc_supply_gregset (&ppcnbsd_gregset, regcache, + regnum, ®s, sizeof regs); + } + + if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) + perror_with_name (_("Couldn't get FP registers")); + + ppc_supply_fpregset (&ppcnbsd_fpregset, regcache, + regnum, &fpregs, sizeof fpregs); + } +} + +void +ppc_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = regcache->arch (); + pid_t pid = regcache->ptid ().pid (); + int lwp = regcache->ptid ().lwp (); + + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) + perror_with_name (_("Couldn't get registers")); + + ppc_collect_gregset (&ppcnbsd_gregset, regcache, + regnum, ®s, sizeof regs); + + if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, lwp) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) + perror_with_name (_("Couldn't get FP registers")); + + ppc_collect_fpregset (&ppcnbsd_fpregset, regcache, + regnum, &fpregs, sizeof fpregs); + + if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, lwp) == -1) + perror_with_name (_("Couldn't set FP registers")); + } +} + +static int +ppcnbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + struct switchframe sf; + struct callframe cf; + struct gdbarch *gdbarch = regcache->arch (); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int i; + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_sp == 0) + return 0; + + read_memory (pcb->pcb_sp, (gdb_byte *)&sf, sizeof sf); + regcache->raw_supply (tdep->ppc_cr_regnum, &sf.cr); + regcache->raw_supply (tdep->ppc_gp0_regnum + 2, &sf.fixreg2); + for (i = 0 ; i < 19 ; i++) + regcache->raw_supply (tdep->ppc_gp0_regnum + 13 + i, &sf.fixreg[i]); + + read_memory(sf.sp, (gdb_byte *)&cf, sizeof(cf)); + regcache->raw_supply (tdep->ppc_gp0_regnum + 30, &cf.r30); + regcache->raw_supply (tdep->ppc_gp0_regnum + 31, &cf.r31); + regcache->raw_supply (tdep->ppc_gp0_regnum + 1, &cf.sp); + + read_memory(cf.sp, (gdb_byte *)&cf, sizeof(cf)); + regcache->raw_supply (tdep->ppc_lr_regnum, &cf.lr); + regcache->raw_supply (gdbarch_pc_regnum (gdbarch), &cf.lr); + + return 1; +} + +void _initialize_ppcnbsd_nat (); +void +_initialize_ppcnbsd_nat () +{ + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (ppcnbsd_supply_pcb); + + add_inf_child_target (&the_ppc_nbsd_nat_target); +} diff --git a/gdb/ppc-netbsd-tdep.c b/gdb/ppc-netbsd-tdep.c new file mode 100644 index 00000000000..64f2b402cad --- /dev/null +++ b/gdb/ppc-netbsd-tdep.c @@ -0,0 +1,223 @@ +/* Target-dependent code for NetBSD/powerpc. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "gdbtypes.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "trad-frame.h" +#include "tramp-frame.h" + +#include "ppc-tdep.h" +#include "netbsd-tdep.h" +#include "ppc-tdep.h" +#include "solib-svr4.h" + +/* Register offsets from . */ +struct ppc_reg_offsets ppcnbsd_reg_offsets; + + +/* Core file support. */ + +/* NetBSD/powerpc register sets. */ + +const struct regset ppcnbsd_gregset = +{ + &ppcnbsd_reg_offsets, + ppc_supply_gregset +}; + +const struct regset ppcnbsd_fpregset = +{ + &ppcnbsd_reg_offsets, + ppc_supply_fpregset +}; + +/* Iterate over core file register note sections. */ + +static void +ppcnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", 148, 148, &ppcnbsd_gregset, NULL, cb_data); + cb (".reg2", 264, 264, &ppcnbsd_fpregset, NULL, cb_data); +} + + +/* NetBSD is confused. It appears that 1.5 was using the correct SVR4 + convention but, 1.6 switched to the below broken convention. For + the moment use the broken convention. Ulgh! */ + +static enum return_value_convention +ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ +#if 0 + if ((valtype->code () == TYPE_CODE_STRUCT + || valtype->code () == TYPE_CODE_UNION) + && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8) + && valtype->is_vector ()) + && !(TYPE_LENGTH (valtype) == 1 + || TYPE_LENGTH (valtype) == 2 + || TYPE_LENGTH (valtype) == 4 + || TYPE_LENGTH (valtype) == 8)) + return RETURN_VALUE_STRUCT_CONVENTION; + else +#endif + return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, + regcache, readbuf, writebuf); +} + + +/* Signal trampolines. */ + +extern const struct tramp_frame ppcnbsd2_sigtramp; + +static void +ppcnbsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + CORE_ADDR addr, base; + int i; + + base = get_frame_register_unsigned (this_frame, + gdbarch_sp_regnum (gdbarch)); + if (self == &ppcnbsd2_sigtramp) + addr = base + 0x10 + 2 * tdep->wordsize; + else + addr = base + 0x18 + 2 * tdep->wordsize; + for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize) + { + int regnum = i + tdep->ppc_gp0_regnum; + trad_frame_set_reg_addr (this_cache, regnum, addr); + } + trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch), + addr); /* SRR0? */ + addr += tdep->wordsize; + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (this_cache, frame_id_build (base, func)); +} + +static const struct tramp_frame ppcnbsd_sigtramp = +{ + SIGTRAMP_FRAME, + 4, + { + { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */ + { 0x4e800021, ULONGEST_MAX }, /* blrl */ + { 0x38610018, ULONGEST_MAX }, /* addi r3,r1,24 */ + { 0x38000127, ULONGEST_MAX }, /* li r0,295 */ + { 0x44000002, ULONGEST_MAX }, /* sc */ + { 0x38000001, ULONGEST_MAX }, /* li r0,1 */ + { 0x44000002, ULONGEST_MAX }, /* sc */ + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + ppcnbsd_sigtramp_cache_init +}; + +/* NetBSD 2.0 introduced a slightly different signal trampoline. */ + +const struct tramp_frame ppcnbsd2_sigtramp = +{ + SIGTRAMP_FRAME, + 4, + { + { 0x3821fff0, ULONGEST_MAX }, /* add r1,r1,-16 */ + { 0x4e800021, ULONGEST_MAX }, /* blrl */ + { 0x38610010, ULONGEST_MAX }, /* addi r3,r1,16 */ + { 0x38000127, ULONGEST_MAX }, /* li r0,295 */ + { 0x44000002, ULONGEST_MAX }, /* sc */ + { 0x38000001, ULONGEST_MAX }, /* li r0,1 */ + { 0x44000002, ULONGEST_MAX }, /* sc */ + { TRAMP_SENTINEL_INSN, ULONGEST_MAX } + }, + ppcnbsd_sigtramp_cache_init +}; + + +static void +ppcnbsd_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + nbsd_init_abi (info, gdbarch); + + /* For NetBSD, this is an on again, off again thing. Some systems + do use the broken struct convention, and some don't. */ + set_gdbarch_return_value (gdbarch, ppcnbsd_return_value); + + /* NetBSD uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + set_gdbarch_iterate_over_regset_sections + (gdbarch, ppcnbsd_iterate_over_regset_sections); + + tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd_sigtramp); + tramp_frame_prepend_unwinder (gdbarch, &ppcnbsd2_sigtramp); +} + +void _initialize_ppcnbsd_tdep (); +void +_initialize_ppcnbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD, + ppcnbsd_init_abi); + + /* Avoid initializing the register offsets again if they were + already initialized by ppc-netbsd-nat.c. */ + if (ppcnbsd_reg_offsets.pc_offset == 0) + { + /* General-purpose registers. */ + ppcnbsd_reg_offsets.r0_offset = 0; + ppcnbsd_reg_offsets.gpr_size = 4; + ppcnbsd_reg_offsets.xr_size = 4; + ppcnbsd_reg_offsets.lr_offset = 128; + ppcnbsd_reg_offsets.cr_offset = 132; + ppcnbsd_reg_offsets.xer_offset = 136; + ppcnbsd_reg_offsets.ctr_offset = 140; + ppcnbsd_reg_offsets.pc_offset = 144; + ppcnbsd_reg_offsets.ps_offset = -1; + ppcnbsd_reg_offsets.mq_offset = -1; + + /* Floating-point registers. */ + ppcnbsd_reg_offsets.f0_offset = 0; + ppcnbsd_reg_offsets.fpscr_offset = 256; + ppcnbsd_reg_offsets.fpscr_size = 4; + + } +} diff --git a/gdb/ppc-netbsd-tdep.h b/gdb/ppc-netbsd-tdep.h new file mode 100644 index 00000000000..efbed9ea002 --- /dev/null +++ b/gdb/ppc-netbsd-tdep.h @@ -0,0 +1,32 @@ +/* Target-dependent code for NetBSD/powerpc. + + Copyright (C) 2004-2020 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 3 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, see . */ + +#ifndef PPC_NBSD_TDEP_H +#define PPC_NBSD_TDEP_H + +struct regset; + +/* Register offsets for NetBSD/powerpc. */ +extern struct ppc_reg_offsets ppcnbsd_reg_offsets; + +/* Register sets for NetBSD/powerpc. */ +extern const struct regset ppcnbsd_gregset; +extern const struct regset ppcnbsd_fpregset; + +#endif /* PPC_NBSD_TDEP_H */ diff --git a/gdb/sh-nbsd-nat.c b/gdb/sh-nbsd-nat.c deleted file mode 100644 index b4f9db691ce..00000000000 --- a/gdb/sh-nbsd-nat.c +++ /dev/null @@ -1,107 +0,0 @@ -/* Native-dependent code for NetBSD/sh. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "inferior.h" - -#include -#include -#include - -#include "sh-tdep.h" -#include "inf-ptrace.h" -#include "nbsd-nat.h" -#include "regcache.h" - -struct sh_nbsd_nat_target final : public nbsd_nat_target -{ - void fetch_registers (struct regcache *, int) override; - void store_registers (struct regcache *, int) override; -}; - -static sh_nbsd_nat_target the_sh_nbsd_nat_target; - -/* Determine if PT_GETREGS fetches this register. */ -#define GETREGS_SUPPLIES(gdbarch, regno) \ - (((regno) >= R0_REGNUM && (regno) <= (R0_REGNUM + 15)) \ -|| (regno) == gdbarch_pc_regnum (gdbarch) || (regno) == PR_REGNUM \ -|| (regno) == MACH_REGNUM || (regno) == MACL_REGNUM \ -|| (regno) == SR_REGNUM) - -/* Sizeof `struct reg' in . */ -#define SHNBSD_SIZEOF_GREGS (21 * 4) - -void -sh_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) -{ - pid_t pid = regcache->ptid ().pid (); - int lwp = regcache->ptid ().lwp (); - - if (regno == -1 || GETREGS_SUPPLIES (regcache->arch (), regno)) - { - struct reg inferior_registers; - - if (ptrace (PT_GETREGS, pid, - (PTRACE_TYPE_ARG3) &inferior_registers, lwp) == -1) - perror_with_name (_("Couldn't get registers")); - - sh_corefile_supply_regset (&sh_corefile_gregset, regcache, regno, - (char *) &inferior_registers, - SHNBSD_SIZEOF_GREGS); - - if (regno != -1) - return; - } -} - -void -sh_nbsd_nat_target::store_registers (struct regcache *regcache, int regno) -{ - pid_t pid = regcache->ptid ().pid (); - int lwp = regcache->ptid ().lwp (); - - if (regno == -1 || GETREGS_SUPPLIES (regcache->arch (), regno)) - { - struct reg inferior_registers; - - if (ptrace (PT_GETREGS, pid, - (PTRACE_TYPE_ARG3) &inferior_registers, lwp) == -1) - perror_with_name (_("Couldn't get registers")); - - sh_corefile_collect_regset (&sh_corefile_gregset, regcache, regno, - (char *) &inferior_registers, - SHNBSD_SIZEOF_GREGS); - - if (ptrace (PT_SETREGS, pid, - (PTRACE_TYPE_ARG3) &inferior_registers, lwp) == -1) - perror_with_name (_("Couldn't set registers")); - - if (regno != -1) - return; - } -} - -void _initialize_shnbsd_nat (); -void -_initialize_shnbsd_nat () -{ - add_inf_child_target (&the_sh_nbsd_nat_target); -} diff --git a/gdb/sh-nbsd-tdep.c b/gdb/sh-nbsd-tdep.c deleted file mode 100644 index 6551c47b5e1..00000000000 --- a/gdb/sh-nbsd-tdep.c +++ /dev/null @@ -1,84 +0,0 @@ -/* Target-dependent code for NetBSD/sh. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "gdbcore.h" -#include "regset.h" -#include "value.h" -#include "osabi.h" - -#include "sh-tdep.h" -#include "nbsd-tdep.h" -#include "solib-svr4.h" -#include "gdbarch.h" - -/* Convert a register number into an offset into a ptrace - register structure. */ -static const struct sh_corefile_regmap regmap[] = -{ - {R0_REGNUM, 20 * 4}, - {R0_REGNUM + 1, 19 * 4}, - {R0_REGNUM + 2, 18 * 4}, - {R0_REGNUM + 3, 17 * 4}, - {R0_REGNUM + 4, 16 * 4}, - {R0_REGNUM + 5, 15 * 4}, - {R0_REGNUM + 6, 14 * 4}, - {R0_REGNUM + 7, 13 * 4}, - {R0_REGNUM + 8, 12 * 4}, - {R0_REGNUM + 9, 11 * 4}, - {R0_REGNUM + 10, 10 * 4}, - {R0_REGNUM + 11, 9 * 4}, - {R0_REGNUM + 12, 8 * 4}, - {R0_REGNUM + 13, 7 * 4}, - {R0_REGNUM + 14, 6 * 4}, - {R0_REGNUM + 15, 5 * 4}, - {PC_REGNUM, 0 * 4}, - {SR_REGNUM, 1 * 4}, - {PR_REGNUM, 2 * 4}, - {MACH_REGNUM, 3 * 4}, - {MACL_REGNUM, 4 * 4}, - {-1 /* Terminator. */, 0} -}; - - -static void -shnbsd_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - nbsd_init_abi (info, gdbarch); - - tdep->core_gregmap = (struct sh_corefile_regmap *)regmap; - tdep->sizeof_gregset = 84; - - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - -void _initialize_shnbsd_tdep (); -void -_initialize_shnbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD, - shnbsd_init_abi); - gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_OPENBSD, - shnbsd_init_abi); -} diff --git a/gdb/sh-netbsd-nat.c b/gdb/sh-netbsd-nat.c new file mode 100644 index 00000000000..fcdc4efb795 --- /dev/null +++ b/gdb/sh-netbsd-nat.c @@ -0,0 +1,107 @@ +/* Native-dependent code for NetBSD/sh. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "inferior.h" + +#include +#include +#include + +#include "sh-tdep.h" +#include "inf-ptrace.h" +#include "netbsd-nat.h" +#include "regcache.h" + +struct sh_nbsd_nat_target final : public nbsd_nat_target +{ + void fetch_registers (struct regcache *, int) override; + void store_registers (struct regcache *, int) override; +}; + +static sh_nbsd_nat_target the_sh_nbsd_nat_target; + +/* Determine if PT_GETREGS fetches this register. */ +#define GETREGS_SUPPLIES(gdbarch, regno) \ + (((regno) >= R0_REGNUM && (regno) <= (R0_REGNUM + 15)) \ +|| (regno) == gdbarch_pc_regnum (gdbarch) || (regno) == PR_REGNUM \ +|| (regno) == MACH_REGNUM || (regno) == MACL_REGNUM \ +|| (regno) == SR_REGNUM) + +/* Sizeof `struct reg' in . */ +#define SHNBSD_SIZEOF_GREGS (21 * 4) + +void +sh_nbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) +{ + pid_t pid = regcache->ptid ().pid (); + int lwp = regcache->ptid ().lwp (); + + if (regno == -1 || GETREGS_SUPPLIES (regcache->arch (), regno)) + { + struct reg inferior_registers; + + if (ptrace (PT_GETREGS, pid, + (PTRACE_TYPE_ARG3) &inferior_registers, lwp) == -1) + perror_with_name (_("Couldn't get registers")); + + sh_corefile_supply_regset (&sh_corefile_gregset, regcache, regno, + (char *) &inferior_registers, + SHNBSD_SIZEOF_GREGS); + + if (regno != -1) + return; + } +} + +void +sh_nbsd_nat_target::store_registers (struct regcache *regcache, int regno) +{ + pid_t pid = regcache->ptid ().pid (); + int lwp = regcache->ptid ().lwp (); + + if (regno == -1 || GETREGS_SUPPLIES (regcache->arch (), regno)) + { + struct reg inferior_registers; + + if (ptrace (PT_GETREGS, pid, + (PTRACE_TYPE_ARG3) &inferior_registers, lwp) == -1) + perror_with_name (_("Couldn't get registers")); + + sh_corefile_collect_regset (&sh_corefile_gregset, regcache, regno, + (char *) &inferior_registers, + SHNBSD_SIZEOF_GREGS); + + if (ptrace (PT_SETREGS, pid, + (PTRACE_TYPE_ARG3) &inferior_registers, lwp) == -1) + perror_with_name (_("Couldn't set registers")); + + if (regno != -1) + return; + } +} + +void _initialize_shnbsd_nat (); +void +_initialize_shnbsd_nat () +{ + add_inf_child_target (&the_sh_nbsd_nat_target); +} diff --git a/gdb/sh-netbsd-tdep.c b/gdb/sh-netbsd-tdep.c new file mode 100644 index 00000000000..eabec984ced --- /dev/null +++ b/gdb/sh-netbsd-tdep.c @@ -0,0 +1,84 @@ +/* Target-dependent code for NetBSD/sh. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "gdbcore.h" +#include "regset.h" +#include "value.h" +#include "osabi.h" + +#include "sh-tdep.h" +#include "netbsd-tdep.h" +#include "solib-svr4.h" +#include "gdbarch.h" + +/* Convert a register number into an offset into a ptrace + register structure. */ +static const struct sh_corefile_regmap regmap[] = +{ + {R0_REGNUM, 20 * 4}, + {R0_REGNUM + 1, 19 * 4}, + {R0_REGNUM + 2, 18 * 4}, + {R0_REGNUM + 3, 17 * 4}, + {R0_REGNUM + 4, 16 * 4}, + {R0_REGNUM + 5, 15 * 4}, + {R0_REGNUM + 6, 14 * 4}, + {R0_REGNUM + 7, 13 * 4}, + {R0_REGNUM + 8, 12 * 4}, + {R0_REGNUM + 9, 11 * 4}, + {R0_REGNUM + 10, 10 * 4}, + {R0_REGNUM + 11, 9 * 4}, + {R0_REGNUM + 12, 8 * 4}, + {R0_REGNUM + 13, 7 * 4}, + {R0_REGNUM + 14, 6 * 4}, + {R0_REGNUM + 15, 5 * 4}, + {PC_REGNUM, 0 * 4}, + {SR_REGNUM, 1 * 4}, + {PR_REGNUM, 2 * 4}, + {MACH_REGNUM, 3 * 4}, + {MACL_REGNUM, 4 * 4}, + {-1 /* Terminator. */, 0} +}; + + +static void +shnbsd_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + nbsd_init_abi (info, gdbarch); + + tdep->core_gregmap = (struct sh_corefile_regmap *)regmap; + tdep->sizeof_gregset = 84; + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +void _initialize_shnbsd_tdep (); +void +_initialize_shnbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD, + shnbsd_init_abi); + gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_OPENBSD, + shnbsd_init_abi); +} diff --git a/gdb/sparc-nbsd-nat.c b/gdb/sparc-nbsd-nat.c deleted file mode 100644 index 7138d7df737..00000000000 --- a/gdb/sparc-nbsd-nat.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Native-dependent code for NetBSD/sparc. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "regcache.h" -#include "target.h" - -#include "sparc-tdep.h" -#include "sparc-nat.h" - -/* Support for debugging kernel virtual memory images. */ - -#include -#include - -#include "bsd-kvm.h" - -static int -sparc32nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - /* The following is true for NetBSD 1.6.2: - - The pcb contains %sp, %pc, %psr and %wim. From this information - we reconstruct the register state as it would look when we just - returned from cpu_switch(). */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_sp == 0) - return 0; - - regcache->raw_supply (SPARC_SP_REGNUM, &pcb->pcb_sp); - regcache->raw_supply (SPARC_O7_REGNUM, &pcb->pcb_pc); - regcache->raw_supply (SPARC32_PSR_REGNUM, &pcb->pcb_psr); - regcache->raw_supply (SPARC32_WIM_REGNUM, &pcb->pcb_wim); - regcache->raw_supply (SPARC32_PC_REGNUM, &pcb->pcb_pc); - - sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); - - return 1; -} - -static sparc_target the_sparc_nbsd_nat_target; - -void _initialize_sparcnbsd_nat (); -void -_initialize_sparcnbsd_nat () -{ - sparc_gregmap = &sparc32nbsd_gregmap; - sparc_fpregmap = &sparc32_bsd_fpregmap; - - add_inf_child_target (&sparc_nbsd_nat_target); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (sparc32nbsd_supply_pcb); -} diff --git a/gdb/sparc-nbsd-tdep.c b/gdb/sparc-nbsd-tdep.c deleted file mode 100644 index ab1b557c57c..00000000000 --- a/gdb/sparc-nbsd-tdep.c +++ /dev/null @@ -1,326 +0,0 @@ -/* Target-dependent code for NetBSD/sparc. - - Copyright (C) 2002-2020 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 3 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, see . */ - -#include "defs.h" -#include "frame.h" -#include "frame-unwind.h" -#include "gdbcore.h" -#include "gdbtypes.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "solib-svr4.h" -#include "symtab.h" -#include "trad-frame.h" -#include "gdbarch.h" - -#include "sparc-tdep.h" -#include "nbsd-tdep.h" - -/* Macros to extract fields from SPARC instructions. */ -#define X_RS1(i) (((i) >> 14) & 0x1f) -#define X_RS2(i) ((i) & 0x1f) -#define X_I(i) (((i) >> 13) & 1) - -const struct sparc_gregmap sparc32nbsd_gregmap = -{ - 0 * 4, /* %psr */ - 1 * 4, /* %pc */ - 2 * 4, /* %npc */ - 3 * 4, /* %y */ - -1, /* %wim */ - -1, /* %tbr */ - 5 * 4, /* %g1 */ - -1 /* %l0 */ -}; - -static void -sparc32nbsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - sparc32_supply_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs); - - /* Traditional NetBSD core files don't use multiple register sets. - Instead, the general-purpose and floating-point registers are - lumped together in a single section. */ - if (len >= 212) - sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, - (const char *) gregs + 80); -} - -static void -sparc32nbsd_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *fpregs, size_t len) -{ - sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs); -} - - -/* Signal trampolines. */ - -/* The following variables describe the location of an on-stack signal - trampoline. The current values correspond to the memory layout for - NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and - up, since NetBSD uses signal trampolines provided by libc now. */ - -static const CORE_ADDR sparc32nbsd_sigtramp_start = 0xeffffef0; -static const CORE_ADDR sparc32nbsd_sigtramp_end = 0xeffffff0; - -static int -sparc32nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) -{ - if (pc >= sparc32nbsd_sigtramp_start && pc < sparc32nbsd_sigtramp_end) - return 1; - - return nbsd_pc_in_sigtramp (pc, name); -} - -struct trad_frame_saved_reg * -sparc32nbsd_sigcontext_saved_regs (struct frame_info *this_frame) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct trad_frame_saved_reg *saved_regs; - CORE_ADDR addr, sigcontext_addr; - int regnum, delta; - ULONGEST psr; - - saved_regs = trad_frame_alloc_saved_regs (this_frame); - - /* We find the appropriate instance of `struct sigcontext' at a - fixed offset in the signal frame. */ - addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); - sigcontext_addr = addr + 64 + 16; - - /* The registers are saved in bits and pieces scattered all over the - place. The code below records their location on the assumption - that the part of the signal trampoline that saves the state has - been executed. */ - - saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; - saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 12; - saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 16; - saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 20; - saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 24; - saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 28; - - /* The remaining `global' registers and %y are saved in the `local' - registers. */ - delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; - for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) - saved_regs[regnum].realreg = regnum + delta; - saved_regs[SPARC32_Y_REGNUM].realreg = SPARC_L1_REGNUM; - - /* The remaining `out' registers can be found in the current frame's - `in' registers. */ - delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; - for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) - saved_regs[regnum].realreg = regnum + delta; - saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; - - /* The `local' and `in' registers have been saved in the register - save area. */ - addr = saved_regs[SPARC_SP_REGNUM].addr; - addr = get_frame_memory_unsigned (this_frame, addr, 4); - for (regnum = SPARC_L0_REGNUM; - regnum <= SPARC_I7_REGNUM; regnum++, addr += 4) - saved_regs[regnum].addr = addr; - - /* Handle StackGhost. */ - { - ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); - - if (wcookie != 0) - { - ULONGEST i7; - - addr = saved_regs[SPARC_I7_REGNUM].addr; - i7 = get_frame_memory_unsigned (this_frame, addr, 4); - trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie); - } - } - - /* The floating-point registers are only saved if the EF bit in %prs - has been set. */ - -#define PSR_EF 0x00001000 - - addr = saved_regs[SPARC32_PSR_REGNUM].addr; - psr = get_frame_memory_unsigned (this_frame, addr, 4); - if (psr & PSR_EF) - { - CORE_ADDR sp; - - sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM); - saved_regs[SPARC32_FSR_REGNUM].addr = sp + 96; - for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8; - regnum <= SPARC_F31_REGNUM; regnum++, addr += 4) - saved_regs[regnum].addr = addr; - } - - return saved_regs; -} - -static struct sparc_frame_cache * -sparc32nbsd_sigcontext_frame_cache (struct frame_info *this_frame, - void **this_cache) -{ - struct sparc_frame_cache *cache; - CORE_ADDR addr; - - if (*this_cache) - return (struct sparc_frame_cache *) *this_cache; - - cache = sparc_frame_cache (this_frame, this_cache); - gdb_assert (cache == *this_cache); - - /* If we couldn't find the frame's function, we're probably dealing - with an on-stack signal trampoline. */ - if (cache->pc == 0) - { - cache->pc = sparc32nbsd_sigtramp_start; - - /* Since we couldn't find the frame's function, the cache was - initialized under the assumption that we're frameless. */ - sparc_record_save_insn (cache); - addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); - cache->base = addr; - } - - cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame); - - return cache; -} - -static void -sparc32nbsd_sigcontext_frame_this_id (struct frame_info *this_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct sparc_frame_cache *cache = - sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache); - - (*this_id) = frame_id_build (cache->base, cache->pc); -} - -static struct value * -sparc32nbsd_sigcontext_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct sparc_frame_cache *cache = - sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache); - - return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); -} - -static int -sparc32nbsd_sigcontext_frame_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_cache) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - const char *name; - - find_pc_partial_function (pc, &name, NULL, NULL); - if (sparc32nbsd_pc_in_sigtramp (pc, name)) - { - if (name == NULL || !startswith (name, "__sigtramp_sigcontext")) - return 1; - } - - return 0; -} - -static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind = -{ - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - sparc32nbsd_sigcontext_frame_this_id, - sparc32nbsd_sigcontext_frame_prev_register, - NULL, - sparc32nbsd_sigcontext_frame_sniffer -}; - -/* Return the address of a system call's alternative return - address. */ - -CORE_ADDR -sparcnbsd_step_trap (struct frame_info *frame, unsigned long insn) -{ - if ((X_I (insn) == 0 && X_RS1 (insn) == 0 && X_RS2 (insn) == 0) - || (X_I (insn) == 1 && X_RS1 (insn) == 0 && (insn & 0x7f) == 0)) - { - /* "New" system call. */ - ULONGEST number = get_frame_register_unsigned (frame, SPARC_G1_REGNUM); - - if (number & 0x400) - return get_frame_register_unsigned (frame, SPARC_G2_REGNUM); - if (number & 0x800) - return get_frame_register_unsigned (frame, SPARC_G7_REGNUM); - } - - return 0; -} - - -static const struct regset sparc32nbsd_gregset = - { - NULL, sparc32nbsd_supply_gregset, NULL - }; - -static const struct regset sparc32nbsd_fpregset = - { - NULL, sparc32nbsd_supply_fpregset, NULL - }; - -void -sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - nbsd_init_abi (info, gdbarch); - - /* NetBSD doesn't support the 128-bit `long double' from the psABI. */ - set_gdbarch_long_double_bit (gdbarch, 64); - set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); - - tdep->gregset = &sparc32nbsd_gregset; - tdep->sizeof_gregset = 20 * 4; - - tdep->fpregset = &sparc32nbsd_fpregset; - tdep->sizeof_fpregset = 33 * 4; - - /* Make sure we can single-step "new" syscalls. */ - tdep->step_trap = sparcnbsd_step_trap; - - frame_unwind_append_unwinder (gdbarch, &sparc32nbsd_sigcontext_frame_unwind); - - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - -void _initialize_sparcnbsd_tdep (); -void -_initialize_sparcnbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD, - sparc32nbsd_init_abi); -} diff --git a/gdb/sparc-netbsd-nat.c b/gdb/sparc-netbsd-nat.c new file mode 100644 index 00000000000..7138d7df737 --- /dev/null +++ b/gdb/sparc-netbsd-nat.c @@ -0,0 +1,71 @@ +/* Native-dependent code for NetBSD/sparc. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "regcache.h" +#include "target.h" + +#include "sparc-tdep.h" +#include "sparc-nat.h" + +/* Support for debugging kernel virtual memory images. */ + +#include +#include + +#include "bsd-kvm.h" + +static int +sparc32nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + /* The following is true for NetBSD 1.6.2: + + The pcb contains %sp, %pc, %psr and %wim. From this information + we reconstruct the register state as it would look when we just + returned from cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_sp == 0) + return 0; + + regcache->raw_supply (SPARC_SP_REGNUM, &pcb->pcb_sp); + regcache->raw_supply (SPARC_O7_REGNUM, &pcb->pcb_pc); + regcache->raw_supply (SPARC32_PSR_REGNUM, &pcb->pcb_psr); + regcache->raw_supply (SPARC32_WIM_REGNUM, &pcb->pcb_wim); + regcache->raw_supply (SPARC32_PC_REGNUM, &pcb->pcb_pc); + + sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); + + return 1; +} + +static sparc_target the_sparc_nbsd_nat_target; + +void _initialize_sparcnbsd_nat (); +void +_initialize_sparcnbsd_nat () +{ + sparc_gregmap = &sparc32nbsd_gregmap; + sparc_fpregmap = &sparc32_bsd_fpregmap; + + add_inf_child_target (&sparc_nbsd_nat_target); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (sparc32nbsd_supply_pcb); +} diff --git a/gdb/sparc-netbsd-tdep.c b/gdb/sparc-netbsd-tdep.c new file mode 100644 index 00000000000..7cb412621dc --- /dev/null +++ b/gdb/sparc-netbsd-tdep.c @@ -0,0 +1,326 @@ +/* Target-dependent code for NetBSD/sparc. + + Copyright (C) 2002-2020 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 3 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, see . */ + +#include "defs.h" +#include "frame.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "gdbtypes.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "solib-svr4.h" +#include "symtab.h" +#include "trad-frame.h" +#include "gdbarch.h" + +#include "sparc-tdep.h" +#include "netbsd-tdep.h" + +/* Macros to extract fields from SPARC instructions. */ +#define X_RS1(i) (((i) >> 14) & 0x1f) +#define X_RS2(i) ((i) & 0x1f) +#define X_I(i) (((i) >> 13) & 1) + +const struct sparc_gregmap sparc32nbsd_gregmap = +{ + 0 * 4, /* %psr */ + 1 * 4, /* %pc */ + 2 * 4, /* %npc */ + 3 * 4, /* %y */ + -1, /* %wim */ + -1, /* %tbr */ + 5 * 4, /* %g1 */ + -1 /* %l0 */ +}; + +static void +sparc32nbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + sparc32_supply_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs); + + /* Traditional NetBSD core files don't use multiple register sets. + Instead, the general-purpose and floating-point registers are + lumped together in a single section. */ + if (len >= 212) + sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, + (const char *) gregs + 80); +} + +static void +sparc32nbsd_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs); +} + + +/* Signal trampolines. */ + +/* The following variables describe the location of an on-stack signal + trampoline. The current values correspond to the memory layout for + NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and + up, since NetBSD uses signal trampolines provided by libc now. */ + +static const CORE_ADDR sparc32nbsd_sigtramp_start = 0xeffffef0; +static const CORE_ADDR sparc32nbsd_sigtramp_end = 0xeffffff0; + +static int +sparc32nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) +{ + if (pc >= sparc32nbsd_sigtramp_start && pc < sparc32nbsd_sigtramp_end) + return 1; + + return nbsd_pc_in_sigtramp (pc, name); +} + +struct trad_frame_saved_reg * +sparc32nbsd_sigcontext_saved_regs (struct frame_info *this_frame) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct trad_frame_saved_reg *saved_regs; + CORE_ADDR addr, sigcontext_addr; + int regnum, delta; + ULONGEST psr; + + saved_regs = trad_frame_alloc_saved_regs (this_frame); + + /* We find the appropriate instance of `struct sigcontext' at a + fixed offset in the signal frame. */ + addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); + sigcontext_addr = addr + 64 + 16; + + /* The registers are saved in bits and pieces scattered all over the + place. The code below records their location on the assumption + that the part of the signal trampoline that saves the state has + been executed. */ + + saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; + saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 12; + saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 16; + saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 20; + saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 24; + saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 28; + + /* The remaining `global' registers and %y are saved in the `local' + registers. */ + delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; + for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) + saved_regs[regnum].realreg = regnum + delta; + saved_regs[SPARC32_Y_REGNUM].realreg = SPARC_L1_REGNUM; + + /* The remaining `out' registers can be found in the current frame's + `in' registers. */ + delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; + for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) + saved_regs[regnum].realreg = regnum + delta; + saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; + + /* The `local' and `in' registers have been saved in the register + save area. */ + addr = saved_regs[SPARC_SP_REGNUM].addr; + addr = get_frame_memory_unsigned (this_frame, addr, 4); + for (regnum = SPARC_L0_REGNUM; + regnum <= SPARC_I7_REGNUM; regnum++, addr += 4) + saved_regs[regnum].addr = addr; + + /* Handle StackGhost. */ + { + ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); + + if (wcookie != 0) + { + ULONGEST i7; + + addr = saved_regs[SPARC_I7_REGNUM].addr; + i7 = get_frame_memory_unsigned (this_frame, addr, 4); + trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie); + } + } + + /* The floating-point registers are only saved if the EF bit in %prs + has been set. */ + +#define PSR_EF 0x00001000 + + addr = saved_regs[SPARC32_PSR_REGNUM].addr; + psr = get_frame_memory_unsigned (this_frame, addr, 4); + if (psr & PSR_EF) + { + CORE_ADDR sp; + + sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM); + saved_regs[SPARC32_FSR_REGNUM].addr = sp + 96; + for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8; + regnum <= SPARC_F31_REGNUM; regnum++, addr += 4) + saved_regs[regnum].addr = addr; + } + + return saved_regs; +} + +static struct sparc_frame_cache * +sparc32nbsd_sigcontext_frame_cache (struct frame_info *this_frame, + void **this_cache) +{ + struct sparc_frame_cache *cache; + CORE_ADDR addr; + + if (*this_cache) + return (struct sparc_frame_cache *) *this_cache; + + cache = sparc_frame_cache (this_frame, this_cache); + gdb_assert (cache == *this_cache); + + /* If we couldn't find the frame's function, we're probably dealing + with an on-stack signal trampoline. */ + if (cache->pc == 0) + { + cache->pc = sparc32nbsd_sigtramp_start; + + /* Since we couldn't find the frame's function, the cache was + initialized under the assumption that we're frameless. */ + sparc_record_save_insn (cache); + addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); + cache->base = addr; + } + + cache->saved_regs = sparc32nbsd_sigcontext_saved_regs (this_frame); + + return cache; +} + +static void +sparc32nbsd_sigcontext_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct sparc_frame_cache *cache = + sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static struct value * +sparc32nbsd_sigcontext_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct sparc_frame_cache *cache = + sparc32nbsd_sigcontext_frame_cache (this_frame, this_cache); + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); +} + +static int +sparc32nbsd_sigcontext_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + const char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (sparc32nbsd_pc_in_sigtramp (pc, name)) + { + if (name == NULL || !startswith (name, "__sigtramp_sigcontext")) + return 1; + } + + return 0; +} + +static const struct frame_unwind sparc32nbsd_sigcontext_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + sparc32nbsd_sigcontext_frame_this_id, + sparc32nbsd_sigcontext_frame_prev_register, + NULL, + sparc32nbsd_sigcontext_frame_sniffer +}; + +/* Return the address of a system call's alternative return + address. */ + +CORE_ADDR +sparcnbsd_step_trap (struct frame_info *frame, unsigned long insn) +{ + if ((X_I (insn) == 0 && X_RS1 (insn) == 0 && X_RS2 (insn) == 0) + || (X_I (insn) == 1 && X_RS1 (insn) == 0 && (insn & 0x7f) == 0)) + { + /* "New" system call. */ + ULONGEST number = get_frame_register_unsigned (frame, SPARC_G1_REGNUM); + + if (number & 0x400) + return get_frame_register_unsigned (frame, SPARC_G2_REGNUM); + if (number & 0x800) + return get_frame_register_unsigned (frame, SPARC_G7_REGNUM); + } + + return 0; +} + + +static const struct regset sparc32nbsd_gregset = + { + NULL, sparc32nbsd_supply_gregset, NULL + }; + +static const struct regset sparc32nbsd_fpregset = + { + NULL, sparc32nbsd_supply_fpregset, NULL + }; + +void +sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + nbsd_init_abi (info, gdbarch); + + /* NetBSD doesn't support the 128-bit `long double' from the psABI. */ + set_gdbarch_long_double_bit (gdbarch, 64); + set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); + + tdep->gregset = &sparc32nbsd_gregset; + tdep->sizeof_gregset = 20 * 4; + + tdep->fpregset = &sparc32nbsd_fpregset; + tdep->sizeof_fpregset = 33 * 4; + + /* Make sure we can single-step "new" syscalls. */ + tdep->step_trap = sparcnbsd_step_trap; + + frame_unwind_append_unwinder (gdbarch, &sparc32nbsd_sigcontext_frame_unwind); + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +void _initialize_sparcnbsd_tdep (); +void +_initialize_sparcnbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD, + sparc32nbsd_init_abi); +} diff --git a/gdb/sparc64-nbsd-nat.c b/gdb/sparc64-nbsd-nat.c deleted file mode 100644 index 5e249b629d1..00000000000 --- a/gdb/sparc64-nbsd-nat.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Native-dependent code for NetBSD/sparc64. - - Copyright (C) 2003-2020 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 3 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, see . */ - -#include "defs.h" -#include "gdbcore.h" -#include "regcache.h" -#include "target.h" - -#include "sparc64-tdep.h" -#include "sparc-nat.h" - -/* NetBSD is different from the other OSes that support both SPARC and - UltraSPARC in that the result of ptrace(2) depends on whether the - traced process is 32-bit or 64-bit. */ - -static void -sparc64nbsd_supply_gregset (const struct sparc_gregmap *gregmap, - struct regcache *regcache, - int regnum, const void *gregs) -{ - int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); - - if (sparc32) - sparc32_supply_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs); - else - sparc64_supply_gregset (&sparc64nbsd_gregmap, regcache, regnum, gregs); -} - -static void -sparc64nbsd_collect_gregset (const struct sparc_gregmap *gregmap, - const struct regcache *regcache, - int regnum, void *gregs) -{ - int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); - - if (sparc32) - sparc32_collect_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs); - else - sparc64_collect_gregset (&sparc64nbsd_gregmap, regcache, regnum, gregs); -} - -static void -sparc64nbsd_supply_fpregset (const struct sparc_fpregmap *fpregmap, - struct regcache *regcache, - int regnum, const void *fpregs) -{ - int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); - - if (sparc32) - sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs); - else - sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); -} - -static void -sparc64nbsd_collect_fpregset (const struct sparc_fpregmap *fpregmap, - const struct regcache *regcache, - int regnum, void *fpregs) -{ - int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); - - if (sparc32) - sparc32_collect_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs); - else - sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); -} - -/* Determine whether `gregset_t' contains register REGNUM. */ - -static int -sparc64nbsd_gregset_supplies_p (struct gdbarch *gdbarch, int regnum) -{ - if (gdbarch_ptr_bit (gdbarch) == 32) - return sparc32_gregset_supplies_p (gdbarch, regnum); - - /* Integer registers. */ - if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM) - || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM) - || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM) - || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM)) - return 1; - - /* Control registers. */ - if (regnum == SPARC64_PC_REGNUM - || regnum == SPARC64_NPC_REGNUM - || regnum == SPARC64_STATE_REGNUM - || regnum == SPARC64_Y_REGNUM) - return 1; - - return 0; -} - -/* Determine whether `fpregset_t' contains register REGNUM. */ - -static int -sparc64nbsd_fpregset_supplies_p (struct gdbarch *gdbarch, int regnum) -{ - if (gdbarch_ptr_bit (gdbarch) == 32) - return sparc32_fpregset_supplies_p (gdbarch, regnum); - - /* Floating-point registers. */ - if ((regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM) - || (regnum >= SPARC64_F32_REGNUM && regnum <= SPARC64_F62_REGNUM)) - return 1; - - /* Control registers. */ - if (regnum == SPARC64_FSR_REGNUM) - return 1; - - return 0; -} - - -/* Support for debugging kernel virtual memory images. */ - -#include -#include - -#include "bsd-kvm.h" - -static int -sparc64nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - u_int64_t state; - int regnum; - - /* The following is true for NetBSD 1.6.2: - - The pcb contains %sp and %pc, %pstate and %cwp. From this - information we reconstruct the register state as it would look - when we just returned from cpu_switch(). */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_sp == 0) - return 0; - - /* If the program counter is zero, this is probably a core dump, and - we can get %pc from the stack. */ - if (pcb->pcb_pc == 0) - read_memory(pcb->pcb_sp + BIAS - 176 + (11 * 8), - (gdb_byte *)&pcb->pcb_pc, sizeof pcb->pcb_pc); - - regcache->raw_supply (SPARC_SP_REGNUM, &pcb->pcb_sp); - regcache->raw_supply (SPARC64_PC_REGNUM, &pcb->pcb_pc); - - state = pcb->pcb_pstate << 8 | pcb->pcb_cwp; - regcache->raw_supply (SPARC64_STATE_REGNUM, &state); - - sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); - - return 1; -} - -/* We've got nothing to add to the generic SPARC target. */ -static sparc_target the_sparc64_nbsd_nat_target; - -void _initialize_sparc64nbsd_nat (); -void -_initialize_sparc64nbsd_nat () -{ - sparc_supply_gregset = sparc64nbsd_supply_gregset; - sparc_collect_gregset = sparc64nbsd_collect_gregset; - sparc_supply_fpregset = sparc64nbsd_supply_fpregset; - sparc_collect_fpregset = sparc64nbsd_collect_fpregset; - sparc_gregset_supplies_p = sparc64nbsd_gregset_supplies_p; - sparc_fpregset_supplies_p = sparc64nbsd_fpregset_supplies_p; - - add_inf_child_target (&the_sparc64_nbsd_nat_target); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (sparc64nbsd_supply_pcb); -} diff --git a/gdb/sparc64-nbsd-tdep.c b/gdb/sparc64-nbsd-tdep.c deleted file mode 100644 index dac7fa78b9b..00000000000 --- a/gdb/sparc64-nbsd-tdep.c +++ /dev/null @@ -1,279 +0,0 @@ -/* Target-dependent code for NetBSD/sparc64. - - Copyright (C) 2002-2020 Free Software Foundation, Inc. - Based on code 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 3 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, see . */ - -#include "defs.h" -#include "frame.h" -#include "frame-unwind.h" -#include "gdbcore.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "symtab.h" -#include "objfiles.h" -#include "solib-svr4.h" -#include "trad-frame.h" - -#include "sparc64-tdep.h" -#include "nbsd-tdep.h" - -/* From . */ -const struct sparc_gregmap sparc64nbsd_gregmap = -{ - 0 * 8, /* "tstate" */ - 1 * 8, /* %pc */ - 2 * 8, /* %npc */ - 3 * 8, /* %y */ - -1, /* %fprs */ - -1, - 5 * 8, /* %g1 */ - -1, /* %l0 */ - 4 /* sizeof (%y) */ -}; - - -static void -sparc64nbsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - sparc64_supply_gregset (&sparc64nbsd_gregmap, regcache, regnum, gregs); -} - -static void -sparc64nbsd_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *fpregs, size_t len) -{ - sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); -} - - -/* Signal trampolines. */ - -/* The following variables describe the location of an on-stack signal - trampoline. The current values correspond to the memory layout for - NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and - up, since NetBSD uses signal trampolines provided by libc now. */ - -static const CORE_ADDR sparc64nbsd_sigtramp_start = 0xffffffffffffdee4ULL; -static const CORE_ADDR sparc64nbsd_sigtramp_end = 0xffffffffffffe000ULL; - -static int -sparc64nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) -{ - if (pc >= sparc64nbsd_sigtramp_start && pc < sparc64nbsd_sigtramp_end) - return 1; - - return nbsd_pc_in_sigtramp (pc, name); -} - -struct trad_frame_saved_reg * -sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr, - struct frame_info *this_frame) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct trad_frame_saved_reg *saved_regs; - CORE_ADDR addr, sp; - int regnum, delta; - - saved_regs = trad_frame_alloc_saved_regs (this_frame); - - /* The registers are saved in bits and pieces scattered all over the - place. The code below records their location on the assumption - that the part of the signal trampoline that saves the state has - been executed. */ - - saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; - saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16; - saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24; - saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32; - saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40; - saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48; - - /* The remaining `global' registers and %y are saved in the `local' - registers. */ - delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; - for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) - saved_regs[regnum].realreg = regnum + delta; - saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM; - - /* The remaining `out' registers can be found in the current frame's - `in' registers. */ - delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; - for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) - saved_regs[regnum].realreg = regnum + delta; - saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; - - /* The `local' and `in' registers have been saved in the register - save area. */ - addr = saved_regs[SPARC_SP_REGNUM].addr; - sp = get_frame_memory_unsigned (this_frame, addr, 8); - for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; - regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) - saved_regs[regnum].addr = addr; - - /* Handle StackGhost. */ - { - ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); - - if (wcookie != 0) - { - ULONGEST i7; - - addr = saved_regs[SPARC_I7_REGNUM].addr; - i7 = get_frame_memory_unsigned (this_frame, addr, 8); - trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie); - } - } - - /* TODO: Handle the floating-point registers. */ - - return saved_regs; -} - -static struct sparc_frame_cache * -sparc64nbsd_sigcontext_frame_cache (struct frame_info *this_frame, - void **this_cache) -{ - struct sparc_frame_cache *cache; - CORE_ADDR addr; - - if (*this_cache) - return (struct sparc_frame_cache *) *this_cache; - - cache = sparc_frame_cache (this_frame, this_cache); - gdb_assert (cache == *this_cache); - - /* If we couldn't find the frame's function, we're probably dealing - with an on-stack signal trampoline. */ - if (cache->pc == 0) - { - cache->pc = sparc64nbsd_sigtramp_start; - - /* Since we couldn't find the frame's function, the cache was - initialized under the assumption that we're frameless. */ - sparc_record_save_insn (cache); - addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); - if (addr & 1) - addr += BIAS; - cache->base = addr; - } - - /* We find the appropriate instance of `struct sigcontext' at a - fixed offset in the signal frame. */ - addr = cache->base + 128 + 8; - cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame); - - return cache; -} - -static void -sparc64nbsd_sigcontext_frame_this_id (struct frame_info *this_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct sparc_frame_cache *cache = - sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache); - - (*this_id) = frame_id_build (cache->base, cache->pc); -} - -static struct value * -sparc64nbsd_sigcontext_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct sparc_frame_cache *cache = - sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache); - - return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); -} - -static int -sparc64nbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_cache) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - const char *name; - - find_pc_partial_function (pc, &name, NULL, NULL); - if (sparc64nbsd_pc_in_sigtramp (pc, name)) - { - if (name == NULL || !startswith (name, "__sigtramp_sigcontext")) - return 1; - } - - return 0; -} - -static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind = -{ - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - sparc64nbsd_sigcontext_frame_this_id, - sparc64nbsd_sigcontext_frame_prev_register, - NULL, - sparc64nbsd_sigtramp_frame_sniffer -}; - - -static const struct regset sparc64nbsd_gregset = - { - NULL, sparc64nbsd_supply_gregset, NULL - }; - -static const struct regset sparc64nbsd_fpregset = - { - NULL, sparc64nbsd_supply_fpregset, NULL - }; - -static void -sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - nbsd_init_abi (info, gdbarch); - - tdep->gregset = &sparc64nbsd_gregset; - tdep->sizeof_gregset = 160; - - tdep->fpregset = &sparc64nbsd_fpregset; - tdep->sizeof_fpregset = 272; - - /* Make sure we can single-step "new" syscalls. */ - tdep->step_trap = sparcnbsd_step_trap; - - frame_unwind_append_unwinder (gdbarch, &sparc64nbsd_sigcontext_frame_unwind); - - sparc64_init_abi (info, gdbarch); - - /* NetBSD/sparc64 has SVR4-style shared libraries. */ - set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); -} - -void _initialize_sparc64nbsd_tdep (); -void -_initialize_sparc64nbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, - GDB_OSABI_NETBSD, sparc64nbsd_init_abi); -} diff --git a/gdb/sparc64-netbsd-nat.c b/gdb/sparc64-netbsd-nat.c new file mode 100644 index 00000000000..5e249b629d1 --- /dev/null +++ b/gdb/sparc64-netbsd-nat.c @@ -0,0 +1,188 @@ +/* Native-dependent code for NetBSD/sparc64. + + Copyright (C) 2003-2020 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 3 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, see . */ + +#include "defs.h" +#include "gdbcore.h" +#include "regcache.h" +#include "target.h" + +#include "sparc64-tdep.h" +#include "sparc-nat.h" + +/* NetBSD is different from the other OSes that support both SPARC and + UltraSPARC in that the result of ptrace(2) depends on whether the + traced process is 32-bit or 64-bit. */ + +static void +sparc64nbsd_supply_gregset (const struct sparc_gregmap *gregmap, + struct regcache *regcache, + int regnum, const void *gregs) +{ + int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); + + if (sparc32) + sparc32_supply_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs); + else + sparc64_supply_gregset (&sparc64nbsd_gregmap, regcache, regnum, gregs); +} + +static void +sparc64nbsd_collect_gregset (const struct sparc_gregmap *gregmap, + const struct regcache *regcache, + int regnum, void *gregs) +{ + int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); + + if (sparc32) + sparc32_collect_gregset (&sparc32nbsd_gregmap, regcache, regnum, gregs); + else + sparc64_collect_gregset (&sparc64nbsd_gregmap, regcache, regnum, gregs); +} + +static void +sparc64nbsd_supply_fpregset (const struct sparc_fpregmap *fpregmap, + struct regcache *regcache, + int regnum, const void *fpregs) +{ + int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); + + if (sparc32) + sparc32_supply_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs); + else + sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); +} + +static void +sparc64nbsd_collect_fpregset (const struct sparc_fpregmap *fpregmap, + const struct regcache *regcache, + int regnum, void *fpregs) +{ + int sparc32 = (gdbarch_ptr_bit (regcache->arch ()) == 32); + + if (sparc32) + sparc32_collect_fpregset (&sparc32_bsd_fpregmap, regcache, regnum, fpregs); + else + sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); +} + +/* Determine whether `gregset_t' contains register REGNUM. */ + +static int +sparc64nbsd_gregset_supplies_p (struct gdbarch *gdbarch, int regnum) +{ + if (gdbarch_ptr_bit (gdbarch) == 32) + return sparc32_gregset_supplies_p (gdbarch, regnum); + + /* Integer registers. */ + if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM) + || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM) + || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM) + || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM)) + return 1; + + /* Control registers. */ + if (regnum == SPARC64_PC_REGNUM + || regnum == SPARC64_NPC_REGNUM + || regnum == SPARC64_STATE_REGNUM + || regnum == SPARC64_Y_REGNUM) + return 1; + + return 0; +} + +/* Determine whether `fpregset_t' contains register REGNUM. */ + +static int +sparc64nbsd_fpregset_supplies_p (struct gdbarch *gdbarch, int regnum) +{ + if (gdbarch_ptr_bit (gdbarch) == 32) + return sparc32_fpregset_supplies_p (gdbarch, regnum); + + /* Floating-point registers. */ + if ((regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM) + || (regnum >= SPARC64_F32_REGNUM && regnum <= SPARC64_F62_REGNUM)) + return 1; + + /* Control registers. */ + if (regnum == SPARC64_FSR_REGNUM) + return 1; + + return 0; +} + + +/* Support for debugging kernel virtual memory images. */ + +#include +#include + +#include "bsd-kvm.h" + +static int +sparc64nbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + u_int64_t state; + int regnum; + + /* The following is true for NetBSD 1.6.2: + + The pcb contains %sp and %pc, %pstate and %cwp. From this + information we reconstruct the register state as it would look + when we just returned from cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_sp == 0) + return 0; + + /* If the program counter is zero, this is probably a core dump, and + we can get %pc from the stack. */ + if (pcb->pcb_pc == 0) + read_memory(pcb->pcb_sp + BIAS - 176 + (11 * 8), + (gdb_byte *)&pcb->pcb_pc, sizeof pcb->pcb_pc); + + regcache->raw_supply (SPARC_SP_REGNUM, &pcb->pcb_sp); + regcache->raw_supply (SPARC64_PC_REGNUM, &pcb->pcb_pc); + + state = pcb->pcb_pstate << 8 | pcb->pcb_cwp; + regcache->raw_supply (SPARC64_STATE_REGNUM, &state); + + sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); + + return 1; +} + +/* We've got nothing to add to the generic SPARC target. */ +static sparc_target the_sparc64_nbsd_nat_target; + +void _initialize_sparc64nbsd_nat (); +void +_initialize_sparc64nbsd_nat () +{ + sparc_supply_gregset = sparc64nbsd_supply_gregset; + sparc_collect_gregset = sparc64nbsd_collect_gregset; + sparc_supply_fpregset = sparc64nbsd_supply_fpregset; + sparc_collect_fpregset = sparc64nbsd_collect_fpregset; + sparc_gregset_supplies_p = sparc64nbsd_gregset_supplies_p; + sparc_fpregset_supplies_p = sparc64nbsd_fpregset_supplies_p; + + add_inf_child_target (&the_sparc64_nbsd_nat_target); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (sparc64nbsd_supply_pcb); +} diff --git a/gdb/sparc64-netbsd-tdep.c b/gdb/sparc64-netbsd-tdep.c new file mode 100644 index 00000000000..f5329a350b0 --- /dev/null +++ b/gdb/sparc64-netbsd-tdep.c @@ -0,0 +1,279 @@ +/* Target-dependent code for NetBSD/sparc64. + + Copyright (C) 2002-2020 Free Software Foundation, Inc. + Based on code 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 3 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, see . */ + +#include "defs.h" +#include "frame.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "symtab.h" +#include "objfiles.h" +#include "solib-svr4.h" +#include "trad-frame.h" + +#include "sparc64-tdep.h" +#include "netbsd-tdep.h" + +/* From . */ +const struct sparc_gregmap sparc64nbsd_gregmap = +{ + 0 * 8, /* "tstate" */ + 1 * 8, /* %pc */ + 2 * 8, /* %npc */ + 3 * 8, /* %y */ + -1, /* %fprs */ + -1, + 5 * 8, /* %g1 */ + -1, /* %l0 */ + 4 /* sizeof (%y) */ +}; + + +static void +sparc64nbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + sparc64_supply_gregset (&sparc64nbsd_gregmap, regcache, regnum, gregs); +} + +static void +sparc64nbsd_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); +} + + +/* Signal trampolines. */ + +/* The following variables describe the location of an on-stack signal + trampoline. The current values correspond to the memory layout for + NetBSD 1.3 and up. These shouldn't be necessary for NetBSD 2.0 and + up, since NetBSD uses signal trampolines provided by libc now. */ + +static const CORE_ADDR sparc64nbsd_sigtramp_start = 0xffffffffffffdee4ULL; +static const CORE_ADDR sparc64nbsd_sigtramp_end = 0xffffffffffffe000ULL; + +static int +sparc64nbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) +{ + if (pc >= sparc64nbsd_sigtramp_start && pc < sparc64nbsd_sigtramp_end) + return 1; + + return nbsd_pc_in_sigtramp (pc, name); +} + +struct trad_frame_saved_reg * +sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr, + struct frame_info *this_frame) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct trad_frame_saved_reg *saved_regs; + CORE_ADDR addr, sp; + int regnum, delta; + + saved_regs = trad_frame_alloc_saved_regs (this_frame); + + /* The registers are saved in bits and pieces scattered all over the + place. The code below records their location on the assumption + that the part of the signal trampoline that saves the state has + been executed. */ + + saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8; + saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16; + saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24; + saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32; + saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40; + saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48; + + /* The remaining `global' registers and %y are saved in the `local' + registers. */ + delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM; + for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++) + saved_regs[regnum].realreg = regnum + delta; + saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM; + + /* The remaining `out' registers can be found in the current frame's + `in' registers. */ + delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM; + for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++) + saved_regs[regnum].realreg = regnum + delta; + saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM; + + /* The `local' and `in' registers have been saved in the register + save area. */ + addr = saved_regs[SPARC_SP_REGNUM].addr; + sp = get_frame_memory_unsigned (this_frame, addr, 8); + for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS; + regnum <= SPARC_I7_REGNUM; regnum++, addr += 8) + saved_regs[regnum].addr = addr; + + /* Handle StackGhost. */ + { + ULONGEST wcookie = sparc_fetch_wcookie (gdbarch); + + if (wcookie != 0) + { + ULONGEST i7; + + addr = saved_regs[SPARC_I7_REGNUM].addr; + i7 = get_frame_memory_unsigned (this_frame, addr, 8); + trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie); + } + } + + /* TODO: Handle the floating-point registers. */ + + return saved_regs; +} + +static struct sparc_frame_cache * +sparc64nbsd_sigcontext_frame_cache (struct frame_info *this_frame, + void **this_cache) +{ + struct sparc_frame_cache *cache; + CORE_ADDR addr; + + if (*this_cache) + return (struct sparc_frame_cache *) *this_cache; + + cache = sparc_frame_cache (this_frame, this_cache); + gdb_assert (cache == *this_cache); + + /* If we couldn't find the frame's function, we're probably dealing + with an on-stack signal trampoline. */ + if (cache->pc == 0) + { + cache->pc = sparc64nbsd_sigtramp_start; + + /* Since we couldn't find the frame's function, the cache was + initialized under the assumption that we're frameless. */ + sparc_record_save_insn (cache); + addr = get_frame_register_unsigned (this_frame, SPARC_FP_REGNUM); + if (addr & 1) + addr += BIAS; + cache->base = addr; + } + + /* We find the appropriate instance of `struct sigcontext' at a + fixed offset in the signal frame. */ + addr = cache->base + 128 + 8; + cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame); + + return cache; +} + +static void +sparc64nbsd_sigcontext_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct sparc_frame_cache *cache = + sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static struct value * +sparc64nbsd_sigcontext_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct sparc_frame_cache *cache = + sparc64nbsd_sigcontext_frame_cache (this_frame, this_cache); + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); +} + +static int +sparc64nbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + const char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (sparc64nbsd_pc_in_sigtramp (pc, name)) + { + if (name == NULL || !startswith (name, "__sigtramp_sigcontext")) + return 1; + } + + return 0; +} + +static const struct frame_unwind sparc64nbsd_sigcontext_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + sparc64nbsd_sigcontext_frame_this_id, + sparc64nbsd_sigcontext_frame_prev_register, + NULL, + sparc64nbsd_sigtramp_frame_sniffer +}; + + +static const struct regset sparc64nbsd_gregset = + { + NULL, sparc64nbsd_supply_gregset, NULL + }; + +static const struct regset sparc64nbsd_fpregset = + { + NULL, sparc64nbsd_supply_fpregset, NULL + }; + +static void +sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + nbsd_init_abi (info, gdbarch); + + tdep->gregset = &sparc64nbsd_gregset; + tdep->sizeof_gregset = 160; + + tdep->fpregset = &sparc64nbsd_fpregset; + tdep->sizeof_fpregset = 272; + + /* Make sure we can single-step "new" syscalls. */ + tdep->step_trap = sparcnbsd_step_trap; + + frame_unwind_append_unwinder (gdbarch, &sparc64nbsd_sigcontext_frame_unwind); + + sparc64_init_abi (info, gdbarch); + + /* NetBSD/sparc64 has SVR4-style shared libraries. */ + set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); +} + +void _initialize_sparc64nbsd_tdep (); +void +_initialize_sparc64nbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, + GDB_OSABI_NETBSD, sparc64nbsd_init_abi); +} diff --git a/gdb/sparc64-tdep.h b/gdb/sparc64-tdep.h index d3ba9e22a45..f6305926dbd 100644 --- a/gdb/sparc64-tdep.h +++ b/gdb/sparc64-tdep.h @@ -124,7 +124,7 @@ extern const struct sparc_fpregmap sparc64_sol2_fpregmap; /* Register offsets for FreeBSD/sparc64. */ extern const struct sparc_gregmap sparc64fbsd_gregmap; -/* Functions and variables exported from sparc64-nbsd-tdep.c. */ +/* Functions and variables exported from sparc64-netbsd-tdep.c. */ /* Register offsets for NetBSD/sparc64. */ extern const struct sparc_gregmap sparc64nbsd_gregmap; diff --git a/gdb/vax-bsd-nat.c b/gdb/vax-bsd-nat.c index 1ca1f7bb1e8..8a08f48b055 100644 --- a/gdb/vax-bsd-nat.c +++ b/gdb/vax-bsd-nat.c @@ -30,7 +30,7 @@ #include "vax-tdep.h" #include "inf-ptrace.h" -#include "nbsd-nat.h" +#include "netbsd-nat.h" struct vax_bsd_nat_target final : public nbsd_nat_target { diff --git a/gdb/vax-nbsd-tdep.c b/gdb/vax-nbsd-tdep.c deleted file mode 100644 index 40007f11660..00000000000 --- a/gdb/vax-nbsd-tdep.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Target-dependent code for NetBSD/vax. - - Copyright (C) 2004-2020 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 3 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, see . */ - -#include "defs.h" -#include "arch-utils.h" -#include "osabi.h" - -#include "vax-tdep.h" -#include "nbsd-tdep.h" -#include "solib-svr4.h" - -/* NetBSD ELF. */ - -static void -vaxnbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - nbsd_init_abi (info, gdbarch); - - /* NetBSD ELF uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - -void _initialize_vaxnbsd_tdep (); -void -_initialize_vaxnbsd_tdep () -{ - gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_NETBSD, - vaxnbsd_elf_init_abi); -} diff --git a/gdb/vax-netbsd-tdep.c b/gdb/vax-netbsd-tdep.c new file mode 100644 index 00000000000..18add042620 --- /dev/null +++ b/gdb/vax-netbsd-tdep.c @@ -0,0 +1,46 @@ +/* Target-dependent code for NetBSD/vax. + + Copyright (C) 2004-2020 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 3 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, see . */ + +#include "defs.h" +#include "arch-utils.h" +#include "osabi.h" + +#include "vax-tdep.h" +#include "netbsd-tdep.h" +#include "solib-svr4.h" + +/* NetBSD ELF. */ + +static void +vaxnbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + nbsd_init_abi (info, gdbarch); + + /* NetBSD ELF uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +void _initialize_vaxnbsd_tdep (); +void +_initialize_vaxnbsd_tdep () +{ + gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_NETBSD, + vaxnbsd_elf_init_abi); +}