From 1b71cfcfdc3e13a655fefa6566b5564cec044c10 Mon Sep 17 00:00:00 2001 From: Kamil Rytarowski Date: Tue, 6 Oct 2020 21:36:22 +0200 Subject: 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. --- gdb/ChangeLog | 67 ++++ gdb/Makefile.in | 78 ++--- gdb/alpha-bsd-nat.c | 2 +- gdb/alpha-bsd-tdep.h | 2 +- gdb/alpha-nbsd-tdep.c | 292 ----------------- gdb/alpha-netbsd-tdep.c | 292 +++++++++++++++++ gdb/amd64-nbsd-nat.c | 68 ---- gdb/amd64-nbsd-tdep.c | 133 -------- gdb/amd64-netbsd-nat.c | 68 ++++ gdb/amd64-netbsd-tdep.c | 133 ++++++++ gdb/amd64-tdep.h | 2 +- gdb/arm-nbsd-nat.c | 363 --------------------- gdb/arm-nbsd-tdep.c | 171 ---------- gdb/arm-nbsd-tdep.h | 27 -- gdb/arm-netbsd-nat.c | 363 +++++++++++++++++++++ gdb/arm-netbsd-tdep.c | 171 ++++++++++ gdb/arm-netbsd-tdep.h | 27 ++ gdb/configure.nat | 22 +- gdb/configure.tgt | 32 +- gdb/hppa-nbsd-nat.c | 238 -------------- gdb/hppa-nbsd-tdep.c | 220 ------------- gdb/hppa-netbsd-nat.c | 238 ++++++++++++++ gdb/hppa-netbsd-tdep.c | 220 +++++++++++++ gdb/i386-nbsd-nat.c | 84 ----- gdb/i386-nbsd-tdep.c | 432 ------------------------ gdb/i386-netbsd-nat.c | 84 +++++ gdb/i386-netbsd-tdep.c | 432 ++++++++++++++++++++++++ gdb/m68k-bsd-nat.c | 2 +- gdb/mips-nbsd-nat.c | 123 ------- gdb/mips-nbsd-tdep.c | 382 ---------------------- gdb/mips-nbsd-tdep.h | 29 -- gdb/mips-netbsd-nat.c | 123 +++++++ gdb/mips-netbsd-tdep.c | 382 ++++++++++++++++++++++ gdb/mips-netbsd-tdep.h | 29 ++ gdb/nbsd-nat.c | 815 ---------------------------------------------- gdb/nbsd-nat.h | 62 ---- gdb/nbsd-tdep.c | 632 ----------------------------------- gdb/nbsd-tdep.h | 50 --- gdb/netbsd-nat.c | 815 ++++++++++++++++++++++++++++++++++++++++++++++ gdb/netbsd-nat.h | 62 ++++ gdb/netbsd-tdep.c | 632 +++++++++++++++++++++++++++++++++++ gdb/netbsd-tdep.h | 50 +++ gdb/ppc-nbsd-nat.c | 195 ----------- gdb/ppc-nbsd-tdep.c | 223 ------------- gdb/ppc-nbsd-tdep.h | 32 -- gdb/ppc-netbsd-nat.c | 195 +++++++++++ gdb/ppc-netbsd-tdep.c | 223 +++++++++++++ gdb/ppc-netbsd-tdep.h | 32 ++ gdb/sh-nbsd-nat.c | 107 ------ gdb/sh-nbsd-tdep.c | 84 ----- gdb/sh-netbsd-nat.c | 107 ++++++ gdb/sh-netbsd-tdep.c | 84 +++++ gdb/sparc-nbsd-nat.c | 71 ---- gdb/sparc-nbsd-tdep.c | 326 ------------------- gdb/sparc-netbsd-nat.c | 71 ++++ gdb/sparc-netbsd-tdep.c | 326 +++++++++++++++++++ gdb/sparc64-nbsd-nat.c | 188 ----------- gdb/sparc64-nbsd-tdep.c | 279 ---------------- gdb/sparc64-netbsd-nat.c | 188 +++++++++++ gdb/sparc64-netbsd-tdep.c | 279 ++++++++++++++++ gdb/sparc64-tdep.h | 2 +- gdb/vax-bsd-nat.c | 2 +- gdb/vax-nbsd-tdep.c | 46 --- gdb/vax-netbsd-tdep.c | 46 +++ 64 files changed, 5811 insertions(+), 5744 deletions(-) delete mode 100644 gdb/alpha-nbsd-tdep.c create mode 100644 gdb/alpha-netbsd-tdep.c delete mode 100644 gdb/amd64-nbsd-nat.c delete mode 100644 gdb/amd64-nbsd-tdep.c create mode 100644 gdb/amd64-netbsd-nat.c create mode 100644 gdb/amd64-netbsd-tdep.c delete mode 100644 gdb/arm-nbsd-nat.c delete mode 100644 gdb/arm-nbsd-tdep.c delete mode 100644 gdb/arm-nbsd-tdep.h create mode 100644 gdb/arm-netbsd-nat.c create mode 100644 gdb/arm-netbsd-tdep.c create mode 100644 gdb/arm-netbsd-tdep.h delete mode 100644 gdb/hppa-nbsd-nat.c delete mode 100644 gdb/hppa-nbsd-tdep.c create mode 100644 gdb/hppa-netbsd-nat.c create mode 100644 gdb/hppa-netbsd-tdep.c delete mode 100644 gdb/i386-nbsd-nat.c delete mode 100644 gdb/i386-nbsd-tdep.c create mode 100644 gdb/i386-netbsd-nat.c create mode 100644 gdb/i386-netbsd-tdep.c delete mode 100644 gdb/mips-nbsd-nat.c delete mode 100644 gdb/mips-nbsd-tdep.c delete mode 100644 gdb/mips-nbsd-tdep.h create mode 100644 gdb/mips-netbsd-nat.c create mode 100644 gdb/mips-netbsd-tdep.c create mode 100644 gdb/mips-netbsd-tdep.h delete mode 100644 gdb/nbsd-nat.c delete mode 100644 gdb/nbsd-nat.h delete mode 100644 gdb/nbsd-tdep.c delete mode 100644 gdb/nbsd-tdep.h create mode 100644 gdb/netbsd-nat.c create mode 100644 gdb/netbsd-nat.h create mode 100644 gdb/netbsd-tdep.c create mode 100644 gdb/netbsd-tdep.h delete mode 100644 gdb/ppc-nbsd-nat.c delete mode 100644 gdb/ppc-nbsd-tdep.c delete mode 100644 gdb/ppc-nbsd-tdep.h create mode 100644 gdb/ppc-netbsd-nat.c create mode 100644 gdb/ppc-netbsd-tdep.c create mode 100644 gdb/ppc-netbsd-tdep.h delete mode 100644 gdb/sh-nbsd-nat.c delete mode 100644 gdb/sh-nbsd-tdep.c create mode 100644 gdb/sh-netbsd-nat.c create mode 100644 gdb/sh-netbsd-tdep.c delete mode 100644 gdb/sparc-nbsd-nat.c delete mode 100644 gdb/sparc-nbsd-tdep.c create mode 100644 gdb/sparc-netbsd-nat.c create mode 100644 gdb/sparc-netbsd-tdep.c delete mode 100644 gdb/sparc64-nbsd-nat.c delete mode 100644 gdb/sparc64-nbsd-tdep.c create mode 100644 gdb/sparc64-netbsd-nat.c create mode 100644 gdb/sparc64-netbsd-tdep.c delete mode 100644 gdb/vax-nbsd-tdep.c create mode 100644 gdb/vax-netbsd-tdep.c diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7dc3590..7953038 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 5f92e87..8a16089 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 8a82739..df9892e 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 a8fd7ba..728763f 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 58294ed..0000000 --- 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 0000000..c78e496 --- /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 7a4c0057..0000000 --- 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 5907148..0000000 --- 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 0000000..f518d37 --- /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 0000000..16c4f0b --- /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 44c1250..a4e6956 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 a8a67e6..0000000 --- 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 b1e369d..0000000 --- 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 1b35395..0000000 --- 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 0000000..acdbdd3 --- /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 0000000..fa2e449 --- /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 0000000..1b35395 --- /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 3e94a06..ef2218f 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 a3e11c4..d865ecd 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 c35f30d..0000000 --- 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 5309b19..0000000 --- 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 0000000..a3a2e32 --- /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 0000000..5a55207 --- /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 ac775c1..0000000 --- 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 82772b4..0000000 --- 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 0000000..4faa67f --- /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 0000000..905c4ff --- /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 9c42da5..731aaf0 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 461304a..0000000 --- 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 524990a..0000000 --- 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 588f168..0000000 --- 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 0000000..51ea1cb --- /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 0000000..b6f8773 --- /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 0000000..588f168 --- /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 46dcfac..0000000 --- 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 7461667..0000000 --- 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 2db994a..0000000 --- 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 a6e3a8f..0000000 --- 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 0000000..e7962e0 --- /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 0000000..7a55094 --- /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 0000000..0fa2d97 --- /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 0000000..a6e3a8f --- /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 8111f3e..0000000 --- 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 fa90243..0000000 --- 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 efbed9e..0000000 --- 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 0000000..6ecff11 --- /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 0000000..64f2b40 --- /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 0000000..efbed9e --- /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 b4f9db6..0000000 --- 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 6551c47..0000000 --- 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 0000000..fcdc4ef --- /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 0000000..eabec98 --- /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 7138d7d..0000000 --- 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 ab1b557..0000000 --- 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 0000000..7138d7d --- /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 0000000..7cb4126 --- /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 5e249b6..0000000 --- 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 dac7fa7..0000000 --- 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 0000000..5e249b6 --- /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 0000000..f5329a3 --- /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 d3ba9e2..f630592 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 1ca1f7b..8a08f48 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 40007f1..0000000 --- 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 0000000..18add04 --- /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); +} -- cgit v1.1