From: Simon Marchi Date: Tue, 22 Nov 2016 21:14:24 +0000 (-0500) Subject: Normalize names of some source files X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=03b62bbbce3dc5f15131d9e78f77d035cd1cffb3;p=binutils-gdb.git Normalize names of some source files Most tdep/nat files are named: --tdep.c --nat.c A few files do not respect this scheme. This patch renames them so that they are consistent with the rest of the files. It builds fine with --enable-targets=all, but that doesn't test the nat files. I can only hope that my grep skill is good enough. gdb/ChangeLog: * Makefile.in (ALL_64_TARGET_OBS, ALL_TARGET_OBS, HFILES_NO_SRCDIR, ALLDEPFILES): Rename files. * alphabsd-nat.c: Rename to ... * alpha-bsd-nat.c: ... this, adjust include. * alphabsd-tdep.c: Rename to ... * alpha-bsd-tdep.c: ... this, adjust include. * alphabsd-tdep.h: Rename to ... * alpha-bsd-tdep.h: ... this, adjust include barrier and comment. * alphafbsd-tdep.c: Rename to ... * alpha-fbsd-tdep.c: ... this. * alphanbsd-tdep.c: Rename to ... * alpha-nbsd-tdep.c: ... this, adjust include. * alphaobsd-tdep.c: Rename to ... * alpha-obsd-tdep.c: ... this, adjust include. * amd64bsd-nat.c: Rename to ... * amd64-bsd-nat.c: ... this, adjust include. * amd64fbsd-nat.c: Rename to ... * amd64-fbsd-nat.c: ... this, adjust include. * amd64fbsd-tdep.c: Rename to ... * amd64-fbsd-tdep.c: ... this, adjust include. * amd64nbsd-nat.c: Rename to ... * amd64-nbsd-nat.c: ... this. * amd64nbsd-tdep.c: Rename to ... * amd64-nbsd-tdep.c: ... this. * amd64obsd-nat.c: Rename to ... * amd64-obsd-nat.c: ... this. * amd64obsd-tdep.c: Rename to ... * amd64-obsd-tdep.c: ... this. * amd64-tdep.h: Update comments. * armbsd-tdep.c: Rename to ... * arm-bsd-tdep.c: ... this. * armnbsd-nat.c: Rename to ... * arm-nbsd-nat.c: ... this. * armnbsd-tdep.c: Rename to ... * arm-nbsd-tdep.c: ... this. * armobsd-tdep.c: Rename to ... * arm-obsd-tdep.c: ... this. * arm-tdep.h: Update comments. * hppabsd-tdep.c: Rename to ... * hppa-bsd-tdep.c: ... this, adjust include. * hppabsd-tdep.h: Rename to ... * hppa-bsd-tdep.h: ... this, adjust include barrier and comment. * hppanbsd-nat.c: Rename to ... * hppa-nbsd-nat.c: ... this. * hppanbsd-tdep.c: Rename to ... * hppa-nbsd-tdep.c: ... this, adjust include. * hppaobsd-nat.c: Rename to ... * hppa-obsd-nat.c: ... this. * hppaobsd-tdep.c: Rename to ... * hppa-obsd-tdep.c: ... this, adjust include. * i386bsd-nat.c: Rename to ... * i386-bsd-nat.c: ... this, adjust include. * i386bsd-nat.h: Rename to ... * i386-bsd-nat.h: ... this, adjust include barrier and comment. * i386bsd-tdep.c: Rename to ... * i386-bsd-tdep.c: ... this. * i386fbsd-nat.c: Rename to ... * i386-fbsd-nat.c: ... this, adjust include. * i386fbsd-tdep.c: Rename to ... * i386-fbsd-tdep.c: ... this, adjust include. * i386fbsd-tdep.h: Rename to ... * i386-fbsd-tdep.h: ... this, adjust include barrier and comment. * i386gnu-nat.c: Rename to ... * i386-gnu-nat.c: ... this. * i386gnu-tdep.c: Rename to ... * i386-gnu-tdep.c: ... this. * i386nbsd-nat.c: Rename to ... * i386-nbsd-nat.c: ... this, adjust include. * i386nbsd-tdep.c: Rename to ... * i386-nbsd-tdep.c: ... this. * i386obsd-nat.c: Rename to ... * i386-obsd-nat.c: ... this, adjust include. * i386obsd-tdep.c: Rename to ... * i386-obsd-tdep.c: ... this. * i386v4-nat.c: Rename to ... * i386-v4-nat.c: ... this. * i386-tdep.h: Update comments. * m68k-tdep.h: Update comments. * m68kbsd-nat.c: Rename to ... * m68k-bsd-nat.c: ... this. * m68kbsd-tdep.c: Rename to ... * m68k-bsd-tdep.c: ... this. * m68klinux-nat.c: Rename to ... * m68k-linux-nat.c: ... this. * m68klinux-tdep.c: Rename to ... * m68k-linux-tdep.c: ... this. * m88kbsd-nat.c: Rename to ... * m88k-bsd-nat.c: ... this. * mipsnbsd-nat.c: Rename to ... * mips-nbsd-nat.c: ... this, adjust include. * mipsnbsd-tdep.c: Rename to ... * mips-nbsd-tdep.c: ... this, adjust include. * mipsnbsd-tdep.h: Rename to ... * mips-nbsd-tdep.h: ... this, adjust include barrier and comment. * mips64obsd-nat.c: Rename to ... * mips64-obsd-nat.c: ... this. * mips64obsd-tdep.c: Rename to ... * mips64-obsd-tdep.c: ... this. * ppcfbsd-nat.c: Rename to ... * ppc-fbsd-nat.c: ... this, adjust include. * ppcfbsd-tdep.c: Rename to ... * ppc-fbsd-tdep.c: ... this, adjust include. * ppcfbsd-tdep.h: Rename to ... * ppc-fbsd-tdep.h: ... this, adjust include barrier and comment. * ppcnbsd-nat.c: Rename to ... * ppc-nbsd-nat.c: ... this, adjust include. * ppcnbsd-tdep.c: Rename to ... * ppc-nbsd-tdep.c: ... this, adjust include. * ppcnbsd-tdep.h: Rename to ... * ppc-nbsd-tdep.h: ... this, adjust include barrier and comment. * ppcobsd-nat.c: Rename to ... * ppc-obsd-nat.c: ... this, adjust include. * ppcobsd-tdep.c: Rename to ... * ppc-obsd-tdep.c: ... this, adjust include. * ppcobsd-tdep.h: Rename to ... * ppc-obsd-tdep.h: ... this, adjust include barrier and comment. * shnbsd-nat.c: Rename to ... * sh-nbsd-nat.c: ... this. * shnbsd-tdep.c: Rename to ... * sh-nbsd-tdep.c: ... this. * sparcnbsd-nat.c: Rename to ... * sparc-nbsd-nat.c: ... this. * sparcnbsd-tdep.c: Rename to ... * sparc-nbsd-tdep.c: ... this. * sparcobsd-tdep.c: Rename to ... * sparc-obsd-tdep.c: ... this. * sparc64fbsd-nat.c: Rename to ... * sparc64-fbsd-nat.c: ... this. * sparc64fbsd-tdep.c: Rename to ... * sparc64-fbsd-tdep.c: ... this. * sparc64nbsd-nat.c: Rename to ... * sparc64-nbsd-nat.c: ... this. * sparc64nbsd-tdep.c: Rename to ... * sparc64-nbsd-tdep.c: ... this. * sparc64obsd-nat.c: Rename to ... * sparc64-obsd-nat.c: ... this. * sparc64obsd-tdep.c: Rename to ... * sparc64-obsd-tdep.c: ... this. * sparc64-tdep.h: Update comments. * vaxbsd-nat.c: Rename to ... * vax-bsd-nat.c: ... this. * vaxnbsd-tdep.c: Rename to ... * vax-nbsd-tdep.c: ... this. * vaxobsd-tdep.c: Rename to ... * vax-obsd-tdep.c: ... this. * x86bsd-nat.h: Rename to ... * x86-bsd-nat.h: ... this, adjust include barrier and comment. * x86bsd-nat.c: Rename to ... * x86-bsd-nat.c: ... this, adjust include. * configure.tgt: Update renamed files. * config/alpha/fbsd.mh: Update renamed files. * config/alpha/nbsd.mh: Update renamed files. * config/arm/nbsdelf.mh: Update renamed files. * config/djgpp/fnchange.lst: Update renamed files. * config/i386/fbsd.mh: Update renamed files. * config/i386/fbsd64.mh: Update renamed files. * config/i386/i386gnu.mh: Update renamed files. * config/i386/i386sol2.mh: Update renamed files. * config/i386/nbsd64.mh: Update renamed files. * config/i386/nbsdelf.mh: Update renamed files. * config/i386/obsd.mh: Update renamed files. * config/i386/obsd64.mh: Update renamed files. * config/i386/sol2-64.mh: Update renamed files. * config/m68k/linux.mh: Update renamed files. * config/m68k/nbsdelf.mh: Update renamed files. * config/m68k/obsd.mh: Update renamed files. * config/m88k/obsd.mh: Update renamed files. * config/mips/nbsd.mh: Update renamed files. * config/mips/obsd64.mh: Update renamed files. * config/pa/nbsd.mh: Update renamed files. * config/pa/obsd.mh: Update renamed files. * config/powerpc/fbsd.mh: Update renamed files. * config/powerpc/nbsd.mh: Update renamed files. * config/powerpc/obsd.mh: Update renamed files. * config/sh/nbsd.mh: Update renamed files. * config/sparc/fbsd.mh: Update renamed files. * config/sparc/nbsd64.mh: Update renamed files. * config/sparc/nbsdelf.mh: Update renamed files. * config/sparc/obsd64.mh: Update renamed files. * config/vax/nbsdelf.mh: Update renamed files. * config/vax/obsd.mh: Update renamed files. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 45c1eeee863..aae4e7abd20 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,187 @@ +2016-11-22 Simon Marchi + + * Makefile.in (ALL_64_TARGET_OBS, ALL_TARGET_OBS, + HFILES_NO_SRCDIR, ALLDEPFILES): Rename files. + * alphabsd-nat.c: Rename to ... + * alpha-bsd-nat.c: ... this, adjust include. + * alphabsd-tdep.c: Rename to ... + * alpha-bsd-tdep.c: ... this, adjust include. + * alphabsd-tdep.h: Rename to ... + * alpha-bsd-tdep.h: ... this, adjust include barrier and comment. + * alphafbsd-tdep.c: Rename to ... + * alpha-fbsd-tdep.c: ... this. + * alphanbsd-tdep.c: Rename to ... + * alpha-nbsd-tdep.c: ... this, adjust include. + * alphaobsd-tdep.c: Rename to ... + * alpha-obsd-tdep.c: ... this, adjust include. + * amd64bsd-nat.c: Rename to ... + * amd64-bsd-nat.c: ... this, adjust include. + * amd64fbsd-nat.c: Rename to ... + * amd64-fbsd-nat.c: ... this, adjust include. + * amd64fbsd-tdep.c: Rename to ... + * amd64-fbsd-tdep.c: ... this, adjust include. + * amd64nbsd-nat.c: Rename to ... + * amd64-nbsd-nat.c: ... this. + * amd64nbsd-tdep.c: Rename to ... + * amd64-nbsd-tdep.c: ... this. + * amd64obsd-nat.c: Rename to ... + * amd64-obsd-nat.c: ... this. + * amd64obsd-tdep.c: Rename to ... + * amd64-obsd-tdep.c: ... this. + * amd64-tdep.h: Update comments. + * armbsd-tdep.c: Rename to ... + * arm-bsd-tdep.c: ... this. + * armnbsd-nat.c: Rename to ... + * arm-nbsd-nat.c: ... this. + * armnbsd-tdep.c: Rename to ... + * arm-nbsd-tdep.c: ... this. + * armobsd-tdep.c: Rename to ... + * arm-obsd-tdep.c: ... this. + * arm-tdep.h: Update comments. + * hppabsd-tdep.c: Rename to ... + * hppa-bsd-tdep.c: ... this, adjust include. + * hppabsd-tdep.h: Rename to ... + * hppa-bsd-tdep.h: ... this, adjust include barrier and comment. + * hppanbsd-nat.c: Rename to ... + * hppa-nbsd-nat.c: ... this. + * hppanbsd-tdep.c: Rename to ... + * hppa-nbsd-tdep.c: ... this, adjust include. + * hppaobsd-nat.c: Rename to ... + * hppa-obsd-nat.c: ... this. + * hppaobsd-tdep.c: Rename to ... + * hppa-obsd-tdep.c: ... this, adjust include. + * i386bsd-nat.c: Rename to ... + * i386-bsd-nat.c: ... this, adjust include. + * i386bsd-nat.h: Rename to ... + * i386-bsd-nat.h: ... this, adjust include barrier and comment. + * i386bsd-tdep.c: Rename to ... + * i386-bsd-tdep.c: ... this. + * i386fbsd-nat.c: Rename to ... + * i386-fbsd-nat.c: ... this, adjust include. + * i386fbsd-tdep.c: Rename to ... + * i386-fbsd-tdep.c: ... this, adjust include. + * i386fbsd-tdep.h: Rename to ... + * i386-fbsd-tdep.h: ... this, adjust include barrier and comment. + * i386gnu-nat.c: Rename to ... + * i386-gnu-nat.c: ... this. + * i386gnu-tdep.c: Rename to ... + * i386-gnu-tdep.c: ... this. + * i386nbsd-nat.c: Rename to ... + * i386-nbsd-nat.c: ... this, adjust include. + * i386nbsd-tdep.c: Rename to ... + * i386-nbsd-tdep.c: ... this. + * i386obsd-nat.c: Rename to ... + * i386-obsd-nat.c: ... this, adjust include. + * i386obsd-tdep.c: Rename to ... + * i386-obsd-tdep.c: ... this. + * i386v4-nat.c: Rename to ... + * i386-v4-nat.c: ... this. + * i386-tdep.h: Update comments. + * m68k-tdep.h: Update comments. + * m68kbsd-nat.c: Rename to ... + * m68k-bsd-nat.c: ... this. + * m68kbsd-tdep.c: Rename to ... + * m68k-bsd-tdep.c: ... this. + * m68klinux-nat.c: Rename to ... + * m68k-linux-nat.c: ... this. + * m68klinux-tdep.c: Rename to ... + * m68k-linux-tdep.c: ... this. + * m88kbsd-nat.c: Rename to ... + * m88k-bsd-nat.c: ... this. + * mipsnbsd-nat.c: Rename to ... + * mips-nbsd-nat.c: ... this, adjust include. + * mipsnbsd-tdep.c: Rename to ... + * mips-nbsd-tdep.c: ... this, adjust include. + * mipsnbsd-tdep.h: Rename to ... + * mips-nbsd-tdep.h: ... this, adjust include barrier and comment. + * mips64obsd-nat.c: Rename to ... + * mips64-obsd-nat.c: ... this. + * mips64obsd-tdep.c: Rename to ... + * mips64-obsd-tdep.c: ... this. + * ppcfbsd-nat.c: Rename to ... + * ppc-fbsd-nat.c: ... this, adjust include. + * ppcfbsd-tdep.c: Rename to ... + * ppc-fbsd-tdep.c: ... this, adjust include. + * ppcfbsd-tdep.h: Rename to ... + * ppc-fbsd-tdep.h: ... this, adjust include barrier and comment. + * ppcnbsd-nat.c: Rename to ... + * ppc-nbsd-nat.c: ... this, adjust include. + * ppcnbsd-tdep.c: Rename to ... + * ppc-nbsd-tdep.c: ... this, adjust include. + * ppcnbsd-tdep.h: Rename to ... + * ppc-nbsd-tdep.h: ... this, adjust include barrier and comment. + * ppcobsd-nat.c: Rename to ... + * ppc-obsd-nat.c: ... this, adjust include. + * ppcobsd-tdep.c: Rename to ... + * ppc-obsd-tdep.c: ... this, adjust include. + * ppcobsd-tdep.h: Rename to ... + * ppc-obsd-tdep.h: ... this, adjust include barrier and comment. + * shnbsd-nat.c: Rename to ... + * sh-nbsd-nat.c: ... this. + * shnbsd-tdep.c: Rename to ... + * sh-nbsd-tdep.c: ... this. + * sparcnbsd-nat.c: Rename to ... + * sparc-nbsd-nat.c: ... this. + * sparcnbsd-tdep.c: Rename to ... + * sparc-nbsd-tdep.c: ... this. + * sparcobsd-tdep.c: Rename to ... + * sparc-obsd-tdep.c: ... this. + * sparc64fbsd-nat.c: Rename to ... + * sparc64-fbsd-nat.c: ... this. + * sparc64fbsd-tdep.c: Rename to ... + * sparc64-fbsd-tdep.c: ... this. + * sparc64nbsd-nat.c: Rename to ... + * sparc64-nbsd-nat.c: ... this. + * sparc64nbsd-tdep.c: Rename to ... + * sparc64-nbsd-tdep.c: ... this. + * sparc64obsd-nat.c: Rename to ... + * sparc64-obsd-nat.c: ... this. + * sparc64obsd-tdep.c: Rename to ... + * sparc64-obsd-tdep.c: ... this. + * sparc64-tdep.h: Update comments. + * vaxbsd-nat.c: Rename to ... + * vax-bsd-nat.c: ... this. + * vaxnbsd-tdep.c: Rename to ... + * vax-nbsd-tdep.c: ... this. + * vaxobsd-tdep.c: Rename to ... + * vax-obsd-tdep.c: ... this. + * x86bsd-nat.h: Rename to ... + * x86-bsd-nat.h: ... this, adjust include barrier and comment. + * x86bsd-nat.c: Rename to ... + * x86-bsd-nat.c: ... this, adjust include. + * configure.tgt: Update renamed files. + * config/alpha/fbsd.mh: Update renamed files. + * config/alpha/nbsd.mh: Update renamed files. + * config/arm/nbsdelf.mh: Update renamed files. + * config/djgpp/fnchange.lst: Update renamed files. + * config/i386/fbsd.mh: Update renamed files. + * config/i386/fbsd64.mh: Update renamed files. + * config/i386/i386gnu.mh: Update renamed files. + * config/i386/i386sol2.mh: Update renamed files. + * config/i386/nbsd64.mh: Update renamed files. + * config/i386/nbsdelf.mh: Update renamed files. + * config/i386/obsd.mh: Update renamed files. + * config/i386/obsd64.mh: Update renamed files. + * config/i386/sol2-64.mh: Update renamed files. + * config/m68k/linux.mh: Update renamed files. + * config/m68k/nbsdelf.mh: Update renamed files. + * config/m68k/obsd.mh: Update renamed files. + * config/m88k/obsd.mh: Update renamed files. + * config/mips/nbsd.mh: Update renamed files. + * config/mips/obsd64.mh: Update renamed files. + * config/pa/nbsd.mh: Update renamed files. + * config/pa/obsd.mh: Update renamed files. + * config/powerpc/fbsd.mh: Update renamed files. + * config/powerpc/nbsd.mh: Update renamed files. + * config/powerpc/obsd.mh: Update renamed files. + * config/sh/nbsd.mh: Update renamed files. + * config/sparc/fbsd.mh: Update renamed files. + * config/sparc/nbsd64.mh: Update renamed files. + * config/sparc/nbsdelf.mh: Update renamed files. + * config/sparc/obsd64.mh: Update renamed files. + * config/vax/nbsdelf.mh: Update renamed files. + * config/vax/obsd.mh: Update renamed files. + 2016-11-22 Simon Marchi * Makefile.in: Add comment about file lists ordering. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index af916aa0798..056b7642bd0 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -732,46 +732,46 @@ ALL_64_TARGET_OBS = \ aarch64-linux-tdep.o \ aarch64-newlib-tdep.o \ aarch64-tdep.o \ + alpha-bsd-tdep.o \ + alpha-fbsd-tdep.o \ alpha-linux-tdep.o \ alpha-mdebug-tdep.o \ + alpha-nbsd-tdep.o \ + alpha-obsd-tdep.o \ alpha-tdep.o \ - alphabsd-tdep.o \ - alphafbsd-tdep.o \ - alphanbsd-tdep.o \ - alphaobsd-tdep.o \ amd64-darwin-tdep.o \ amd64-dicos-tdep.o \ + amd64-fbsd-tdep.o \ amd64-linux-tdep.o \ + amd64-nbsd-tdep.o \ + amd64-obsd-tdep.o \ amd64-sol2-tdep.o \ amd64-tdep.o \ amd64-windows-tdep.o \ - amd64fbsd-tdep.o \ - amd64nbsd-tdep.o \ - amd64obsd-tdep.o \ ia64-linux-tdep.o \ ia64-tdep.o \ ia64-vms-tdep.o \ - mips64obsd-tdep.o \ + mips64-obsd-tdep.o \ + sparc64-fbsd-tdep.o \ sparc64-linux-tdep.o \ + sparc64-nbsd-tdep.o \ + sparc64-obsd-tdep.o \ sparc64-sol2-tdep.o \ - sparc64-tdep.o \ - sparc64fbsd-tdep.o \ - sparc64nbsd-tdep.o \ - sparc64obsd-tdep.o + sparc64-tdep.o # All other target-dependent objects files (used with --enable-targets=all). ALL_TARGET_OBS = \ arc-tdep.o \ arm.o \ + arm-bsd-tdep.o \ arm-get-next-pcs.o \ arm-linux.o \ arm-linux-tdep.o \ + arm-nbsd-tdep.o \ + arm-obsd-tdep.o \ arm-symbian-tdep.o \ arm-tdep.o \ arm-wince-tdep.o \ - armbsd-tdep.o \ - armnbsd-tdep.o \ - armobsd-tdep.o \ avr-tdep.o \ bfin-linux-tdep.o \ bfin-tdep.o \ @@ -785,23 +785,23 @@ ALL_TARGET_OBS = \ ft32-tdep.o \ glibc-tdep.o \ h8300-tdep.o \ + hppa-bsd-tdep.o \ hppa-linux-tdep.o \ + hppa-nbsd-tdep.o \ + hppa-obsd-tdep.o \ hppa-tdep.o \ - hppabsd-tdep.o \ - hppanbsd-tdep.o \ - hppaobsd-tdep.o \ + i386-bsd-tdep.o \ i386-cygwin-tdep.o \ i386-darwin-tdep.o \ i386-dicos-tdep.o \ + i386-fbsd-tdep.o \ + i386-gnu-tdep.o \ i386-linux-tdep.o \ + i386-nbsd-tdep.o \ i386-nto-tdep.o \ + i386-obsd-tdep.o \ i386-sol2-tdep.o \ i386-tdep.o \ - i386bsd-tdep.o \ - i386fbsd-tdep.o \ - i386gnu-tdep.o \ - i386nbsd-tdep.o \ - i386obsd-tdep.o \ i387-tdep.o \ iq2000-tdep.o \ linux-record.o \ @@ -811,17 +811,17 @@ ALL_TARGET_OBS = \ m32r-linux-tdep.o \ m32r-tdep.o \ m68hc11-tdep.o \ + m68k-bsd-tdep.o \ + m68k-linux-tdep.o \ m68k-tdep.o \ - m68kbsd-tdep.o \ - m68klinux-tdep.o \ m88k-tdep.o \ mep-tdep.o \ microblaze-linux-tdep.o \ microblaze-tdep.o \ mips-linux-tdep.o \ + mips-nbsd-tdep.o \ mips-sde-tdep.o \ mips-tdep.o \ - mipsnbsd-tdep.o \ mn10300-linux-tdep.o \ mn10300-tdep.o \ moxie-tdep.o \ @@ -833,13 +833,13 @@ ALL_TARGET_OBS = \ nios2-tdep.o \ nto-tdep.o \ obsd-tdep.o \ + ppc-fbsd-tdep.o \ ppc-linux-tdep.o \ + ppc-nbsd-tdep.o \ + ppc-obsd-tdep.o \ ppc-ravenscar-thread.o \ ppc-sysv-tdep.o \ ppc64-tdep.o \ - ppcfbsd-tdep.o \ - ppcnbsd-tdep.o \ - ppcobsd-tdep.o \ ravenscar-thread.o \ rl78-tdep.o \ rs6000-aix-tdep.o \ @@ -849,9 +849,9 @@ ALL_TARGET_OBS = \ s390-linux-tdep.o \ score-tdep.o \ sh-linux-tdep.o \ + sh-nbsd-tdep.o \ sh-tdep.o \ sh64-tdep.o \ - shnbsd-tdep.o \ sol2-tdep.o \ solib-aix.o \ solib-darwin.o \ @@ -860,11 +860,11 @@ ALL_TARGET_OBS = \ solib-spu.o \ solib-svr4.o \ sparc-linux-tdep.o \ + sparc-nbsd-tdep.o \ + sparc-obsd-tdep.o \ sparc-ravenscar-thread.o \ sparc-sol2-tdep.o \ sparc-tdep.o \ - sparcnbsd-tdep.o \ - sparcobsd-tdep.o \ spu-multiarch.o \ spu-tdep.o \ symfile-mem.o \ @@ -873,9 +873,9 @@ ALL_TARGET_OBS = \ tilegx-linux-tdep.o \ tilegx-tdep.o \ v850-tdep.o \ + vax-nbsd-tdep.o \ + vax-obsd-tdep.o \ vax-tdep.o \ - vaxnbsd-tdep.o \ - vaxobsd-tdep.o \ windows-tdep.o \ xcoffread.o \ xstormy16-tdep.o \ @@ -1222,8 +1222,8 @@ HFILES_NO_SRCDIR = \ aarch64-tdep.h \ ada-lang.h \ addrmap.h \ + alpha-bsd-tdep.h \ alpha-tdep.h \ - alphabsd-tdep.h \ amd64-darwin-tdep.h \ amd64-linux-tdep.h \ amd64-nat.h \ @@ -1312,14 +1312,14 @@ HFILES_NO_SRCDIR = \ gnu-nat.h \ go-lang.h \ gregset.h \ + hppa-bsd-tdep.h \ hppa-linux-offsets.h \ hppa-tdep.h \ - hppabsd-tdep.h \ + i386-bsd-nat.h \ i386-darwin-tdep.h \ i386-linux-nat.h \ i386-linux-tdep.h \ i386-tdep.h \ - i386bsd-nat.h \ i387-tdep.h \ ia64-libunwind-tdep.h \ ia64-tdep.h \ @@ -1353,8 +1353,8 @@ HFILES_NO_SRCDIR = \ memrange.h \ microblaze-tdep.h \ mips-linux-tdep.h \ + mips-nbsd-tdep.h \ mips-tdep.h \ - mipsnbsd-tdep.h \ mn10300-tdep.h \ moxie-tdep.h \ nbsd-nat.h \ @@ -1370,13 +1370,13 @@ HFILES_NO_SRCDIR = \ osdata.h \ p-lang.h \ parser-defs.h \ + ppc-fbsd-tdep.h \ ppc-linux-tdep.h \ + ppc-nbsd-tdep.h \ + ppc-obsd-tdep.h \ ppc-ravenscar-thread.h \ ppc-tdep.h \ ppc64-tdep.h \ - ppcfbsd-tdep.h \ - ppcnbsd-tdep.h \ - ppcobsd-tdep.h \ probe.h \ proc-utils.h \ procfs.h \ @@ -1448,9 +1448,9 @@ HFILES_NO_SRCDIR = \ vax-tdep.h \ windows-nat.h \ windows-tdep.h \ + x86-bsd-nat.h \ x86-linux-nat.h \ x86-nat.h \ - x86bsd-nat.h \ xcoffread.h \ xml-support.h \ xml-syscall.h \ @@ -2433,41 +2433,41 @@ ALLDEPFILES = \ aarch64-newlib-tdep.c \ aarch64-tdep.c \ aix-thread.c \ + alpha-bsd-nat.c \ + alpha-bsd-tdep.c \ + alpha-fbsd-tdep.c \ alpha-linux-nat.c \ alpha-linux-tdep.c \ alpha-mdebug-tdep.c \ + alpha-nbsd-tdep.c \ + alpha-obsd-tdep.c \ alpha-tdep.c \ - alphabsd-nat.c \ - alphabsd-tdep.c \ - alphafbsd-tdep.c \ - alphanbsd-tdep.c \ - alphaobsd-tdep.c \ + amd64-bsd-nat.c \ amd64-darwin-tdep.c \ amd64-dicos-tdep.c \ + amd64-fbsd-nat.c \ + amd64-fbsd-tdep.c \ amd64-linux-nat.c \ amd64-linux-tdep.c \ amd64-nat.c \ + amd64-nbsd-nat.c \ + amd64-nbsd-tdep.c \ + amd64-obsd-nat.c \ + amd64-obsd-tdep.c \ amd64-sol2-tdep.c \ amd64-tdep.c \ - amd64bsd-nat.c \ - amd64fbsd-nat.c \ - amd64fbsd-tdep.c \ - amd64nbsd-nat.c \ - amd64nbsd-tdep.c \ - amd64obsd-nat.c \ - amd64obsd-tdep.c \ arc-tdep.c \ arm.c \ + arm-bsd-tdep.c \ arm-get-next-pcs.c \ arm-linux.c \ arm-linux-nat.c \ arm-linux-tdep.c \ + arm-nbsd-nat.c \ + arm-nbsd-tdep.c \ + arm-obsd-tdep.c \ arm-symbian-tdep.c \ arm-tdep.c \ - armbsd-tdep.c \ - armnbsd-nat.c \ - armnbsd-tdep.c \ - armobsd-tdep.c \ avr-tdep.c \ bfin-linux-tdep.c \ bfin-tdep.c \ @@ -2486,34 +2486,34 @@ ALLDEPFILES = \ glibc-tdep.c \ go32-nat.c \ h8300-tdep.c \ + hppa-bsd-tdep.c \ hppa-linux-nat.c \ hppa-linux-tdep.c \ + hppa-nbsd-nat.c \ + hppa-nbsd-tdep.c \ + hppa-obsd-nat.c \ + hppa-obsd-tdep.c \ hppa-tdep.c \ - hppabsd-tdep.c \ - hppanbsd-nat.c \ - hppanbsd-tdep.c \ - hppaobsd-nat.c \ - hppaobsd-tdep.c \ + i386-bsd-nat.c \ + i386-bsd-tdep.c \ i386-cygwin-tdep.c \ i386-darwin-nat.c \ i386-darwin-tdep.c \ i386-dicos-tdep.c \ + i386-fbsd-nat.c \ + i386-fbsd-tdep.c \ + i386-gnu-nat.c \ + i386-gnu-tdep.c \ i386-linux-nat.c \ i386-linux-tdep.c \ + i386-nbsd-nat.c \ + i386-nbsd-tdep.c \ + i386-obsd-nat.c \ + i386-obsd-tdep.c \ i386-sol2-nat.c \ i386-sol2-tdep.c \ i386-tdep.c \ - i386bsd-nat.c \ - i386bsd-tdep.c \ - i386fbsd-nat.c \ - i386fbsd-tdep.c \ - i386gnu-nat.c \ - i386gnu-tdep.c \ - i386nbsd-nat.c \ - i386nbsd-tdep.c \ - i386obsd-nat.c \ - i386obsd-tdep.c \ - i386v4-nat.c \ + i386-v4-nat.c \ i387-tdep.c \ ia64-libunwind-tdep.c \ ia64-linux-nat.c \ @@ -2529,24 +2529,24 @@ ALLDEPFILES = \ m32r-linux-tdep.c \ m32r-tdep.c \ m68hc11-tdep.c \ + m68k-bsd-nat.c \ + m68k-bsd-tdep.c \ + m68k-linux-nat.c \ + m68k-linux-tdep.c \ m68k-tdep.c \ - m68kbsd-nat.c \ - m68kbsd-tdep.c \ - m68klinux-nat.c \ - m68klinux-tdep.c \ + m88k-bsd-nat.c \ m88k-tdep.c \ - m88kbsd-nat.c \ microblaze-linux-tdep.c \ microblaze-tdep.c \ mingw-hdep.c \ mips-linux-nat.c \ mips-linux-tdep.c \ + mips-nbsd-nat.c \ + mips-nbsd-tdep.c \ mips-sde-tdep.c \ mips-tdep.c \ - mips64obsd-nat.c \ - mips64obsd-tdep.c \ - mipsnbsd-nat.c \ - mipsnbsd-tdep.c \ + mips64-obsd-nat.c \ + mips64-obsd-tdep.c \ msp430-tdep.c \ nbsd-nat.c \ nbsd-tdep.c \ @@ -2556,17 +2556,17 @@ ALLDEPFILES = \ obsd-nat.c \ obsd-tdep.c \ posix-hdep.c \ + ppc-fbsd-nat.c \ + ppc-fbsd-tdep.c \ ppc-linux-nat.c \ ppc-linux-tdep.c \ + ppc-nbsd-nat.c \ + ppc-nbsd-tdep.c \ + ppc-obsd-nat.c \ + ppc-obsd-tdep.c \ ppc-ravenscar-thread.c \ ppc-sysv-tdep.c \ ppc64-tdep.c \ - ppcfbsd-nat.c \ - ppcfbsd-tdep.c \ - ppcnbsd-nat.c \ - ppcnbsd-tdep.c \ - ppcobsd-nat.c \ - ppcobsd-tdep.c \ procfs.c \ ravenscar-thread.c \ remote-sim.c \ @@ -2582,10 +2582,10 @@ ALLDEPFILES = \ ser-mingw.c \ ser-pipe.c \ ser-tcp.c \ + sh-nbsd-nat.c \ + sh-nbsd-tdep.c \ sh-tdep.c \ sh64-tdep.c \ - shnbsd-nat.c \ - shnbsd-tdep.c \ sol2-tdep.c \ solib-aix.c \ solib-spu.c \ @@ -2593,24 +2593,24 @@ ALLDEPFILES = \ sparc-linux-nat.c \ sparc-linux-tdep.c \ sparc-nat.c \ + sparc-nbsd-nat.c \ + sparc-nbsd-tdep.c \ + sparc-obsd-tdep.c \ sparc-ravenscar-thread.c \ sparc-sol2-nat.c \ sparc-sol2-tdep.c \ sparc-tdep.c \ + sparc64-fbsd-nat.c \ + sparc64-fbsd-tdep.c \ sparc64-linux-nat.c \ sparc64-linux-tdep.c \ sparc64-nat.c \ + sparc64-nbsd-nat.c \ + sparc64-nbsd-tdep.c \ + sparc64-obsd-nat.c \ + sparc64-obsd-tdep.c \ sparc64-sol2-tdep.c \ sparc64-tdep.c \ - sparc64fbsd-nat.c \ - sparc64fbsd-tdep.c \ - sparc64nbsd-nat.c \ - sparc64nbsd-tdep.c \ - sparc64obsd-nat.c \ - sparc64obsd-tdep.c \ - sparcnbsd-nat.c \ - sparcnbsd-tdep.c \ - sparcobsd-tdep.c \ spu-linux-nat.c \ spu-multiarch.c \ spu-tdep.c \ @@ -2618,9 +2618,9 @@ ALLDEPFILES = \ tilegx-linux-tdep.c \ tilegx-tdep.c \ v850-tdep.c \ + vax-bsd-nat.c \ + vax-nbsd-tdep.c \ vax-tdep.c \ - vaxbsd-nat.c \ - vaxnbsd-tdep.c \ windows-nat.c \ windows-tdep.c \ x86-nat.c \ diff --git a/gdb/alpha-bsd-nat.c b/gdb/alpha-bsd-nat.c new file mode 100644 index 00000000000..1e58be36d5e --- /dev/null +++ b/gdb/alpha-bsd-nat.c @@ -0,0 +1,205 @@ +/* Native-dependent code for Alpha BSD's. + + Copyright (C) 2000-2016 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 "alpha-tdep.h" +#include "alpha-bsd-tdep.h" +#include "inf-ptrace.h" + +#include +#include +#include + +#ifdef HAVE_SYS_PROCFS_H +#include +#endif + +#ifndef HAVE_GREGSET_T +typedef struct reg gregset_t; +#endif + +#ifndef HAVE_FPREGSET_T +typedef struct fpreg fpregset_t; +#endif + +#include "gregset.h" + +/* Provide *regset() wrappers around the generic Alpha BSD register + supply/fill routines. */ + +void +supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) +{ + alphabsd_supply_reg (regcache, (const char *) gregsetp, -1); +} + +void +fill_gregset (const struct regcache *regcache, gregset_t *gregsetp, int regno) +{ + alphabsd_fill_reg (regcache, (char *) gregsetp, regno); +} + +void +supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) +{ + alphabsd_supply_fpreg (regcache, (const char *) fpregsetp, -1); +} + +void +fill_fpregset (const struct regcache *regcache, + fpregset_t *fpregsetp, int regno) +{ + alphabsd_fill_fpreg (regcache, (char *) fpregsetp, regno); +} + +/* Determine if PT_GETREGS fetches this register. */ + +static int +getregs_supplies (int regno) +{ + return ((regno >= ALPHA_V0_REGNUM && regno <= ALPHA_ZERO_REGNUM) + || regno >= ALPHA_PC_REGNUM); +} + +/* Fetch register REGNO from the inferior. If REGNO is -1, do this + for all registers (including the floating point registers). */ + +static void +alphabsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + if (regno == -1 || getregs_supplies (regno)) + { + struct reg gregs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &gregs, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + alphabsd_supply_reg (regcache, (char *) &gregs, regno); + if (regno != -1) + return; + } + + if (regno == -1 + || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + alphabsd_supply_fpreg (regcache, (char *) &fpregs, regno); + } +} + +/* Store register REGNO back into the inferior. If REGNO is -1, do + this for all registers (including the floating point registers). */ + +static void +alphabsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + if (regno == -1 || getregs_supplies (regno)) + { + struct reg gregs; + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &gregs, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + alphabsd_fill_reg (regcache, (char *) &gregs, regno); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &gregs, 0) == -1) + perror_with_name (_("Couldn't write registers")); + + if (regno != -1) + return; + } + + if (regno == -1 + || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + alphabsd_fill_fpreg (regcache, (char *) &fpregs, regno); + + if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + + +/* Support for debugging kernel virtual memory images. */ + +#include +#include + +#include "bsd-kvm.h" + +static int +alphabsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + int regnum; + + /* The following is true for OpenBSD 3.9: + + The pcb contains the register state at the context switch inside + cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_hw.apcb_ksp == 0) + return 0; + + regcache_raw_supply (regcache, ALPHA_SP_REGNUM, &pcb->pcb_hw.apcb_ksp); + + for (regnum = ALPHA_S0_REGNUM; regnum < ALPHA_A0_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, + &pcb->pcb_context[regnum - ALPHA_S0_REGNUM]); + regcache_raw_supply (regcache, ALPHA_RA_REGNUM, &pcb->pcb_context[7]); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_alphabsd_nat (void); + +void +_initialize_alphabsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = alphabsd_fetch_inferior_registers; + t->to_store_registers = alphabsd_store_inferior_registers; + add_target (t); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (alphabsd_supply_pcb); +} diff --git a/gdb/alpha-bsd-tdep.c b/gdb/alpha-bsd-tdep.c new file mode 100644 index 00000000000..ee868c7f508 --- /dev/null +++ b/gdb/alpha-bsd-tdep.c @@ -0,0 +1,56 @@ +/* Common target dependent code Alpha BSD's. + + Copyright (C) 2000-2016 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 "alpha-tdep.h" +#include "alpha-bsd-tdep.h" + +/* Conviently, GDB uses the same register numbering as the + ptrace register structure used by BSD on Alpha. */ + +void +alphabsd_supply_reg (struct regcache *regcache, const char *regs, int regno) +{ + /* PC is at slot 32; UNIQUE not present. */ + alpha_supply_int_regs (regcache, regno, regs, regs + 31 * 8, NULL); +} + +void +alphabsd_fill_reg (const struct regcache *regcache, char *regs, int regno) +{ + /* PC is at slot 32; UNIQUE not present. */ + alpha_fill_int_regs (regcache, regno, regs, regs + 31 * 8, NULL); +} + +void +alphabsd_supply_fpreg (struct regcache *regcache, + const char *fpregs, int regno) +{ + /* FPCR is at slot 33; slot 32 unused. */ + alpha_supply_fp_regs (regcache, regno, fpregs, fpregs + 32 * 8); +} + +void +alphabsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno) +{ + /* FPCR is at slot 33; slot 32 unused. */ + alpha_fill_fp_regs (regcache, regno, fpregs, fpregs + 32 * 8); +} diff --git a/gdb/alpha-bsd-tdep.h b/gdb/alpha-bsd-tdep.h new file mode 100644 index 00000000000..4e042fd3c91 --- /dev/null +++ b/gdb/alpha-bsd-tdep.h @@ -0,0 +1,40 @@ +/* Common target dependent code for Alpha BSD's. + + Copyright (C) 2002-2016 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 ALPHA_BSD_TDEP_H +#define ALPHA_BSD_TDEP_H + +struct regcache; + +void alphabsd_supply_reg (struct regcache *, const char *, int); +void alphabsd_fill_reg (const struct regcache *, char *, int); + +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. */ + +/* 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); + +#endif /* alpha-bsd-tdep.h */ diff --git a/gdb/alpha-fbsd-tdep.c b/gdb/alpha-fbsd-tdep.c new file mode 100644 index 00000000000..84fedc27f1f --- /dev/null +++ b/gdb/alpha-fbsd-tdep.c @@ -0,0 +1,132 @@ +/* Target-dependent code for FreeBSD/alpha. + + Copyright (C) 2001-2016 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 "value.h" +#include "osabi.h" + +#include "alpha-tdep.h" +#include "solib-svr4.h" + +static int +alphafbsd_return_in_memory (struct type *type) +{ + enum type_code code; + int i; + + /* All aggregate types that won't fit in a register must be returned + in memory. */ + if (TYPE_LENGTH (type) > ALPHA_REGISTER_SIZE) + return 1; + + /* The only aggregate types that can be returned in a register are + structs and unions. Arrays must be returned in memory. */ + code = TYPE_CODE (type); + if (code != TYPE_CODE_STRUCT && code != TYPE_CODE_UNION) + return 1; + + /* We need to check if this struct/union is "integer" like. For + this to be true, the offset of each adressable subfield must be + zero. Note that bit fields are not addressable. */ + for (i = 0; i < TYPE_NFIELDS (type); i++) + { + /* If the field bitsize is non-zero, it isn't adressable. */ + if (TYPE_FIELD_BITPOS (type, i) != 0 + && TYPE_FIELD_BITSIZE (type, i) == 0) + return 1; + } + + return 0; +} + + +/* Support for signal handlers. */ + +/* Return whether PC is in a BSD sigtramp routine. */ + +CORE_ADDR alphafbsd_sigtramp_start = 0x11ffff68; +CORE_ADDR alphafbsd_sigtramp_end = 0x11ffffe0; + +static int +alphafbsd_pc_in_sigtramp (struct gdbarch *gdbarch, + CORE_ADDR pc, const char *func_name) +{ + return (pc >= alphafbsd_sigtramp_start && pc < alphafbsd_sigtramp_end); +} + +static LONGEST +alphafbsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + return pc - alphafbsd_sigtramp_start; +} + +/* Assuming THIS_FRAME is the frame of a BSD sigtramp routine, + return the address of the associated sigcontext structure. */ + +static CORE_ADDR +alphafbsd_sigcontext_addr (struct frame_info *this_frame) +{ + return get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM) + 24; +} + +/* FreeBSD 5.0-RELEASE or later. */ + +static void +alphafbsd_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* FIXME: Should activate generic FreeBSD support here with + fbsd_init_abi(), but this requires a valid + 'iterate_over_regset_sections' gdbarch method and + 'collect_regset' functions for each regset. */ + + /* 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); + + /* FreeBSD/alpha has SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); + + tdep->dynamic_sigtramp_offset = alphafbsd_sigtramp_offset; + tdep->sigcontext_addr = alphafbsd_sigcontext_addr; + tdep->pc_in_sigtramp = alphafbsd_pc_in_sigtramp; + tdep->return_in_memory = alphafbsd_return_in_memory; + tdep->sc_pc_offset = 288; + tdep->sc_regs_offset = 24; + tdep->sc_fpregs_offset = 320; + + tdep->jb_pc = 2; + tdep->jb_elt_size = 8; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_alphafbsd_tdep (void); + +void +_initialize_alphafbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_FREEBSD_ELF, + alphafbsd_init_abi); +} diff --git a/gdb/alpha-nbsd-tdep.c b/gdb/alpha-nbsd-tdep.c new file mode 100644 index 00000000000..00ff4814069 --- /dev/null +++ b/gdb/alpha-nbsd-tdep.c @@ -0,0 +1,304 @@ +/* Target-dependent code for NetBSD/alpha. + + Copyright (C) 2002-2016 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. */ + +/* Even though NetBSD/alpha used ELF since day one, it used the + traditional a.out-style core dump format before NetBSD 1.6. */ + +/* 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 (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8); + } + + if (regnum == ALPHA_FPCR_REGNUM || regnum == -1) + regcache_raw_supply (regcache, 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 (regcache, i, regs + regmap[i] * 8); + } + + if (regnum == ALPHA_PC_REGNUM || regnum == -1) + regcache_raw_supply (regcache, 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 (regcache, i, regs + i * 8); + } + + if (regnum == ALPHA_PC_REGNUM || regnum == -1) + regcache_raw_supply (regcache, 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_gregset, NULL, cb_data); + cb (".reg2", 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); + + /* 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); +} + + +static enum gdb_osabi +alphanbsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_ELF; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_alphanbsd_tdep (void); + +void +_initialize_alphanbsd_tdep (void) +{ + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_alpha, bfd_target_unknown_flavour, + alphanbsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD_ELF, + alphanbsd_init_abi); +} diff --git a/gdb/alpha-obsd-tdep.c b/gdb/alpha-obsd-tdep.c new file mode 100644 index 00000000000..98436f3a295 --- /dev/null +++ b/gdb/alpha-obsd-tdep.c @@ -0,0 +1,137 @@ +/* Target-dependent code for OpenBSD/alpha. + + Copyright (C) 2006-2016 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 "frame.h" +#include "gdbcore.h" +#include "osabi.h" + +#include "obsd-tdep.h" +#include "alpha-tdep.h" +#include "alpha-bsd-tdep.h" +#include "solib-svr4.h" + +/* Signal trampolines. */ + +/* The OpenBSD kernel maps the signal trampoline at some random + location in user space, which means that the traditional BSD way of + detecting it won't work. + + The signal trampoline will be mapped at an address that is page + aligned. We recognize the signal trampoline by looking for the + sigreturn system call. */ + +static const int alphaobsd_page_size = 8192; + +static LONGEST +alphaobsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + return (pc & (alphaobsd_page_size - 1)); +} + +static int +alphaobsd_pc_in_sigtramp (struct gdbarch *gdbarch, + CORE_ADDR pc, const char *name) +{ + CORE_ADDR start_pc = (pc & ~(alphaobsd_page_size - 1)); + unsigned insn; + + if (name) + return 0; + + /* Check for "". */ + insn = alpha_read_insn (gdbarch, start_pc + 5 * ALPHA_INSN_SIZE); + if (insn != 0x201f0067) + return 0; + + /* Check for "". */ + insn = alpha_read_insn (gdbarch, start_pc + 6 * ALPHA_INSN_SIZE); + if (insn != 0x00000083) + return 0; + + return 1; +} + +static CORE_ADDR +alphaobsd_sigcontext_addr (struct frame_info *this_frame) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + CORE_ADDR pc = get_frame_pc (this_frame); + + if (alphaobsd_sigtramp_offset (gdbarch, pc) < 3 * ALPHA_INSN_SIZE) + { + /* On entry, a pointer the `struct sigcontext' is passed in %a2. */ + return get_frame_register_unsigned (this_frame, ALPHA_A0_REGNUM + 2); + } + else if (alphaobsd_sigtramp_offset (gdbarch, pc) < 4 * ALPHA_INSN_SIZE) + { + /* It is stored on the stack Before calling the signal handler. */ + CORE_ADDR sp; + sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM); + return get_frame_memory_unsigned (this_frame, sp, 8); + } + else + { + /* It is reloaded into %a0 for the sigreturn(2) call. */ + return get_frame_register_unsigned (this_frame, ALPHA_A0_REGNUM); + } +} + + +static void +alphaobsd_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); + + /* OpenBSD/alpha 3.0 and earlier does not provide single step + support via ptrace(2); use software single-stepping for now. */ + set_gdbarch_software_single_step (gdbarch, alpha_software_single_step); + + /* OpenBSD/alpha has SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); + set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); + + tdep->dynamic_sigtramp_offset = alphaobsd_sigtramp_offset; + tdep->pc_in_sigtramp = alphaobsd_pc_in_sigtramp; + tdep->sigcontext_addr = alphaobsd_sigcontext_addr; + + tdep->jb_pc = 2; + tdep->jb_elt_size = 8; + + set_gdbarch_iterate_over_regset_sections + (gdbarch, alphanbsd_iterate_over_regset_sections); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_alphaobsd_tdep (void); + +void +_initialize_alphaobsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_OPENBSD_ELF, + alphaobsd_init_abi); +} diff --git a/gdb/alphabsd-nat.c b/gdb/alphabsd-nat.c deleted file mode 100644 index a7113df7466..00000000000 --- a/gdb/alphabsd-nat.c +++ /dev/null @@ -1,205 +0,0 @@ -/* Native-dependent code for Alpha BSD's. - - Copyright (C) 2000-2016 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 "alpha-tdep.h" -#include "alphabsd-tdep.h" -#include "inf-ptrace.h" - -#include -#include -#include - -#ifdef HAVE_SYS_PROCFS_H -#include -#endif - -#ifndef HAVE_GREGSET_T -typedef struct reg gregset_t; -#endif - -#ifndef HAVE_FPREGSET_T -typedef struct fpreg fpregset_t; -#endif - -#include "gregset.h" - -/* Provide *regset() wrappers around the generic Alpha BSD register - supply/fill routines. */ - -void -supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) -{ - alphabsd_supply_reg (regcache, (const char *) gregsetp, -1); -} - -void -fill_gregset (const struct regcache *regcache, gregset_t *gregsetp, int regno) -{ - alphabsd_fill_reg (regcache, (char *) gregsetp, regno); -} - -void -supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) -{ - alphabsd_supply_fpreg (regcache, (const char *) fpregsetp, -1); -} - -void -fill_fpregset (const struct regcache *regcache, - fpregset_t *fpregsetp, int regno) -{ - alphabsd_fill_fpreg (regcache, (char *) fpregsetp, regno); -} - -/* Determine if PT_GETREGS fetches this register. */ - -static int -getregs_supplies (int regno) -{ - return ((regno >= ALPHA_V0_REGNUM && regno <= ALPHA_ZERO_REGNUM) - || regno >= ALPHA_PC_REGNUM); -} - -/* Fetch register REGNO from the inferior. If REGNO is -1, do this - for all registers (including the floating point registers). */ - -static void -alphabsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - if (regno == -1 || getregs_supplies (regno)) - { - struct reg gregs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &gregs, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - alphabsd_supply_reg (regcache, (char *) &gregs, regno); - if (regno != -1) - return; - } - - if (regno == -1 - || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - alphabsd_supply_fpreg (regcache, (char *) &fpregs, regno); - } -} - -/* Store register REGNO back into the inferior. If REGNO is -1, do - this for all registers (including the floating point registers). */ - -static void -alphabsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - if (regno == -1 || getregs_supplies (regno)) - { - struct reg gregs; - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &gregs, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - alphabsd_fill_reg (regcache, (char *) &gregs, regno); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &gregs, 0) == -1) - perror_with_name (_("Couldn't write registers")); - - if (regno != -1) - return; - } - - if (regno == -1 - || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - alphabsd_fill_fpreg (regcache, (char *) &fpregs, regno); - - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - - -/* Support for debugging kernel virtual memory images. */ - -#include -#include - -#include "bsd-kvm.h" - -static int -alphabsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - int regnum; - - /* The following is true for OpenBSD 3.9: - - The pcb contains the register state at the context switch inside - cpu_switch(). */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_hw.apcb_ksp == 0) - return 0; - - regcache_raw_supply (regcache, ALPHA_SP_REGNUM, &pcb->pcb_hw.apcb_ksp); - - for (regnum = ALPHA_S0_REGNUM; regnum < ALPHA_A0_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, - &pcb->pcb_context[regnum - ALPHA_S0_REGNUM]); - regcache_raw_supply (regcache, ALPHA_RA_REGNUM, &pcb->pcb_context[7]); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_alphabsd_nat (void); - -void -_initialize_alphabsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = alphabsd_fetch_inferior_registers; - t->to_store_registers = alphabsd_store_inferior_registers; - add_target (t); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (alphabsd_supply_pcb); -} diff --git a/gdb/alphabsd-tdep.c b/gdb/alphabsd-tdep.c deleted file mode 100644 index 5f531d9639d..00000000000 --- a/gdb/alphabsd-tdep.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Common target dependent code Alpha BSD's. - - Copyright (C) 2000-2016 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 "alpha-tdep.h" -#include "alphabsd-tdep.h" - -/* Conviently, GDB uses the same register numbering as the - ptrace register structure used by BSD on Alpha. */ - -void -alphabsd_supply_reg (struct regcache *regcache, const char *regs, int regno) -{ - /* PC is at slot 32; UNIQUE not present. */ - alpha_supply_int_regs (regcache, regno, regs, regs + 31 * 8, NULL); -} - -void -alphabsd_fill_reg (const struct regcache *regcache, char *regs, int regno) -{ - /* PC is at slot 32; UNIQUE not present. */ - alpha_fill_int_regs (regcache, regno, regs, regs + 31 * 8, NULL); -} - -void -alphabsd_supply_fpreg (struct regcache *regcache, - const char *fpregs, int regno) -{ - /* FPCR is at slot 33; slot 32 unused. */ - alpha_supply_fp_regs (regcache, regno, fpregs, fpregs + 32 * 8); -} - -void -alphabsd_fill_fpreg (const struct regcache *regcache, char *fpregs, int regno) -{ - /* FPCR is at slot 33; slot 32 unused. */ - alpha_fill_fp_regs (regcache, regno, fpregs, fpregs + 32 * 8); -} diff --git a/gdb/alphabsd-tdep.h b/gdb/alphabsd-tdep.h deleted file mode 100644 index 19257350d93..00000000000 --- a/gdb/alphabsd-tdep.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Common target dependent code for Alpha BSD's. - - Copyright (C) 2002-2016 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 ALPHABSD_TDEP_H -#define ALPHABSD_TDEP_H - -struct regcache; - -void alphabsd_supply_reg (struct regcache *, const char *, int); -void alphabsd_fill_reg (const struct regcache *, char *, int); - -void alphabsd_supply_fpreg (struct regcache *, const char *, int); -void alphabsd_fill_fpreg (const struct regcache *, char *, int); - - -/* Functions exported from alphanbsd-tdep.c. */ - -/* 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); - -#endif /* alphabsd-tdep.h */ diff --git a/gdb/alphafbsd-tdep.c b/gdb/alphafbsd-tdep.c deleted file mode 100644 index 84fedc27f1f..00000000000 --- a/gdb/alphafbsd-tdep.c +++ /dev/null @@ -1,132 +0,0 @@ -/* Target-dependent code for FreeBSD/alpha. - - Copyright (C) 2001-2016 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 "value.h" -#include "osabi.h" - -#include "alpha-tdep.h" -#include "solib-svr4.h" - -static int -alphafbsd_return_in_memory (struct type *type) -{ - enum type_code code; - int i; - - /* All aggregate types that won't fit in a register must be returned - in memory. */ - if (TYPE_LENGTH (type) > ALPHA_REGISTER_SIZE) - return 1; - - /* The only aggregate types that can be returned in a register are - structs and unions. Arrays must be returned in memory. */ - code = TYPE_CODE (type); - if (code != TYPE_CODE_STRUCT && code != TYPE_CODE_UNION) - return 1; - - /* We need to check if this struct/union is "integer" like. For - this to be true, the offset of each adressable subfield must be - zero. Note that bit fields are not addressable. */ - for (i = 0; i < TYPE_NFIELDS (type); i++) - { - /* If the field bitsize is non-zero, it isn't adressable. */ - if (TYPE_FIELD_BITPOS (type, i) != 0 - && TYPE_FIELD_BITSIZE (type, i) == 0) - return 1; - } - - return 0; -} - - -/* Support for signal handlers. */ - -/* Return whether PC is in a BSD sigtramp routine. */ - -CORE_ADDR alphafbsd_sigtramp_start = 0x11ffff68; -CORE_ADDR alphafbsd_sigtramp_end = 0x11ffffe0; - -static int -alphafbsd_pc_in_sigtramp (struct gdbarch *gdbarch, - CORE_ADDR pc, const char *func_name) -{ - return (pc >= alphafbsd_sigtramp_start && pc < alphafbsd_sigtramp_end); -} - -static LONGEST -alphafbsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) -{ - return pc - alphafbsd_sigtramp_start; -} - -/* Assuming THIS_FRAME is the frame of a BSD sigtramp routine, - return the address of the associated sigcontext structure. */ - -static CORE_ADDR -alphafbsd_sigcontext_addr (struct frame_info *this_frame) -{ - return get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM) + 24; -} - -/* FreeBSD 5.0-RELEASE or later. */ - -static void -alphafbsd_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* FIXME: Should activate generic FreeBSD support here with - fbsd_init_abi(), but this requires a valid - 'iterate_over_regset_sections' gdbarch method and - 'collect_regset' functions for each regset. */ - - /* 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); - - /* FreeBSD/alpha has SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); - - tdep->dynamic_sigtramp_offset = alphafbsd_sigtramp_offset; - tdep->sigcontext_addr = alphafbsd_sigcontext_addr; - tdep->pc_in_sigtramp = alphafbsd_pc_in_sigtramp; - tdep->return_in_memory = alphafbsd_return_in_memory; - tdep->sc_pc_offset = 288; - tdep->sc_regs_offset = 24; - tdep->sc_fpregs_offset = 320; - - tdep->jb_pc = 2; - tdep->jb_elt_size = 8; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_alphafbsd_tdep (void); - -void -_initialize_alphafbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_FREEBSD_ELF, - alphafbsd_init_abi); -} diff --git a/gdb/alphanbsd-tdep.c b/gdb/alphanbsd-tdep.c deleted file mode 100644 index abe3926e45f..00000000000 --- a/gdb/alphanbsd-tdep.c +++ /dev/null @@ -1,304 +0,0 @@ -/* Target-dependent code for NetBSD/alpha. - - Copyright (C) 2002-2016 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 "alphabsd-tdep.h" -#include "nbsd-tdep.h" -#include "solib-svr4.h" -#include "target.h" - -/* Core file support. */ - -/* Even though NetBSD/alpha used ELF since day one, it used the - traditional a.out-style core dump format before NetBSD 1.6. */ - -/* 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 (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8); - } - - if (regnum == ALPHA_FPCR_REGNUM || regnum == -1) - regcache_raw_supply (regcache, 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 (regcache, i, regs + regmap[i] * 8); - } - - if (regnum == ALPHA_PC_REGNUM || regnum == -1) - regcache_raw_supply (regcache, 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 (regcache, i, regs + i * 8); - } - - if (regnum == ALPHA_PC_REGNUM || regnum == -1) - regcache_raw_supply (regcache, 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_gregset, NULL, cb_data); - cb (".reg2", 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); - - /* 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); -} - - -static enum gdb_osabi -alphanbsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_NETBSD_ELF; - - return GDB_OSABI_UNKNOWN; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_alphanbsd_tdep (void); - -void -_initialize_alphanbsd_tdep (void) -{ - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_alpha, bfd_target_unknown_flavour, - alphanbsd_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_NETBSD_ELF, - alphanbsd_init_abi); -} diff --git a/gdb/alphaobsd-tdep.c b/gdb/alphaobsd-tdep.c deleted file mode 100644 index 9c04da09747..00000000000 --- a/gdb/alphaobsd-tdep.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Target-dependent code for OpenBSD/alpha. - - Copyright (C) 2006-2016 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 "frame.h" -#include "gdbcore.h" -#include "osabi.h" - -#include "obsd-tdep.h" -#include "alpha-tdep.h" -#include "alphabsd-tdep.h" -#include "solib-svr4.h" - -/* Signal trampolines. */ - -/* The OpenBSD kernel maps the signal trampoline at some random - location in user space, which means that the traditional BSD way of - detecting it won't work. - - The signal trampoline will be mapped at an address that is page - aligned. We recognize the signal trampoline by looking for the - sigreturn system call. */ - -static const int alphaobsd_page_size = 8192; - -static LONGEST -alphaobsd_sigtramp_offset (struct gdbarch *gdbarch, CORE_ADDR pc) -{ - return (pc & (alphaobsd_page_size - 1)); -} - -static int -alphaobsd_pc_in_sigtramp (struct gdbarch *gdbarch, - CORE_ADDR pc, const char *name) -{ - CORE_ADDR start_pc = (pc & ~(alphaobsd_page_size - 1)); - unsigned insn; - - if (name) - return 0; - - /* Check for "". */ - insn = alpha_read_insn (gdbarch, start_pc + 5 * ALPHA_INSN_SIZE); - if (insn != 0x201f0067) - return 0; - - /* Check for "". */ - insn = alpha_read_insn (gdbarch, start_pc + 6 * ALPHA_INSN_SIZE); - if (insn != 0x00000083) - return 0; - - return 1; -} - -static CORE_ADDR -alphaobsd_sigcontext_addr (struct frame_info *this_frame) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - CORE_ADDR pc = get_frame_pc (this_frame); - - if (alphaobsd_sigtramp_offset (gdbarch, pc) < 3 * ALPHA_INSN_SIZE) - { - /* On entry, a pointer the `struct sigcontext' is passed in %a2. */ - return get_frame_register_unsigned (this_frame, ALPHA_A0_REGNUM + 2); - } - else if (alphaobsd_sigtramp_offset (gdbarch, pc) < 4 * ALPHA_INSN_SIZE) - { - /* It is stored on the stack Before calling the signal handler. */ - CORE_ADDR sp; - sp = get_frame_register_unsigned (this_frame, ALPHA_SP_REGNUM); - return get_frame_memory_unsigned (this_frame, sp, 8); - } - else - { - /* It is reloaded into %a0 for the sigreturn(2) call. */ - return get_frame_register_unsigned (this_frame, ALPHA_A0_REGNUM); - } -} - - -static void -alphaobsd_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); - - /* OpenBSD/alpha 3.0 and earlier does not provide single step - support via ptrace(2); use software single-stepping for now. */ - set_gdbarch_software_single_step (gdbarch, alpha_software_single_step); - - /* OpenBSD/alpha has SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); - set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); - - tdep->dynamic_sigtramp_offset = alphaobsd_sigtramp_offset; - tdep->pc_in_sigtramp = alphaobsd_pc_in_sigtramp; - tdep->sigcontext_addr = alphaobsd_sigcontext_addr; - - tdep->jb_pc = 2; - tdep->jb_elt_size = 8; - - set_gdbarch_iterate_over_regset_sections - (gdbarch, alphanbsd_iterate_over_regset_sections); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_alphaobsd_tdep (void); - -void -_initialize_alphaobsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_alpha, 0, GDB_OSABI_OPENBSD_ELF, - alphaobsd_init_abi); -} diff --git a/gdb/amd64-bsd-nat.c b/gdb/amd64-bsd-nat.c new file mode 100644 index 00000000000..4e6995c6448 --- /dev/null +++ b/gdb/amd64-bsd-nat.c @@ -0,0 +1,159 @@ +/* Native-dependent code for AMD64 BSD's. + + Copyright (C) 2003-2016 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 "target.h" + +/* We include to make sure `struct fxsave64' is defined on + NetBSD, since NetBSD's needs it. */ +#include +#include +#include +#include + +#include "amd64-tdep.h" +#include "amd64-nat.h" +#include "x86-bsd-nat.h" +#include "inf-ptrace.h" + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +static void +amd64bsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + amd64_supply_native_gregset (regcache, ®s, -1); + if (regnum != -1) + return; + } + + if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) + { + struct fpreg fpregs; +#ifdef PT_GETXSTATE_INFO + void *xstateregs; + + if (x86bsd_xsave_len != 0) + { + xstateregs = alloca (x86bsd_xsave_len); + if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) + perror_with_name (_("Couldn't get extended state status")); + + amd64_supply_xsave (regcache, -1, xstateregs); + return; + } +#endif + + if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + amd64_supply_fxsave (regcache, -1, &fpregs); + } +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers (including the floating-point registers). */ + +static void +amd64bsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + amd64_collect_native_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + + if (regnum != -1) + return; + } + + if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) + { + struct fpreg fpregs; +#ifdef PT_GETXSTATE_INFO + void *xstateregs; + + if (x86bsd_xsave_len != 0) + { + xstateregs = alloca (x86bsd_xsave_len); + if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) + perror_with_name (_("Couldn't get extended state status")); + + amd64_collect_xsave (regcache, regnum, xstateregs, 0); + + if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xstateregs, x86bsd_xsave_len) == -1) + perror_with_name (_("Couldn't write extended state status")); + return; + } +#endif + + if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + amd64_collect_fxsave (regcache, regnum, &fpregs); + + if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + +/* Create a prototype *BSD/amd64 target. The client can override it + with local methods. */ + +struct target_ops * +amd64bsd_target (void) +{ + struct target_ops *t; + + t = x86bsd_target (); + t->to_fetch_registers = amd64bsd_fetch_inferior_registers; + t->to_store_registers = amd64bsd_store_inferior_registers; + return t; +} diff --git a/gdb/amd64-fbsd-nat.c b/gdb/amd64-fbsd-nat.c new file mode 100644 index 00000000000..fce269978c9 --- /dev/null +++ b/gdb/amd64-fbsd-nat.c @@ -0,0 +1,291 @@ +/* Native-dependent code for FreeBSD/amd64. + + Copyright (C) 2003-2016 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 "target.h" + +#include +#include +#include +#include +#include +#include + +#include "fbsd-nat.h" +#include "amd64-tdep.h" +#include "amd64-nat.h" +#include "x86-bsd-nat.h" +#include "x86-nat.h" + + +/* Offset in `struct reg' where MEMBER is stored. */ +#define REG_OFFSET(member) offsetof (struct reg, member) + +/* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in + `struct reg' location where the GDB register REGNUM is stored. + Unsupported registers are marked with `-1'. */ +static int amd64fbsd64_r_reg_offset[] = +{ + REG_OFFSET (r_rax), + REG_OFFSET (r_rbx), + REG_OFFSET (r_rcx), + REG_OFFSET (r_rdx), + REG_OFFSET (r_rsi), + REG_OFFSET (r_rdi), + REG_OFFSET (r_rbp), + REG_OFFSET (r_rsp), + REG_OFFSET (r_r8), + REG_OFFSET (r_r9), + REG_OFFSET (r_r10), + REG_OFFSET (r_r11), + REG_OFFSET (r_r12), + REG_OFFSET (r_r13), + REG_OFFSET (r_r14), + REG_OFFSET (r_r15), + REG_OFFSET (r_rip), + REG_OFFSET (r_rflags), + REG_OFFSET (r_cs), + REG_OFFSET (r_ss), + -1, + -1, + -1, + -1 +}; + + +/* Mapping between the general-purpose registers in FreeBSD/amd64 + `struct reg' format and GDB's register cache layout for + FreeBSD/i386. + + Note that most FreeBSD/amd64 registers are 64-bit, while the + FreeBSD/i386 registers are all 32-bit, but since we're + little-endian we get away with that. */ + +/* From . */ +static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] = +{ + 14 * 8, 13 * 8, /* %eax, %ecx */ + 12 * 8, 11 * 8, /* %edx, %ebx */ + 20 * 8, 10 * 8, /* %esp, %ebp */ + 9 * 8, 8 * 8, /* %esi, %edi */ + 17 * 8, 19 * 8, /* %eip, %eflags */ + 18 * 8, 21 * 8, /* %cs, %ss */ + -1, -1, -1, -1 /* %ds, %es, %fs, %gs */ +}; + + +/* Support for debugging kernel virtual memory images. */ + +#include +#include + +#include "bsd-kvm.h" + +static int +amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + /* The following is true for FreeBSD 5.2: + + The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, + %ds, %es, %fs and %gs. This accounts for all callee-saved + registers specified by the psABI and then some. Here %esp + contains the stack pointer at the point just after the call to + cpu_switch(). From this information we reconstruct the register + state as it would like when we just returned from cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_rsp == 0) + return 0; + + pcb->pcb_rsp += 8; + regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip); + regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx); + regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp); + regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp); + regcache_raw_supply (regcache, 12, &pcb->pcb_r12); + regcache_raw_supply (regcache, 13, &pcb->pcb_r13); + regcache_raw_supply (regcache, 14, &pcb->pcb_r14); + regcache_raw_supply (regcache, 15, &pcb->pcb_r15); +#if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075) + /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only + up until __FreeBSD_version 800074: The removal of these fields + occurred on 2009-04-01 while the __FreeBSD_version number was + bumped to 800075 on 2009-04-06. So 800075 is the closest version + number where we should not try to access these fields. */ + regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds); + regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es); + regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs); + regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs); +#endif + + return 1; +} + + +/* Implement the to_read_description method. */ + +static const struct target_desc * +amd64fbsd_read_description (struct target_ops *ops) +{ +#ifdef PT_GETXSTATE_INFO + static int xsave_probed; + static uint64_t xcr0; +#endif + struct reg regs; + int is64; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL)); +#ifdef PT_GETXSTATE_INFO + if (!xsave_probed) + { + struct ptrace_xstate_info info; + + if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) + { + x86bsd_xsave_len = info.xsave_len; + xcr0 = info.xsave_mask; + } + xsave_probed = 1; + } + + if (x86bsd_xsave_len != 0) + { + if (is64) + return amd64_target_description (xcr0); + else + return i386_target_description (xcr0); + } +#endif + if (is64) + return tdesc_amd64; + else + return tdesc_i386; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_amd64fbsd_nat (void); + +void +_initialize_amd64fbsd_nat (void) +{ + struct target_ops *t; + int offset; + + amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset; + amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset; + + /* Add some extra features to the common *BSD/i386 target. */ + t = amd64bsd_target (); + t->to_read_description = amd64fbsd_read_description; + + fbsd_nat_add_target (t); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (amd64fbsd_supply_pcb); + + /* To support the recognition of signal handlers, i386-bsd-tdep.c + hardcodes some constants. Inclusion of this file means that we + are compiling a native debugger, which means that we can use the + system header files and sysctl(3) to get at the relevant + information. */ + +#define SC_REG_OFFSET amd64fbsd_sc_reg_offset + + /* We only check the program counter, stack pointer and frame + pointer since these members of `struct sigcontext' are essential + for providing backtraces. */ + +#define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM] +#define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM] +#define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM] + + /* Override the default value for the offset of the program counter + in the sigcontext structure. */ + offset = offsetof (struct sigcontext, sc_rip); + + if (SC_RIP_OFFSET != offset) + { + warning (_("\ +offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\ +Please report this to ."), + offset, SC_RIP_OFFSET); + } + + SC_RIP_OFFSET = offset; + + /* Likewise for the stack pointer. */ + offset = offsetof (struct sigcontext, sc_rsp); + + if (SC_RSP_OFFSET != offset) + { + warning (_("\ +offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\ +Please report this to ."), + offset, SC_RSP_OFFSET); + } + + SC_RSP_OFFSET = offset; + + /* And the frame pointer. */ + offset = offsetof (struct sigcontext, sc_rbp); + + if (SC_RBP_OFFSET != offset) + { + warning (_("\ +offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\ +Please report this to ."), + offset, SC_RBP_OFFSET); + } + + SC_RBP_OFFSET = offset; + +#ifdef KERN_PROC_SIGTRAMP + /* Normally signal frames are detected via amd64fbsd_sigtramp_p. + However, FreeBSD 9.2 through 10.1 do not include the page holding + the signal code in core dumps. These releases do provide a + kern.proc.sigtramp. sysctl that returns the location of the + signal trampoline for a running process. We fetch the location + of the current (gdb) process and use this to identify signal + frames in core dumps from these releases. Note that this only + works for core dumps of 64-bit (FreeBSD/amd64) processes and does + not handle core dumps of 32-bit (FreeBSD/i386) processes. */ + { + int mib[4]; + struct kinfo_sigtramp kst; + size_t len; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_SIGTRAMP; + mib[3] = getpid (); + len = sizeof (kst); + if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) + { + amd64fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start; + amd64fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end; + } + } +#endif +} diff --git a/gdb/amd64-fbsd-tdep.c b/gdb/amd64-fbsd-tdep.c new file mode 100644 index 00000000000..d3c42706f4c --- /dev/null +++ b/gdb/amd64-fbsd-tdep.c @@ -0,0 +1,319 @@ +/* Target-dependent code for FreeBSD/amd64. + + Copyright (C) 2003-2016 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 "osabi.h" +#include "regset.h" +#include "i386-fbsd-tdep.h" +#include "x86-xstate.h" + +#include "amd64-tdep.h" +#include "bsd-uthread.h" +#include "fbsd-tdep.h" +#include "solib-svr4.h" + +/* Support for signal handlers. */ + +/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp + routine. */ + +static const gdb_byte amd64fbsd_sigtramp_code[] = +{ + 0x48, 0x8d, 0x7c, 0x24, 0x10, /* lea SIGF_UC(%rsp),%rdi */ + 0x6a, 0x00, /* pushq $0 */ + 0x48, 0xc7, 0xc0, 0xa1, 0x01, 0x00, 0x00, + /* movq $SYS_sigreturn,%rax */ + 0x0f, 0x05 /* syscall */ +}; + +static int +amd64fbsd_sigtramp_p (struct frame_info *this_frame) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + gdb_byte buf[sizeof amd64fbsd_sigtramp_code]; + + if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf)) + return 0; + if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code) + != 0) + return 0; + + return 1; +} + +/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the + address of the associated sigcontext structure. */ + +static CORE_ADDR +amd64fbsd_sigcontext_addr (struct frame_info *this_frame) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp; + gdb_byte buf[8]; + + /* The `struct sigcontext' (which really is an `ucontext_t' on + FreeBSD/amd64) lives at a fixed offset in the signal frame. See + . */ + get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 8, byte_order); + return sp + 16; +} + +/* FreeBSD 5.1-RELEASE or later. */ + +/* Mapping between the general-purpose registers in `struct reg' + format and GDB's register cache layout. + + Note that some registers are 32-bit, but since we're little-endian + we get away with that. */ + +/* From . */ +static int amd64fbsd_r_reg_offset[] = +{ + 14 * 8, /* %rax */ + 11 * 8, /* %rbx */ + 13 * 8, /* %rcx */ + 12 * 8, /* %rdx */ + 9 * 8, /* %rsi */ + 8 * 8, /* %rdi */ + 10 * 8, /* %rbp */ + 20 * 8, /* %rsp */ + 7 * 8, /* %r8 ... */ + 6 * 8, + 5 * 8, + 4 * 8, + 3 * 8, + 2 * 8, + 1 * 8, + 0 * 8, /* ... %r15 */ + 17 * 8, /* %rip */ + 19 * 8, /* %eflags */ + 18 * 8, /* %cs */ + 21 * 8, /* %ss */ + -1, /* %ds */ + -1, /* %es */ + -1, /* %fs */ + -1 /* %gs */ +}; + +/* Location of the signal trampoline. */ +CORE_ADDR amd64fbsd_sigtramp_start_addr; +CORE_ADDR amd64fbsd_sigtramp_end_addr; + +/* From . */ +int amd64fbsd_sc_reg_offset[] = +{ + 24 + 6 * 8, /* %rax */ + 24 + 7 * 8, /* %rbx */ + 24 + 3 * 8, /* %rcx */ + 24 + 2 * 8, /* %rdx */ + 24 + 1 * 8, /* %rsi */ + 24 + 0 * 8, /* %rdi */ + 24 + 8 * 8, /* %rbp */ + 24 + 22 * 8, /* %rsp */ + 24 + 4 * 8, /* %r8 ... */ + 24 + 5 * 8, + 24 + 9 * 8, + 24 + 10 * 8, + 24 + 11 * 8, + 24 + 12 * 8, + 24 + 13 * 8, + 24 + 14 * 8, /* ... %r15 */ + 24 + 19 * 8, /* %rip */ + 24 + 21 * 8, /* %eflags */ + 24 + 20 * 8, /* %cs */ + 24 + 23 * 8, /* %ss */ + -1, /* %ds */ + -1, /* %es */ + -1, /* %fs */ + -1 /* %gs */ +}; + +/* From /usr/src/lib/libc/amd64/gen/_setjmp.S. */ +static int amd64fbsd_jmp_buf_reg_offset[] = +{ + -1, /* %rax */ + 1 * 8, /* %rbx */ + -1, /* %rcx */ + -1, /* %rdx */ + -1, /* %rsi */ + -1, /* %rdi */ + 3 * 8, /* %rbp */ + 2 * 8, /* %rsp */ + -1, /* %r8 ... */ + -1, + -1, + -1, /* ... %r11 */ + 4 * 8, /* %r12 ... */ + 5 * 8, + 6 * 8, + 7 * 8, /* ... %r15 */ + 0 * 8 /* %rip */ +}; + +/* Implement the core_read_description gdbarch method. */ + +static const struct target_desc * +amd64fbsd_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, + bfd *abfd) +{ + return amd64_target_description (i386fbsd_core_read_xcr0 (abfd)); +} + +/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */ + +static void +amd64fbsd_supply_xstateregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *xstateregs, size_t len) +{ + amd64_supply_xsave (regcache, regnum, xstateregs); +} + +/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */ + +static void +amd64fbsd_collect_xstateregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *xstateregs, size_t len) +{ + amd64_collect_xsave (regcache, regnum, xstateregs, 1); +} + +static const struct regset amd64fbsd_xstateregset = + { + NULL, + amd64fbsd_supply_xstateregset, + amd64fbsd_collect_xstateregset + }; + +/* Iterate over core file register note sections. */ + +static void +amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); + cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data); + cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), + &amd64fbsd_xstateregset, "XSAVE extended state", cb_data); +} + +static void +amd64fbsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + gdb_byte buf[8]; + int i; + + gdb_assert (regnum >= -1); + + for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++) + { + if (amd64fbsd_jmp_buf_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + read_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8); + regcache_raw_supply (regcache, i, buf); + } + } +} + +static void +amd64fbsd_collect_uthread (const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + gdb_byte buf[8]; + int i; + + gdb_assert (regnum >= -1); + + for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++) + { + if (amd64fbsd_jmp_buf_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + regcache_raw_collect (regcache, i, buf); + write_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8); + } + } +} + +static void +amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Generic FreeBSD support. */ + fbsd_init_abi (info, gdbarch); + + /* Obviously FreeBSD is BSD-based. */ + i386bsd_init_abi (info, gdbarch); + + tdep->gregset_reg_offset = amd64fbsd_r_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset); + tdep->sizeof_gregset = 22 * 8; + + amd64_init_abi (info, gdbarch); + + tdep->sigtramp_p = amd64fbsd_sigtramp_p; + tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr; + tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr; + tdep->sigcontext_addr = amd64fbsd_sigcontext_addr; + tdep->sc_reg_offset = amd64fbsd_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset); + + tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; + + /* Iterate over core file register note sections. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, amd64fbsd_iterate_over_regset_sections); + + set_gdbarch_core_read_description (gdbarch, + amd64fbsd_core_read_description); + + /* FreeBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread); + + /* FreeBSD uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_amd64fbsd_tdep (void); + +void +_initialize_amd64fbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, + GDB_OSABI_FREEBSD_ELF, amd64fbsd_init_abi); +} diff --git a/gdb/amd64-nbsd-nat.c b/gdb/amd64-nbsd-nat.c new file mode 100644 index 00000000000..97910174ddb --- /dev/null +++ b/gdb/amd64-nbsd-nat.c @@ -0,0 +1,73 @@ +/* Native-dependent code for NetBSD/amd64. + + Copyright (C) 2003-2016 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-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 */ +}; + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_amd64nbsd_nat (void); + +void +_initialize_amd64nbsd_nat (void) +{ + struct target_ops *t; + + 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 some extra features to the common *BSD/amd64 target. */ + t = amd64bsd_target (); + t->to_pid_to_exec_file = nbsd_pid_to_exec_file; + add_target (t); +} diff --git a/gdb/amd64-nbsd-tdep.c b/gdb/amd64-nbsd-tdep.c new file mode 100644 index 00000000000..9e3cb11e70c --- /dev/null +++ b/gdb/amd64-nbsd-tdep.c @@ -0,0 +1,133 @@ +/* Target-dependent code for NetBSD/amd64. + + Copyright (C) 2003-2016 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 "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); + + 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); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_amd64nbsd_tdep (void); + +void +_initialize_amd64nbsd_tdep (void) +{ + /* 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_ELF, amd64nbsd_init_abi); +} diff --git a/gdb/amd64-obsd-nat.c b/gdb/amd64-obsd-nat.c new file mode 100644 index 00000000000..7256dec89e9 --- /dev/null +++ b/gdb/amd64-obsd-nat.c @@ -0,0 +1,144 @@ +/* Native-dependent code for OpenBSD/amd64. + + Copyright (C) 2003-2016 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 "amd64-tdep.h" +#include "amd64-nat.h" +#include "obsd-nat.h" + +/* Mapping between the general-purpose registers in OpenBSD/amd64 + `struct reg' format and GDB's register cache layout for + OpenBSD/i386. + + Note that most (if not all) OpenBSD/amd64 registers are 64-bit, + while the OpenBSD/i386 registers are all 32-bit, but since we're + little-endian we get away with that. */ + +/* From . */ +static int amd64obsd32_r_reg_offset[] = +{ + 14 * 8, /* %eax */ + 3 * 8, /* %ecx */ + 2 * 8, /* %edx */ + 13 * 8, /* %ebx */ + 15 * 8, /* %esp */ + 12 * 8, /* %ebp */ + 1 * 8, /* %esi */ + 0 * 8, /* %edi */ + 16 * 8, /* %eip */ + 17 * 8, /* %eflags */ + 18 * 8, /* %cs */ + 19 * 8, /* %ss */ + 20 * 8, /* %ds */ + 21 * 8, /* %es */ + 22 * 8, /* %fs */ + 23 * 8 /* %gs */ +}; + + +/* Support for debugging kernel virtual memory images. */ + +#include +#include +#include + +#include "bsd-kvm.h" + +static int +amd64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + struct switchframe sf; + int regnum; + + /* The following is true for OpenBSD 3.5: + + The pcb contains the stack pointer 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 OpenBSD 3.5 has the + following layout: + + interrupt level + %r15 + %r14 + %r13 + %r12 + %rbp + %rbx + return address + + Together with %rsp in the pcb, this accounts for all callee-saved + registers specified by the psABI. From this information we + reconstruct the register state as it would look when we just + returned from cpu_switch(). + + For core dumps the pcb is saved by savectx(). In that case the + stack frame only contains the return address, and there is no way + to recover the other registers. */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_rsp == 0) + return 0; + + /* Read the stack frame, and check its validity. */ + read_memory (pcb->pcb_rsp, (gdb_byte *) &sf, sizeof sf); + if (sf.sf_rbp == pcb->pcb_rbp) + { + /* Yes, we have a frame that matches cpu_switch(). */ + pcb->pcb_rsp += sizeof (struct switchframe); + regcache_raw_supply (regcache, 12, &sf.sf_r12); + regcache_raw_supply (regcache, 13, &sf.sf_r13); + regcache_raw_supply (regcache, 14, &sf.sf_r14); + regcache_raw_supply (regcache, 15, &sf.sf_r15); + regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &sf.sf_rbx); + regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &sf.sf_rip); + } + else + { + /* No, the pcb must have been last updated by savectx(). */ + pcb->pcb_rsp += 8; + regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &sf); + } + + regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp); + regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_amd64obsd_nat (void); + +void +_initialize_amd64obsd_nat (void) +{ + amd64_native_gregset32_reg_offset = amd64obsd32_r_reg_offset; + amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64obsd32_r_reg_offset); + amd64_native_gregset64_reg_offset = amd64obsd_r_reg_offset; + + /* Add some extra features to the common *BSD/amd64 target. */ + obsd_add_target (amd64bsd_target ()); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (amd64obsd_supply_pcb); +} diff --git a/gdb/amd64-obsd-tdep.c b/gdb/amd64-obsd-tdep.c new file mode 100644 index 00000000000..7c79e44bdea --- /dev/null +++ b/gdb/amd64-obsd-tdep.c @@ -0,0 +1,514 @@ +/* Target-dependent code for OpenBSD/amd64. + + Copyright (C) 2003-2016 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 "frame.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "symtab.h" +#include "objfiles.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "target.h" +#include "trad-frame.h" + +#include "obsd-tdep.h" +#include "amd64-tdep.h" +#include "i387-tdep.h" +#include "solib-svr4.h" +#include "bsd-uthread.h" + +/* Support for core dumps. */ + +static void +amd64obsd_supply_regset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *regs, size_t len) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE); + + i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset); + amd64_supply_fxsave (regcache, regnum, + ((const gdb_byte *)regs) + tdep->sizeof_gregset); +} + +static const struct regset amd64obsd_combined_regset = + { + NULL, amd64obsd_supply_regset, NULL + }; + +static void +amd64obsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* OpenBSD core dumps don't use seperate register sets for the + general-purpose and floating-point registers. */ + + cb (".reg", tdep->sizeof_gregset + I387_SIZEOF_FXSAVE, + &amd64obsd_combined_regset, NULL, cb_data); +} + + +/* Support for signal handlers. */ + +/* Default page size. */ +static const int amd64obsd_page_size = 4096; + +/* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp + routine. */ + +static int +amd64obsd_sigtramp_p (struct frame_info *this_frame) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1)); + const gdb_byte osigreturn[] = + { + 0x48, 0xc7, 0xc0, + 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ + 0xcd, 0x80 /* int $0x80 */ + }; + const gdb_byte sigreturn[] = + { + 0x48, 0xc7, 0xc0, + 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ + 0x0f, 0x05 /* syscall */ + }; + size_t buflen = (sizeof sigreturn) + 1; + gdb_byte *buf; + const char *name; + + /* If the function has a valid symbol name, it isn't a + trampoline. */ + find_pc_partial_function (pc, &name, NULL, NULL); + if (name != NULL) + return 0; + + /* If the function lives in a valid section (even without a starting + point) it isn't a trampoline. */ + if (find_pc_section (pc) != NULL) + return 0; + + /* If we can't read the instructions at START_PC, return zero. */ + buf = (gdb_byte *) alloca ((sizeof sigreturn) + 1); + if (!safe_frame_unwind_memory (this_frame, start_pc + 6, buf, buflen)) + return 0; + + /* Check for sigreturn(2). Depending on how the assembler encoded + the `movq %rsp, %rdi' instruction, the code starts at offset 6 or + 7. OpenBSD 5.0 and later use the `syscall' instruction. Older + versions use `int $0x80'. Check for both. */ + if (memcmp (buf, sigreturn, sizeof sigreturn) + && memcmp (buf + 1, sigreturn, sizeof sigreturn) + && memcmp (buf, osigreturn, sizeof osigreturn) + && memcmp (buf + 1, osigreturn, sizeof osigreturn)) + return 0; + + return 1; +} + +/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the + address of the associated sigcontext structure. */ + +static CORE_ADDR +amd64obsd_sigcontext_addr (struct frame_info *this_frame) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + ULONGEST offset = (pc & (amd64obsd_page_size - 1)); + + /* The %rsp register points at `struct sigcontext' upon entry of a + signal trampoline. The relevant part of the trampoline is + + call *%rax + movq %rsp, %rdi + pushq %rdi + movq $SYS_sigreturn,%rax + int $0x80 + + (see /usr/src/sys/arch/amd64/amd64/locore.S). The `pushq' + instruction clobbers %rsp, but its value is saved in `%rdi'. */ + + if (offset > 5) + return get_frame_register_unsigned (this_frame, AMD64_RDI_REGNUM); + else + return get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); +} + +/* OpenBSD 3.5 or later. */ + +/* Mapping between the general-purpose registers in `struct reg' + format and GDB's register cache layout. */ + +/* From . */ +int amd64obsd_r_reg_offset[] = +{ + 14 * 8, /* %rax */ + 13 * 8, /* %rbx */ + 3 * 8, /* %rcx */ + 2 * 8, /* %rdx */ + 1 * 8, /* %rsi */ + 0 * 8, /* %rdi */ + 12 * 8, /* %rbp */ + 15 * 8, /* %rsp */ + 4 * 8, /* %r8 .. */ + 5 * 8, + 6 * 8, + 7 * 8, + 8 * 8, + 9 * 8, + 10 * 8, + 11 * 8, /* ... %r15 */ + 16 * 8, /* %rip */ + 17 * 8, /* %eflags */ + 18 * 8, /* %cs */ + 19 * 8, /* %ss */ + 20 * 8, /* %ds */ + 21 * 8, /* %es */ + 22 * 8, /* %fs */ + 23 * 8 /* %gs */ +}; + +/* From . */ +static int amd64obsd_sc_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 */ +}; + +/* From /usr/src/lib/libpthread/arch/amd64/uthread_machdep.c. */ +static int amd64obsd_uthread_reg_offset[] = +{ + 19 * 8, /* %rax */ + 16 * 8, /* %rbx */ + 18 * 8, /* %rcx */ + 17 * 8, /* %rdx */ + 14 * 8, /* %rsi */ + 13 * 8, /* %rdi */ + 15 * 8, /* %rbp */ + -1, /* %rsp */ + 12 * 8, /* %r8 ... */ + 11 * 8, + 10 * 8, + 9 * 8, + 8 * 8, + 7 * 8, + 6 * 8, + 5 * 8, /* ... %r15 */ + 20 * 8, /* %rip */ + 4 * 8, /* %eflags */ + 21 * 8, /* %cs */ + -1, /* %ss */ + 3 * 8, /* %ds */ + 2 * 8, /* %es */ + 1 * 8, /* %fs */ + 0 * 8 /* %gs */ +}; + +/* Offset within the thread structure where we can find the saved + stack pointer (%esp). */ +#define AMD64OBSD_UTHREAD_RSP_OFFSET 400 + +static void +amd64obsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET; + CORE_ADDR sp = 0; + gdb_byte buf[8]; + int i; + + gdb_assert (regnum >= -1); + + if (regnum == -1 || regnum == AMD64_RSP_REGNUM) + { + int offset; + + /* Fetch stack pointer from thread structure. */ + sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); + + /* Adjust the stack pointer such that it looks as if we just + returned from _thread_machdep_switch. */ + offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8; + store_unsigned_integer (buf, 8, byte_order, sp + offset); + regcache_raw_supply (regcache, AMD64_RSP_REGNUM, buf); + } + + for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++) + { + if (amd64obsd_uthread_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + /* Fetch stack pointer from thread structure (if we didn't + do so already). */ + if (sp == 0) + sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); + + /* Read the saved register from the stack frame. */ + read_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); + regcache_raw_supply (regcache, i, buf); + } + } +} + +static void +amd64obsd_collect_uthread (const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET; + CORE_ADDR sp = 0; + gdb_byte buf[8]; + int i; + + gdb_assert (regnum >= -1); + + if (regnum == -1 || regnum == AMD64_RSP_REGNUM) + { + int offset; + + /* Calculate the stack pointer (frame pointer) that will be + stored into the thread structure. */ + offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8; + regcache_raw_collect (regcache, AMD64_RSP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 8, byte_order) - offset; + + /* Store the stack pointer. */ + write_memory_unsigned_integer (sp_addr, 8, byte_order, sp); + + /* The stack pointer was (potentially) modified. Make sure we + build a proper stack frame. */ + regnum = -1; + } + + for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++) + { + if (amd64obsd_uthread_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + /* Fetch stack pointer from thread structure (if we didn't + calculate it already). */ + if (sp == 0) + sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); + + /* Write the register into the stack frame. */ + regcache_raw_collect (regcache, i, buf); + write_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); + } + } +} +/* Kernel debugging support. */ + +/* From . Easy since `struct trapframe' matches + `struct sigcontext'. */ +#define amd64obsd_tf_reg_offset amd64obsd_sc_reg_offset + +static struct trad_frame_cache * +amd64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct trad_frame_cache *cache; + CORE_ADDR func, sp, addr; + ULONGEST cs; + const char *name; + int i; + + if (*this_cache) + return (struct trad_frame_cache *) *this_cache; + + cache = trad_frame_cache_zalloc (this_frame); + *this_cache = cache; + + func = get_frame_func (this_frame); + sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); + + find_pc_partial_function (func, &name, NULL, NULL); + if (name && startswith (name, "Xintr")) + addr = sp + 8; /* It's an interrupt frame. */ + else + addr = sp; + + for (i = 0; i < ARRAY_SIZE (amd64obsd_tf_reg_offset); i++) + if (amd64obsd_tf_reg_offset[i] != -1) + trad_frame_set_reg_addr (cache, i, addr + amd64obsd_tf_reg_offset[i]); + + /* Read %cs from trap frame. */ + addr += amd64obsd_tf_reg_offset[AMD64_CS_REGNUM]; + cs = read_memory_unsigned_integer (addr, 8, byte_order); + if ((cs & I386_SEL_RPL) == I386_SEL_UPL) + { + /* Trap from user space; terminate backtrace. */ + trad_frame_set_id (cache, outer_frame_id); + } + else + { + /* Construct the frame ID using the function start. */ + trad_frame_set_id (cache, frame_id_build (sp + 16, func)); + } + + return cache; +} + +static void +amd64obsd_trapframe_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + struct trad_frame_cache *cache = + amd64obsd_trapframe_cache (this_frame, this_cache); + + trad_frame_get_id (cache, this_id); +} + +static struct value * +amd64obsd_trapframe_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct trad_frame_cache *cache = + amd64obsd_trapframe_cache (this_frame, this_cache); + + return trad_frame_get_register (cache, this_frame, regnum); +} + +static int +amd64obsd_trapframe_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + ULONGEST cs; + const char *name; + + /* Check Current Privilege Level and bail out if we're not executing + in kernel space. */ + cs = get_frame_register_unsigned (this_frame, AMD64_CS_REGNUM); + if ((cs & I386_SEL_RPL) == I386_SEL_UPL) + return 0; + + find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL); + return (name && ((strcmp (name, "calltrap") == 0) + || (strcmp (name, "osyscall1") == 0) + || (strcmp (name, "Xsyscall") == 0) + || (startswith (name, "Xintr")))); +} + +static const struct frame_unwind amd64obsd_trapframe_unwind = { + /* FIXME: kettenis/20051219: This really is more like an interrupt + frame, but SIGTRAMP_FRAME would print , + which really is not what we want here. */ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + amd64obsd_trapframe_this_id, + amd64obsd_trapframe_prev_register, + NULL, + amd64obsd_trapframe_sniffer +}; + + +static void +amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + amd64_init_abi (info, gdbarch); + obsd_init_abi (info, gdbarch); + + /* Initialize general-purpose register set details. */ + tdep->gregset_reg_offset = amd64obsd_r_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_r_reg_offset); + tdep->sizeof_gregset = 24 * 8; + + tdep->jb_pc_offset = 7 * 8; + + tdep->sigtramp_p = amd64obsd_sigtramp_p; + tdep->sigcontext_addr = amd64obsd_sigcontext_addr; + tdep->sc_reg_offset = amd64obsd_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset); + + /* OpenBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, amd64obsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread); + + /* OpenBSD uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); + + /* Unwind kernel trap frames correctly. */ + frame_unwind_prepend_unwinder (gdbarch, &amd64obsd_trapframe_unwind); +} + +/* Traditional (a.out) NetBSD-style core dumps. */ + +static void +amd64obsd_core_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + amd64obsd_init_abi (info, gdbarch); + + set_gdbarch_iterate_over_regset_sections + (gdbarch, amd64obsd_iterate_over_regset_sections); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_amd64obsd_tdep (void); + +void +_initialize_amd64obsd_tdep (void) +{ + /* The OpenBSD/amd64 native dependent code makes this assumption. */ + gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS); + + gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, + GDB_OSABI_OPENBSD_ELF, amd64obsd_init_abi); + + /* OpenBSD uses traditional (a.out) NetBSD-style core dumps. */ + gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, + GDB_OSABI_NETBSD_AOUT, amd64obsd_core_init_abi); +} diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h index 2691e99e87f..fa30648265e 100644 --- a/gdb/amd64-tdep.h +++ b/gdb/amd64-tdep.h @@ -128,13 +128,13 @@ extern const struct regset amd64_fpregset; /* Variables exported from amd64-linux-tdep.c. */ extern int amd64_linux_gregset_reg_offset[]; -/* Variables exported from amd64nbsd-tdep.c. */ +/* Variables exported from amd64-nbsd-tdep.c. */ extern int amd64nbsd_r_reg_offset[]; -/* Variables exported from amd64obsd-tdep.c. */ +/* Variables exported from amd64-obsd-tdep.c. */ extern int amd64obsd_r_reg_offset[]; -/* Variables exported from amd64fbsd-tdep.c. */ +/* Variables exported from amd64-fbsd-tdep.c. */ extern CORE_ADDR amd64fbsd_sigtramp_start_addr; extern CORE_ADDR amd64fbsd_sigtramp_end_addr; extern int amd64fbsd_sc_reg_offset[]; diff --git a/gdb/amd64bsd-nat.c b/gdb/amd64bsd-nat.c deleted file mode 100644 index b87672ac72a..00000000000 --- a/gdb/amd64bsd-nat.c +++ /dev/null @@ -1,159 +0,0 @@ -/* Native-dependent code for AMD64 BSD's. - - Copyright (C) 2003-2016 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 "target.h" - -/* We include to make sure `struct fxsave64' is defined on - NetBSD, since NetBSD's needs it. */ -#include -#include -#include -#include - -#include "amd64-tdep.h" -#include "amd64-nat.h" -#include "x86bsd-nat.h" -#include "inf-ptrace.h" - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers (including the floating-point registers). */ - -static void -amd64bsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - amd64_supply_native_gregset (regcache, ®s, -1); - if (regnum != -1) - return; - } - - if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) - { - struct fpreg fpregs; -#ifdef PT_GETXSTATE_INFO - void *xstateregs; - - if (x86bsd_xsave_len != 0) - { - xstateregs = alloca (x86bsd_xsave_len); - if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) - perror_with_name (_("Couldn't get extended state status")); - - amd64_supply_xsave (regcache, -1, xstateregs); - return; - } -#endif - - if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - amd64_supply_fxsave (regcache, -1, &fpregs); - } -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers (including the floating-point registers). */ - -static void -amd64bsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - amd64_collect_native_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - - if (regnum != -1) - return; - } - - if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) - { - struct fpreg fpregs; -#ifdef PT_GETXSTATE_INFO - void *xstateregs; - - if (x86bsd_xsave_len != 0) - { - xstateregs = alloca (x86bsd_xsave_len); - if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) - perror_with_name (_("Couldn't get extended state status")); - - amd64_collect_xsave (regcache, regnum, xstateregs, 0); - - if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, x86bsd_xsave_len) == -1) - perror_with_name (_("Couldn't write extended state status")); - return; - } -#endif - - if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - amd64_collect_fxsave (regcache, regnum, &fpregs); - - if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - -/* Create a prototype *BSD/amd64 target. The client can override it - with local methods. */ - -struct target_ops * -amd64bsd_target (void) -{ - struct target_ops *t; - - t = x86bsd_target (); - t->to_fetch_registers = amd64bsd_fetch_inferior_registers; - t->to_store_registers = amd64bsd_store_inferior_registers; - return t; -} diff --git a/gdb/amd64fbsd-nat.c b/gdb/amd64fbsd-nat.c deleted file mode 100644 index 66c374c22b7..00000000000 --- a/gdb/amd64fbsd-nat.c +++ /dev/null @@ -1,291 +0,0 @@ -/* Native-dependent code for FreeBSD/amd64. - - Copyright (C) 2003-2016 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 "target.h" - -#include -#include -#include -#include -#include -#include - -#include "fbsd-nat.h" -#include "amd64-tdep.h" -#include "amd64-nat.h" -#include "x86bsd-nat.h" -#include "x86-nat.h" - - -/* Offset in `struct reg' where MEMBER is stored. */ -#define REG_OFFSET(member) offsetof (struct reg, member) - -/* At amd64fbsd64_r_reg_offset[REGNUM] you'll find the offset in - `struct reg' location where the GDB register REGNUM is stored. - Unsupported registers are marked with `-1'. */ -static int amd64fbsd64_r_reg_offset[] = -{ - REG_OFFSET (r_rax), - REG_OFFSET (r_rbx), - REG_OFFSET (r_rcx), - REG_OFFSET (r_rdx), - REG_OFFSET (r_rsi), - REG_OFFSET (r_rdi), - REG_OFFSET (r_rbp), - REG_OFFSET (r_rsp), - REG_OFFSET (r_r8), - REG_OFFSET (r_r9), - REG_OFFSET (r_r10), - REG_OFFSET (r_r11), - REG_OFFSET (r_r12), - REG_OFFSET (r_r13), - REG_OFFSET (r_r14), - REG_OFFSET (r_r15), - REG_OFFSET (r_rip), - REG_OFFSET (r_rflags), - REG_OFFSET (r_cs), - REG_OFFSET (r_ss), - -1, - -1, - -1, - -1 -}; - - -/* Mapping between the general-purpose registers in FreeBSD/amd64 - `struct reg' format and GDB's register cache layout for - FreeBSD/i386. - - Note that most FreeBSD/amd64 registers are 64-bit, while the - FreeBSD/i386 registers are all 32-bit, but since we're - little-endian we get away with that. */ - -/* From . */ -static int amd64fbsd32_r_reg_offset[I386_NUM_GREGS] = -{ - 14 * 8, 13 * 8, /* %eax, %ecx */ - 12 * 8, 11 * 8, /* %edx, %ebx */ - 20 * 8, 10 * 8, /* %esp, %ebp */ - 9 * 8, 8 * 8, /* %esi, %edi */ - 17 * 8, 19 * 8, /* %eip, %eflags */ - 18 * 8, 21 * 8, /* %cs, %ss */ - -1, -1, -1, -1 /* %ds, %es, %fs, %gs */ -}; - - -/* Support for debugging kernel virtual memory images. */ - -#include -#include - -#include "bsd-kvm.h" - -static int -amd64fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - /* The following is true for FreeBSD 5.2: - - The pcb contains %rip, %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, - %ds, %es, %fs and %gs. This accounts for all callee-saved - registers specified by the psABI and then some. Here %esp - contains the stack pointer at the point just after the call to - cpu_switch(). From this information we reconstruct the register - state as it would like when we just returned from cpu_switch(). */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_rsp == 0) - return 0; - - pcb->pcb_rsp += 8; - regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &pcb->pcb_rip); - regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &pcb->pcb_rbx); - regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp); - regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp); - regcache_raw_supply (regcache, 12, &pcb->pcb_r12); - regcache_raw_supply (regcache, 13, &pcb->pcb_r13); - regcache_raw_supply (regcache, 14, &pcb->pcb_r14); - regcache_raw_supply (regcache, 15, &pcb->pcb_r15); -#if (__FreeBSD_version < 800075) && (__FreeBSD_kernel_version < 800075) - /* struct pcb provides the pcb_ds/pcb_es/pcb_fs/pcb_gs fields only - up until __FreeBSD_version 800074: The removal of these fields - occurred on 2009-04-01 while the __FreeBSD_version number was - bumped to 800075 on 2009-04-06. So 800075 is the closest version - number where we should not try to access these fields. */ - regcache_raw_supply (regcache, AMD64_DS_REGNUM, &pcb->pcb_ds); - regcache_raw_supply (regcache, AMD64_ES_REGNUM, &pcb->pcb_es); - regcache_raw_supply (regcache, AMD64_FS_REGNUM, &pcb->pcb_fs); - regcache_raw_supply (regcache, AMD64_GS_REGNUM, &pcb->pcb_gs); -#endif - - return 1; -} - - -/* Implement the to_read_description method. */ - -static const struct target_desc * -amd64fbsd_read_description (struct target_ops *ops) -{ -#ifdef PT_GETXSTATE_INFO - static int xsave_probed; - static uint64_t xcr0; -#endif - struct reg regs; - int is64; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - is64 = (regs.r_cs == GSEL (GUCODE_SEL, SEL_UPL)); -#ifdef PT_GETXSTATE_INFO - if (!xsave_probed) - { - struct ptrace_xstate_info info; - - if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) - { - x86bsd_xsave_len = info.xsave_len; - xcr0 = info.xsave_mask; - } - xsave_probed = 1; - } - - if (x86bsd_xsave_len != 0) - { - if (is64) - return amd64_target_description (xcr0); - else - return i386_target_description (xcr0); - } -#endif - if (is64) - return tdesc_amd64; - else - return tdesc_i386; -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_amd64fbsd_nat (void); - -void -_initialize_amd64fbsd_nat (void) -{ - struct target_ops *t; - int offset; - - amd64_native_gregset32_reg_offset = amd64fbsd32_r_reg_offset; - amd64_native_gregset64_reg_offset = amd64fbsd64_r_reg_offset; - - /* Add some extra features to the common *BSD/i386 target. */ - t = amd64bsd_target (); - t->to_read_description = amd64fbsd_read_description; - - fbsd_nat_add_target (t); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (amd64fbsd_supply_pcb); - - /* To support the recognition of signal handlers, i386bsd-tdep.c - hardcodes some constants. Inclusion of this file means that we - are compiling a native debugger, which means that we can use the - system header files and sysctl(3) to get at the relevant - information. */ - -#define SC_REG_OFFSET amd64fbsd_sc_reg_offset - - /* We only check the program counter, stack pointer and frame - pointer since these members of `struct sigcontext' are essential - for providing backtraces. */ - -#define SC_RIP_OFFSET SC_REG_OFFSET[AMD64_RIP_REGNUM] -#define SC_RSP_OFFSET SC_REG_OFFSET[AMD64_RSP_REGNUM] -#define SC_RBP_OFFSET SC_REG_OFFSET[AMD64_RBP_REGNUM] - - /* Override the default value for the offset of the program counter - in the sigcontext structure. */ - offset = offsetof (struct sigcontext, sc_rip); - - if (SC_RIP_OFFSET != offset) - { - warning (_("\ -offsetof (struct sigcontext, sc_rip) yields %d instead of %d.\n\ -Please report this to ."), - offset, SC_RIP_OFFSET); - } - - SC_RIP_OFFSET = offset; - - /* Likewise for the stack pointer. */ - offset = offsetof (struct sigcontext, sc_rsp); - - if (SC_RSP_OFFSET != offset) - { - warning (_("\ -offsetof (struct sigcontext, sc_rsp) yields %d instead of %d.\n\ -Please report this to ."), - offset, SC_RSP_OFFSET); - } - - SC_RSP_OFFSET = offset; - - /* And the frame pointer. */ - offset = offsetof (struct sigcontext, sc_rbp); - - if (SC_RBP_OFFSET != offset) - { - warning (_("\ -offsetof (struct sigcontext, sc_rbp) yields %d instead of %d.\n\ -Please report this to ."), - offset, SC_RBP_OFFSET); - } - - SC_RBP_OFFSET = offset; - -#ifdef KERN_PROC_SIGTRAMP - /* Normally signal frames are detected via amd64fbsd_sigtramp_p. - However, FreeBSD 9.2 through 10.1 do not include the page holding - the signal code in core dumps. These releases do provide a - kern.proc.sigtramp. sysctl that returns the location of the - signal trampoline for a running process. We fetch the location - of the current (gdb) process and use this to identify signal - frames in core dumps from these releases. Note that this only - works for core dumps of 64-bit (FreeBSD/amd64) processes and does - not handle core dumps of 32-bit (FreeBSD/i386) processes. */ - { - int mib[4]; - struct kinfo_sigtramp kst; - size_t len; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_SIGTRAMP; - mib[3] = getpid (); - len = sizeof (kst); - if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) - { - amd64fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start; - amd64fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end; - } - } -#endif -} diff --git a/gdb/amd64fbsd-tdep.c b/gdb/amd64fbsd-tdep.c deleted file mode 100644 index dd71066c669..00000000000 --- a/gdb/amd64fbsd-tdep.c +++ /dev/null @@ -1,319 +0,0 @@ -/* Target-dependent code for FreeBSD/amd64. - - Copyright (C) 2003-2016 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 "osabi.h" -#include "regset.h" -#include "i386fbsd-tdep.h" -#include "x86-xstate.h" - -#include "amd64-tdep.h" -#include "bsd-uthread.h" -#include "fbsd-tdep.h" -#include "solib-svr4.h" - -/* Support for signal handlers. */ - -/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp - routine. */ - -static const gdb_byte amd64fbsd_sigtramp_code[] = -{ - 0x48, 0x8d, 0x7c, 0x24, 0x10, /* lea SIGF_UC(%rsp),%rdi */ - 0x6a, 0x00, /* pushq $0 */ - 0x48, 0xc7, 0xc0, 0xa1, 0x01, 0x00, 0x00, - /* movq $SYS_sigreturn,%rax */ - 0x0f, 0x05 /* syscall */ -}; - -static int -amd64fbsd_sigtramp_p (struct frame_info *this_frame) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - gdb_byte buf[sizeof amd64fbsd_sigtramp_code]; - - if (!safe_frame_unwind_memory (this_frame, pc, buf, sizeof buf)) - return 0; - if (memcmp (buf, amd64fbsd_sigtramp_code, sizeof amd64fbsd_sigtramp_code) - != 0) - return 0; - - return 1; -} - -/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the - address of the associated sigcontext structure. */ - -static CORE_ADDR -amd64fbsd_sigcontext_addr (struct frame_info *this_frame) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp; - gdb_byte buf[8]; - - /* The `struct sigcontext' (which really is an `ucontext_t' on - FreeBSD/amd64) lives at a fixed offset in the signal frame. See - . */ - get_frame_register (this_frame, AMD64_RSP_REGNUM, buf); - sp = extract_unsigned_integer (buf, 8, byte_order); - return sp + 16; -} - -/* FreeBSD 5.1-RELEASE or later. */ - -/* Mapping between the general-purpose registers in `struct reg' - format and GDB's register cache layout. - - Note that some registers are 32-bit, but since we're little-endian - we get away with that. */ - -/* From . */ -static int amd64fbsd_r_reg_offset[] = -{ - 14 * 8, /* %rax */ - 11 * 8, /* %rbx */ - 13 * 8, /* %rcx */ - 12 * 8, /* %rdx */ - 9 * 8, /* %rsi */ - 8 * 8, /* %rdi */ - 10 * 8, /* %rbp */ - 20 * 8, /* %rsp */ - 7 * 8, /* %r8 ... */ - 6 * 8, - 5 * 8, - 4 * 8, - 3 * 8, - 2 * 8, - 1 * 8, - 0 * 8, /* ... %r15 */ - 17 * 8, /* %rip */ - 19 * 8, /* %eflags */ - 18 * 8, /* %cs */ - 21 * 8, /* %ss */ - -1, /* %ds */ - -1, /* %es */ - -1, /* %fs */ - -1 /* %gs */ -}; - -/* Location of the signal trampoline. */ -CORE_ADDR amd64fbsd_sigtramp_start_addr; -CORE_ADDR amd64fbsd_sigtramp_end_addr; - -/* From . */ -int amd64fbsd_sc_reg_offset[] = -{ - 24 + 6 * 8, /* %rax */ - 24 + 7 * 8, /* %rbx */ - 24 + 3 * 8, /* %rcx */ - 24 + 2 * 8, /* %rdx */ - 24 + 1 * 8, /* %rsi */ - 24 + 0 * 8, /* %rdi */ - 24 + 8 * 8, /* %rbp */ - 24 + 22 * 8, /* %rsp */ - 24 + 4 * 8, /* %r8 ... */ - 24 + 5 * 8, - 24 + 9 * 8, - 24 + 10 * 8, - 24 + 11 * 8, - 24 + 12 * 8, - 24 + 13 * 8, - 24 + 14 * 8, /* ... %r15 */ - 24 + 19 * 8, /* %rip */ - 24 + 21 * 8, /* %eflags */ - 24 + 20 * 8, /* %cs */ - 24 + 23 * 8, /* %ss */ - -1, /* %ds */ - -1, /* %es */ - -1, /* %fs */ - -1 /* %gs */ -}; - -/* From /usr/src/lib/libc/amd64/gen/_setjmp.S. */ -static int amd64fbsd_jmp_buf_reg_offset[] = -{ - -1, /* %rax */ - 1 * 8, /* %rbx */ - -1, /* %rcx */ - -1, /* %rdx */ - -1, /* %rsi */ - -1, /* %rdi */ - 3 * 8, /* %rbp */ - 2 * 8, /* %rsp */ - -1, /* %r8 ... */ - -1, - -1, - -1, /* ... %r11 */ - 4 * 8, /* %r12 ... */ - 5 * 8, - 6 * 8, - 7 * 8, /* ... %r15 */ - 0 * 8 /* %rip */ -}; - -/* Implement the core_read_description gdbarch method. */ - -static const struct target_desc * -amd64fbsd_core_read_description (struct gdbarch *gdbarch, - struct target_ops *target, - bfd *abfd) -{ - return amd64_target_description (i386fbsd_core_read_xcr0 (abfd)); -} - -/* Similar to amd64_supply_fpregset, but use XSAVE extended state. */ - -static void -amd64fbsd_supply_xstateregset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *xstateregs, size_t len) -{ - amd64_supply_xsave (regcache, regnum, xstateregs); -} - -/* Similar to amd64_collect_fpregset, but use XSAVE extended state. */ - -static void -amd64fbsd_collect_xstateregset (const struct regset *regset, - const struct regcache *regcache, - int regnum, void *xstateregs, size_t len) -{ - amd64_collect_xsave (regcache, regnum, xstateregs, 1); -} - -static const struct regset amd64fbsd_xstateregset = - { - NULL, - amd64fbsd_supply_xstateregset, - amd64fbsd_collect_xstateregset - }; - -/* Iterate over core file register note sections. */ - -static void -amd64fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); - cb (".reg2", tdep->sizeof_fpregset, &amd64_fpregset, NULL, cb_data); - cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), - &amd64fbsd_xstateregset, "XSAVE extended state", cb_data); -} - -static void -amd64fbsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[8]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++) - { - if (amd64fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - read_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8); - regcache_raw_supply (regcache, i, buf); - } - } -} - -static void -amd64fbsd_collect_uthread (const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[8]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (amd64fbsd_jmp_buf_reg_offset); i++) - { - if (amd64fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - regcache_raw_collect (regcache, i, buf); - write_memory (addr + amd64fbsd_jmp_buf_reg_offset[i], buf, 8); - } - } -} - -static void -amd64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Generic FreeBSD support. */ - fbsd_init_abi (info, gdbarch); - - /* Obviously FreeBSD is BSD-based. */ - i386bsd_init_abi (info, gdbarch); - - tdep->gregset_reg_offset = amd64fbsd_r_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (amd64fbsd_r_reg_offset); - tdep->sizeof_gregset = 22 * 8; - - amd64_init_abi (info, gdbarch); - - tdep->sigtramp_p = amd64fbsd_sigtramp_p; - tdep->sigtramp_start = amd64fbsd_sigtramp_start_addr; - tdep->sigtramp_end = amd64fbsd_sigtramp_end_addr; - tdep->sigcontext_addr = amd64fbsd_sigcontext_addr; - tdep->sc_reg_offset = amd64fbsd_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (amd64fbsd_sc_reg_offset); - - tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; - - /* Iterate over core file register note sections. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, amd64fbsd_iterate_over_regset_sections); - - set_gdbarch_core_read_description (gdbarch, - amd64fbsd_core_read_description); - - /* FreeBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, amd64fbsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, amd64fbsd_collect_uthread); - - /* FreeBSD uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_amd64fbsd_tdep (void); - -void -_initialize_amd64fbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, - GDB_OSABI_FREEBSD_ELF, amd64fbsd_init_abi); -} diff --git a/gdb/amd64nbsd-nat.c b/gdb/amd64nbsd-nat.c deleted file mode 100644 index 97910174ddb..00000000000 --- a/gdb/amd64nbsd-nat.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Native-dependent code for NetBSD/amd64. - - Copyright (C) 2003-2016 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-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 */ -}; - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_amd64nbsd_nat (void); - -void -_initialize_amd64nbsd_nat (void) -{ - struct target_ops *t; - - 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 some extra features to the common *BSD/amd64 target. */ - t = amd64bsd_target (); - t->to_pid_to_exec_file = nbsd_pid_to_exec_file; - add_target (t); -} diff --git a/gdb/amd64nbsd-tdep.c b/gdb/amd64nbsd-tdep.c deleted file mode 100644 index 9e3cb11e70c..00000000000 --- a/gdb/amd64nbsd-tdep.c +++ /dev/null @@ -1,133 +0,0 @@ -/* Target-dependent code for NetBSD/amd64. - - Copyright (C) 2003-2016 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 "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); - - 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); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_amd64nbsd_tdep (void); - -void -_initialize_amd64nbsd_tdep (void) -{ - /* 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_ELF, amd64nbsd_init_abi); -} diff --git a/gdb/amd64obsd-nat.c b/gdb/amd64obsd-nat.c deleted file mode 100644 index 7256dec89e9..00000000000 --- a/gdb/amd64obsd-nat.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Native-dependent code for OpenBSD/amd64. - - Copyright (C) 2003-2016 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 "amd64-tdep.h" -#include "amd64-nat.h" -#include "obsd-nat.h" - -/* Mapping between the general-purpose registers in OpenBSD/amd64 - `struct reg' format and GDB's register cache layout for - OpenBSD/i386. - - Note that most (if not all) OpenBSD/amd64 registers are 64-bit, - while the OpenBSD/i386 registers are all 32-bit, but since we're - little-endian we get away with that. */ - -/* From . */ -static int amd64obsd32_r_reg_offset[] = -{ - 14 * 8, /* %eax */ - 3 * 8, /* %ecx */ - 2 * 8, /* %edx */ - 13 * 8, /* %ebx */ - 15 * 8, /* %esp */ - 12 * 8, /* %ebp */ - 1 * 8, /* %esi */ - 0 * 8, /* %edi */ - 16 * 8, /* %eip */ - 17 * 8, /* %eflags */ - 18 * 8, /* %cs */ - 19 * 8, /* %ss */ - 20 * 8, /* %ds */ - 21 * 8, /* %es */ - 22 * 8, /* %fs */ - 23 * 8 /* %gs */ -}; - - -/* Support for debugging kernel virtual memory images. */ - -#include -#include -#include - -#include "bsd-kvm.h" - -static int -amd64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - struct switchframe sf; - int regnum; - - /* The following is true for OpenBSD 3.5: - - The pcb contains the stack pointer 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 OpenBSD 3.5 has the - following layout: - - interrupt level - %r15 - %r14 - %r13 - %r12 - %rbp - %rbx - return address - - Together with %rsp in the pcb, this accounts for all callee-saved - registers specified by the psABI. From this information we - reconstruct the register state as it would look when we just - returned from cpu_switch(). - - For core dumps the pcb is saved by savectx(). In that case the - stack frame only contains the return address, and there is no way - to recover the other registers. */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_rsp == 0) - return 0; - - /* Read the stack frame, and check its validity. */ - read_memory (pcb->pcb_rsp, (gdb_byte *) &sf, sizeof sf); - if (sf.sf_rbp == pcb->pcb_rbp) - { - /* Yes, we have a frame that matches cpu_switch(). */ - pcb->pcb_rsp += sizeof (struct switchframe); - regcache_raw_supply (regcache, 12, &sf.sf_r12); - regcache_raw_supply (regcache, 13, &sf.sf_r13); - regcache_raw_supply (regcache, 14, &sf.sf_r14); - regcache_raw_supply (regcache, 15, &sf.sf_r15); - regcache_raw_supply (regcache, AMD64_RBX_REGNUM, &sf.sf_rbx); - regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &sf.sf_rip); - } - else - { - /* No, the pcb must have been last updated by savectx(). */ - pcb->pcb_rsp += 8; - regcache_raw_supply (regcache, AMD64_RIP_REGNUM, &sf); - } - - regcache_raw_supply (regcache, AMD64_RSP_REGNUM, &pcb->pcb_rsp); - regcache_raw_supply (regcache, AMD64_RBP_REGNUM, &pcb->pcb_rbp); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_amd64obsd_nat (void); - -void -_initialize_amd64obsd_nat (void) -{ - amd64_native_gregset32_reg_offset = amd64obsd32_r_reg_offset; - amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64obsd32_r_reg_offset); - amd64_native_gregset64_reg_offset = amd64obsd_r_reg_offset; - - /* Add some extra features to the common *BSD/amd64 target. */ - obsd_add_target (amd64bsd_target ()); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (amd64obsd_supply_pcb); -} diff --git a/gdb/amd64obsd-tdep.c b/gdb/amd64obsd-tdep.c deleted file mode 100644 index 7c79e44bdea..00000000000 --- a/gdb/amd64obsd-tdep.c +++ /dev/null @@ -1,514 +0,0 @@ -/* Target-dependent code for OpenBSD/amd64. - - Copyright (C) 2003-2016 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 "frame.h" -#include "frame-unwind.h" -#include "gdbcore.h" -#include "symtab.h" -#include "objfiles.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "target.h" -#include "trad-frame.h" - -#include "obsd-tdep.h" -#include "amd64-tdep.h" -#include "i387-tdep.h" -#include "solib-svr4.h" -#include "bsd-uthread.h" - -/* Support for core dumps. */ - -static void -amd64obsd_supply_regset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *regs, size_t len) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FXSAVE); - - i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset); - amd64_supply_fxsave (regcache, regnum, - ((const gdb_byte *)regs) + tdep->sizeof_gregset); -} - -static const struct regset amd64obsd_combined_regset = - { - NULL, amd64obsd_supply_regset, NULL - }; - -static void -amd64obsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* OpenBSD core dumps don't use seperate register sets for the - general-purpose and floating-point registers. */ - - cb (".reg", tdep->sizeof_gregset + I387_SIZEOF_FXSAVE, - &amd64obsd_combined_regset, NULL, cb_data); -} - - -/* Support for signal handlers. */ - -/* Default page size. */ -static const int amd64obsd_page_size = 4096; - -/* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp - routine. */ - -static int -amd64obsd_sigtramp_p (struct frame_info *this_frame) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1)); - const gdb_byte osigreturn[] = - { - 0x48, 0xc7, 0xc0, - 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ - 0xcd, 0x80 /* int $0x80 */ - }; - const gdb_byte sigreturn[] = - { - 0x48, 0xc7, 0xc0, - 0x67, 0x00, 0x00, 0x00, /* movq $SYS_sigreturn, %rax */ - 0x0f, 0x05 /* syscall */ - }; - size_t buflen = (sizeof sigreturn) + 1; - gdb_byte *buf; - const char *name; - - /* If the function has a valid symbol name, it isn't a - trampoline. */ - find_pc_partial_function (pc, &name, NULL, NULL); - if (name != NULL) - return 0; - - /* If the function lives in a valid section (even without a starting - point) it isn't a trampoline. */ - if (find_pc_section (pc) != NULL) - return 0; - - /* If we can't read the instructions at START_PC, return zero. */ - buf = (gdb_byte *) alloca ((sizeof sigreturn) + 1); - if (!safe_frame_unwind_memory (this_frame, start_pc + 6, buf, buflen)) - return 0; - - /* Check for sigreturn(2). Depending on how the assembler encoded - the `movq %rsp, %rdi' instruction, the code starts at offset 6 or - 7. OpenBSD 5.0 and later use the `syscall' instruction. Older - versions use `int $0x80'. Check for both. */ - if (memcmp (buf, sigreturn, sizeof sigreturn) - && memcmp (buf + 1, sigreturn, sizeof sigreturn) - && memcmp (buf, osigreturn, sizeof osigreturn) - && memcmp (buf + 1, osigreturn, sizeof osigreturn)) - return 0; - - return 1; -} - -/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the - address of the associated sigcontext structure. */ - -static CORE_ADDR -amd64obsd_sigcontext_addr (struct frame_info *this_frame) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - ULONGEST offset = (pc & (amd64obsd_page_size - 1)); - - /* The %rsp register points at `struct sigcontext' upon entry of a - signal trampoline. The relevant part of the trampoline is - - call *%rax - movq %rsp, %rdi - pushq %rdi - movq $SYS_sigreturn,%rax - int $0x80 - - (see /usr/src/sys/arch/amd64/amd64/locore.S). The `pushq' - instruction clobbers %rsp, but its value is saved in `%rdi'. */ - - if (offset > 5) - return get_frame_register_unsigned (this_frame, AMD64_RDI_REGNUM); - else - return get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); -} - -/* OpenBSD 3.5 or later. */ - -/* Mapping between the general-purpose registers in `struct reg' - format and GDB's register cache layout. */ - -/* From . */ -int amd64obsd_r_reg_offset[] = -{ - 14 * 8, /* %rax */ - 13 * 8, /* %rbx */ - 3 * 8, /* %rcx */ - 2 * 8, /* %rdx */ - 1 * 8, /* %rsi */ - 0 * 8, /* %rdi */ - 12 * 8, /* %rbp */ - 15 * 8, /* %rsp */ - 4 * 8, /* %r8 .. */ - 5 * 8, - 6 * 8, - 7 * 8, - 8 * 8, - 9 * 8, - 10 * 8, - 11 * 8, /* ... %r15 */ - 16 * 8, /* %rip */ - 17 * 8, /* %eflags */ - 18 * 8, /* %cs */ - 19 * 8, /* %ss */ - 20 * 8, /* %ds */ - 21 * 8, /* %es */ - 22 * 8, /* %fs */ - 23 * 8 /* %gs */ -}; - -/* From . */ -static int amd64obsd_sc_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 */ -}; - -/* From /usr/src/lib/libpthread/arch/amd64/uthread_machdep.c. */ -static int amd64obsd_uthread_reg_offset[] = -{ - 19 * 8, /* %rax */ - 16 * 8, /* %rbx */ - 18 * 8, /* %rcx */ - 17 * 8, /* %rdx */ - 14 * 8, /* %rsi */ - 13 * 8, /* %rdi */ - 15 * 8, /* %rbp */ - -1, /* %rsp */ - 12 * 8, /* %r8 ... */ - 11 * 8, - 10 * 8, - 9 * 8, - 8 * 8, - 7 * 8, - 6 * 8, - 5 * 8, /* ... %r15 */ - 20 * 8, /* %rip */ - 4 * 8, /* %eflags */ - 21 * 8, /* %cs */ - -1, /* %ss */ - 3 * 8, /* %ds */ - 2 * 8, /* %es */ - 1 * 8, /* %fs */ - 0 * 8 /* %gs */ -}; - -/* Offset within the thread structure where we can find the saved - stack pointer (%esp). */ -#define AMD64OBSD_UTHREAD_RSP_OFFSET 400 - -static void -amd64obsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET; - CORE_ADDR sp = 0; - gdb_byte buf[8]; - int i; - - gdb_assert (regnum >= -1); - - if (regnum == -1 || regnum == AMD64_RSP_REGNUM) - { - int offset; - - /* Fetch stack pointer from thread structure. */ - sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); - - /* Adjust the stack pointer such that it looks as if we just - returned from _thread_machdep_switch. */ - offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8; - store_unsigned_integer (buf, 8, byte_order, sp + offset); - regcache_raw_supply (regcache, AMD64_RSP_REGNUM, buf); - } - - for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++) - { - if (amd64obsd_uthread_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - /* Fetch stack pointer from thread structure (if we didn't - do so already). */ - if (sp == 0) - sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); - - /* Read the saved register from the stack frame. */ - read_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); - regcache_raw_supply (regcache, i, buf); - } - } -} - -static void -amd64obsd_collect_uthread (const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp_addr = addr + AMD64OBSD_UTHREAD_RSP_OFFSET; - CORE_ADDR sp = 0; - gdb_byte buf[8]; - int i; - - gdb_assert (regnum >= -1); - - if (regnum == -1 || regnum == AMD64_RSP_REGNUM) - { - int offset; - - /* Calculate the stack pointer (frame pointer) that will be - stored into the thread structure. */ - offset = amd64obsd_uthread_reg_offset[AMD64_RIP_REGNUM] + 8; - regcache_raw_collect (regcache, AMD64_RSP_REGNUM, buf); - sp = extract_unsigned_integer (buf, 8, byte_order) - offset; - - /* Store the stack pointer. */ - write_memory_unsigned_integer (sp_addr, 8, byte_order, sp); - - /* The stack pointer was (potentially) modified. Make sure we - build a proper stack frame. */ - regnum = -1; - } - - for (i = 0; i < ARRAY_SIZE (amd64obsd_uthread_reg_offset); i++) - { - if (amd64obsd_uthread_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - /* Fetch stack pointer from thread structure (if we didn't - calculate it already). */ - if (sp == 0) - sp = read_memory_unsigned_integer (sp_addr, 8, byte_order); - - /* Write the register into the stack frame. */ - regcache_raw_collect (regcache, i, buf); - write_memory (sp + amd64obsd_uthread_reg_offset[i], buf, 8); - } - } -} -/* Kernel debugging support. */ - -/* From . Easy since `struct trapframe' matches - `struct sigcontext'. */ -#define amd64obsd_tf_reg_offset amd64obsd_sc_reg_offset - -static struct trad_frame_cache * -amd64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct trad_frame_cache *cache; - CORE_ADDR func, sp, addr; - ULONGEST cs; - const char *name; - int i; - - if (*this_cache) - return (struct trad_frame_cache *) *this_cache; - - cache = trad_frame_cache_zalloc (this_frame); - *this_cache = cache; - - func = get_frame_func (this_frame); - sp = get_frame_register_unsigned (this_frame, AMD64_RSP_REGNUM); - - find_pc_partial_function (func, &name, NULL, NULL); - if (name && startswith (name, "Xintr")) - addr = sp + 8; /* It's an interrupt frame. */ - else - addr = sp; - - for (i = 0; i < ARRAY_SIZE (amd64obsd_tf_reg_offset); i++) - if (amd64obsd_tf_reg_offset[i] != -1) - trad_frame_set_reg_addr (cache, i, addr + amd64obsd_tf_reg_offset[i]); - - /* Read %cs from trap frame. */ - addr += amd64obsd_tf_reg_offset[AMD64_CS_REGNUM]; - cs = read_memory_unsigned_integer (addr, 8, byte_order); - if ((cs & I386_SEL_RPL) == I386_SEL_UPL) - { - /* Trap from user space; terminate backtrace. */ - trad_frame_set_id (cache, outer_frame_id); - } - else - { - /* Construct the frame ID using the function start. */ - trad_frame_set_id (cache, frame_id_build (sp + 16, func)); - } - - return cache; -} - -static void -amd64obsd_trapframe_this_id (struct frame_info *this_frame, - void **this_cache, struct frame_id *this_id) -{ - struct trad_frame_cache *cache = - amd64obsd_trapframe_cache (this_frame, this_cache); - - trad_frame_get_id (cache, this_id); -} - -static struct value * -amd64obsd_trapframe_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct trad_frame_cache *cache = - amd64obsd_trapframe_cache (this_frame, this_cache); - - return trad_frame_get_register (cache, this_frame, regnum); -} - -static int -amd64obsd_trapframe_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_prologue_cache) -{ - ULONGEST cs; - const char *name; - - /* Check Current Privilege Level and bail out if we're not executing - in kernel space. */ - cs = get_frame_register_unsigned (this_frame, AMD64_CS_REGNUM); - if ((cs & I386_SEL_RPL) == I386_SEL_UPL) - return 0; - - find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL); - return (name && ((strcmp (name, "calltrap") == 0) - || (strcmp (name, "osyscall1") == 0) - || (strcmp (name, "Xsyscall") == 0) - || (startswith (name, "Xintr")))); -} - -static const struct frame_unwind amd64obsd_trapframe_unwind = { - /* FIXME: kettenis/20051219: This really is more like an interrupt - frame, but SIGTRAMP_FRAME would print , - which really is not what we want here. */ - NORMAL_FRAME, - default_frame_unwind_stop_reason, - amd64obsd_trapframe_this_id, - amd64obsd_trapframe_prev_register, - NULL, - amd64obsd_trapframe_sniffer -}; - - -static void -amd64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - amd64_init_abi (info, gdbarch); - obsd_init_abi (info, gdbarch); - - /* Initialize general-purpose register set details. */ - tdep->gregset_reg_offset = amd64obsd_r_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (amd64obsd_r_reg_offset); - tdep->sizeof_gregset = 24 * 8; - - tdep->jb_pc_offset = 7 * 8; - - tdep->sigtramp_p = amd64obsd_sigtramp_p; - tdep->sigcontext_addr = amd64obsd_sigcontext_addr; - tdep->sc_reg_offset = amd64obsd_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (amd64obsd_sc_reg_offset); - - /* OpenBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, amd64obsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, amd64obsd_collect_uthread); - - /* OpenBSD uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); - - /* Unwind kernel trap frames correctly. */ - frame_unwind_prepend_unwinder (gdbarch, &amd64obsd_trapframe_unwind); -} - -/* Traditional (a.out) NetBSD-style core dumps. */ - -static void -amd64obsd_core_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - amd64obsd_init_abi (info, gdbarch); - - set_gdbarch_iterate_over_regset_sections - (gdbarch, amd64obsd_iterate_over_regset_sections); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_amd64obsd_tdep (void); - -void -_initialize_amd64obsd_tdep (void) -{ - /* The OpenBSD/amd64 native dependent code makes this assumption. */ - gdb_assert (ARRAY_SIZE (amd64obsd_r_reg_offset) == AMD64_NUM_GREGS); - - gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, - GDB_OSABI_OPENBSD_ELF, amd64obsd_init_abi); - - /* OpenBSD uses traditional (a.out) NetBSD-style core dumps. */ - gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, - GDB_OSABI_NETBSD_AOUT, amd64obsd_core_init_abi); -} diff --git a/gdb/arm-bsd-tdep.c b/gdb/arm-bsd-tdep.c new file mode 100644 index 00000000000..be0c0bbc266 --- /dev/null +++ b/gdb/arm-bsd-tdep.c @@ -0,0 +1,122 @@ +/* Target-dependent code for ARM BSD's. + + Copyright (C) 2006-2016 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 "arm-tdep.h" + +/* Core file support. */ + +/* Sizeof `struct reg' in . */ +#define ARMBSD_SIZEOF_GREGS (17 * 4) + +/* Sizeof `struct fpreg' in = ARMBSD_SIZEOF_FPREGS); + + for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + armbsd_fpreg_offset (i)); + } +} + +/* 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 +armbsd_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 >= ARMBSD_SIZEOF_GREGS); + + for (i = ARM_A1_REGNUM; i <= ARM_PC_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + i * 4); + } + + if (regnum == ARM_PS_REGNUM || regnum == -1) + regcache_raw_supply (regcache, i, regs + 16 * 4); + + if (len >= ARMBSD_SIZEOF_GREGS + ARMBSD_SIZEOF_FPREGS) + { + regs += ARMBSD_SIZEOF_GREGS; + len -= ARMBSD_SIZEOF_GREGS; + armbsd_supply_fpregset (regset, regcache, regnum, regs, len); + } +} + +/* ARM register sets. */ + +static const struct regset armbsd_gregset = +{ + NULL, + armbsd_supply_gregset, + NULL, + REGSET_VARIABLE_SIZE +}; + +static const struct regset armbsd_fpregset = +{ + NULL, + armbsd_supply_fpregset +}; + +/* Iterate over supported core file register note sections. */ + +void +armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", ARMBSD_SIZEOF_GREGS, &armbsd_gregset, NULL, cb_data); + cb (".reg2", ARMBSD_SIZEOF_FPREGS, &armbsd_fpregset, NULL, cb_data); +} diff --git a/gdb/arm-nbsd-nat.c b/gdb/arm-nbsd-nat.c new file mode 100644 index 00000000000..c8b549e47f9 --- /dev/null +++ b/gdb/arm-nbsd-nat.c @@ -0,0 +1,501 @@ +/* Native-dependent code for BSD Unix running on ARM's, for GDB. + + Copyright (C) 1988-2016 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 "inferior.h" +#include "regcache.h" +#include "target.h" +#include +#include +#include +#include + +#include "arm-tdep.h" +#include "inf-ptrace.h" + +extern int arm_apcs_32; + +static void +arm_supply_gregset (struct regcache *regcache, struct reg *gregset) +{ + int regno; + CORE_ADDR r_pc; + + /* Integer registers. */ + for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) + regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]); + + regcache_raw_supply (regcache, ARM_SP_REGNUM, + (char *) &gregset->r_sp); + regcache_raw_supply (regcache, ARM_LR_REGNUM, + (char *) &gregset->r_lr); + /* This is ok: we're running native... */ + r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), gregset->r_pc); + regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc); + + if (arm_apcs_32) + regcache_raw_supply (regcache, ARM_PS_REGNUM, + (char *) &gregset->r_cpsr); + else + regcache_raw_supply (regcache, ARM_PS_REGNUM, + (char *) &gregset->r_pc); +} + +static void +arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset) +{ + int regno; + + for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) + regcache_raw_supply (regcache, regno, + (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]); + + regcache_raw_supply (regcache, ARM_FPS_REGNUM, + (char *) &fparegset->fpr_fpsr); +} + +static void +fetch_register (struct regcache *regcache, int regno) +{ + struct reg inferior_registers; + int ret; + + ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0); + + if (ret < 0) + { + warning (_("unable to fetch general register")); + return; + } + + switch (regno) + { + case ARM_SP_REGNUM: + regcache_raw_supply (regcache, ARM_SP_REGNUM, + (char *) &inferior_registers.r_sp); + break; + + case ARM_LR_REGNUM: + regcache_raw_supply (regcache, ARM_LR_REGNUM, + (char *) &inferior_registers.r_lr); + break; + + case ARM_PC_REGNUM: + /* This is ok: we're running native... */ + inferior_registers.r_pc = gdbarch_addr_bits_remove + (get_regcache_arch (regcache), + inferior_registers.r_pc); + regcache_raw_supply (regcache, ARM_PC_REGNUM, + (char *) &inferior_registers.r_pc); + break; + + case ARM_PS_REGNUM: + if (arm_apcs_32) + regcache_raw_supply (regcache, ARM_PS_REGNUM, + (char *) &inferior_registers.r_cpsr); + else + regcache_raw_supply (regcache, ARM_PS_REGNUM, + (char *) &inferior_registers.r_pc); + break; + + default: + regcache_raw_supply (regcache, regno, + (char *) &inferior_registers.r[regno]); + break; + } +} + +static void +fetch_regs (struct regcache *regcache) +{ + struct reg inferior_registers; + int ret; + int regno; + + ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0); + + if (ret < 0) + { + warning (_("unable to fetch general registers")); + return; + } + + arm_supply_gregset (regcache, &inferior_registers); +} + +static void +fetch_fp_register (struct regcache *regcache, int regno) +{ + struct fpreg inferior_fp_registers; + int ret; + + ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); + + if (ret < 0) + { + warning (_("unable to fetch floating-point register")); + return; + } + + switch (regno) + { + case ARM_FPS_REGNUM: + regcache_raw_supply (regcache, ARM_FPS_REGNUM, + (char *) &inferior_fp_registers.fpr_fpsr); + break; + + default: + regcache_raw_supply (regcache, regno, + (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); + break; + } +} + +static void +fetch_fp_regs (struct regcache *regcache) +{ + struct fpreg inferior_fp_registers; + int ret; + int regno; + + ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); + + if (ret < 0) + { + warning (_("unable to fetch general registers")); + return; + } + + arm_supply_fparegset (regcache, &inferior_fp_registers); +} + +static void +armnbsd_fetch_registers (struct target_ops *ops, + 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_regs (regcache); + fetch_fp_regs (regcache); + } +} + + +static void +store_register (const struct regcache *regcache, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct reg inferior_registers; + int ret; + + ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0); + + if (ret < 0) + { + warning (_("unable to fetch general registers")); + return; + } + + switch (regno) + { + case ARM_SP_REGNUM: + regcache_raw_collect (regcache, ARM_SP_REGNUM, + (char *) &inferior_registers.r_sp); + break; + + case ARM_LR_REGNUM: + regcache_raw_collect (regcache, ARM_LR_REGNUM, + (char *) &inferior_registers.r_lr); + break; + + case ARM_PC_REGNUM: + if (arm_apcs_32) + regcache_raw_collect (regcache, ARM_PC_REGNUM, + (char *) &inferior_registers.r_pc); + else + { + unsigned pc_val; + + regcache_raw_collect (regcache, 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 (regcache, ARM_PS_REGNUM, + (char *) &inferior_registers.r_cpsr); + else + { + unsigned psr_val; + + regcache_raw_collect (regcache, 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 (regcache, regno, + (char *) &inferior_registers.r[regno]); + break; + } + + ret = ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0); + + if (ret < 0) + warning (_("unable to write register %d to inferior"), regno); +} + +static void +store_regs (const struct regcache *regcache) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct reg inferior_registers; + int ret; + int regno; + + + for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) + regcache_raw_collect (regcache, regno, + (char *) &inferior_registers.r[regno]); + + regcache_raw_collect (regcache, ARM_SP_REGNUM, + (char *) &inferior_registers.r_sp); + regcache_raw_collect (regcache, ARM_LR_REGNUM, + (char *) &inferior_registers.r_lr); + + if (arm_apcs_32) + { + regcache_raw_collect (regcache, ARM_PC_REGNUM, + (char *) &inferior_registers.r_pc); + regcache_raw_collect (regcache, ARM_PS_REGNUM, + (char *) &inferior_registers.r_cpsr); + } + else + { + unsigned pc_val; + unsigned psr_val; + + regcache_raw_collect (regcache, ARM_PC_REGNUM, + (char *) &pc_val); + regcache_raw_collect (regcache, 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, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0); + + 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 ret; + + ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); + + if (ret < 0) + { + warning (_("unable to fetch floating-point registers")); + return; + } + + switch (regno) + { + case ARM_FPS_REGNUM: + regcache_raw_collect (regcache, ARM_FPS_REGNUM, + (char *) &inferior_fp_registers.fpr_fpsr); + break; + + default: + regcache_raw_collect (regcache, regno, + (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); + break; + } + + ret = ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); + + if (ret < 0) + warning (_("unable to write register %d to inferior"), regno); +} + +static void +store_fp_regs (const struct regcache *regcache) +{ + struct fpreg inferior_fp_registers; + int ret; + int regno; + + + for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) + regcache_raw_collect (regcache, regno, + (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); + + regcache_raw_collect (regcache, ARM_FPS_REGNUM, + (char *) &inferior_fp_registers.fpr_fpsr); + + ret = ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); + + if (ret < 0) + warning (_("unable to store floating-point registers")); +} + +static void +armnbsd_store_registers (struct target_ops *ops, + 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); + } +} + +struct md_core +{ + struct reg intreg; + struct fpreg freg; +}; + +static void +fetch_core_registers (struct regcache *regcache, + char *core_reg_sect, unsigned core_reg_size, + int which, CORE_ADDR ignore) +{ + struct md_core *core_reg = (struct md_core *) core_reg_sect; + int regno; + CORE_ADDR r_pc; + + arm_supply_gregset (regcache, &core_reg->intreg); + arm_supply_fparegset (regcache, &core_reg->freg); +} + +static void +fetch_elfcore_registers (struct regcache *regcache, + char *core_reg_sect, unsigned core_reg_size, + int which, CORE_ADDR ignore) +{ + struct reg gregset; + struct fpreg fparegset; + + switch (which) + { + case 0: /* Integer registers. */ + if (core_reg_size != sizeof (struct reg)) + warning (_("wrong size of register set in core file")); + else + { + /* The memcpy may be unnecessary, but we can't really be sure + of the alignment of the data in the core file. */ + memcpy (&gregset, core_reg_sect, sizeof (gregset)); + arm_supply_gregset (regcache, &gregset); + } + break; + + case 2: + if (core_reg_size != sizeof (struct fpreg)) + warning (_("wrong size of FPA register set in core file")); + else + { + /* The memcpy may be unnecessary, but we can't really be sure + of the alignment of the data in the core file. */ + memcpy (&fparegset, core_reg_sect, sizeof (fparegset)); + arm_supply_fparegset (regcache, &fparegset); + } + break; + + default: + /* Don't know what kind of register request this is; just ignore it. */ + break; + } +} + +static struct core_fns arm_netbsd_core_fns = +{ + bfd_target_unknown_flavour, /* core_flovour. */ + default_check_format, /* check_format. */ + default_core_sniffer, /* core_sniffer. */ + fetch_core_registers, /* core_read_registers. */ + NULL +}; + +static struct core_fns arm_netbsd_elfcore_fns = +{ + bfd_target_elf_flavour, /* core_flovour. */ + default_check_format, /* check_format. */ + default_core_sniffer, /* core_sniffer. */ + fetch_elfcore_registers, /* core_read_registers. */ + NULL +}; + +void +_initialize_arm_netbsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = armnbsd_fetch_registers; + t->to_store_registers = armnbsd_store_registers; + add_target (t); + + deprecated_add_core_fns (&arm_netbsd_core_fns); + deprecated_add_core_fns (&arm_netbsd_elfcore_fns); +} diff --git a/gdb/arm-nbsd-tdep.c b/gdb/arm-nbsd-tdep.c new file mode 100644 index 00000000000..259853c6465 --- /dev/null +++ b/gdb/arm-nbsd-tdep.c @@ -0,0 +1,121 @@ +/* Target-dependent code for NetBSD/arm. + + Copyright (C) 2002-2016 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-tdep.h" +#include "solib-svr4.h" + +/* Description of the longjmp buffer. */ +#define ARM_NBSD_JB_PC 24 +#define ARM_NBSD_JB_ELEMENT_SIZE INT_REGISTER_SIZE + +/* For compatibility with previous implemenations 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}; + +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; + + /* Single stepping. */ + set_gdbarch_software_single_step (gdbarch, arm_software_single_step); +} + +static void +arm_netbsd_aout_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + arm_netbsd_init_abi_common (info, gdbarch); + if (tdep->fp_model == ARM_FLOAT_AUTO) + tdep->fp_model = ARM_FLOAT_SOFT_FPA; +} + +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); + 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); +} + +static enum gdb_osabi +arm_netbsd_aout_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "a.out-arm-netbsd") == 0) + return GDB_OSABI_NETBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_arm_netbsd_tdep; + +void +_initialize_arm_netbsd_tdep (void) +{ + gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_aout_flavour, + arm_netbsd_aout_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD_AOUT, + arm_netbsd_aout_init_abi); + gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD_ELF, + arm_netbsd_elf_init_abi); +} diff --git a/gdb/arm-obsd-tdep.c b/gdb/arm-obsd-tdep.c new file mode 100644 index 00000000000..5ccf1d146d1 --- /dev/null +++ b/gdb/arm-obsd-tdep.c @@ -0,0 +1,140 @@ +/* Target-dependent code for OpenBSD/arm. + + Copyright (C) 2006-2016 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 "trad-frame.h" +#include "tramp-frame.h" + +#include "obsd-tdep.h" +#include "arm-tdep.h" +#include "solib-svr4.h" + +/* Signal trampolines. */ + +static void +armobsd_sigframe_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *cache, + CORE_ADDR func) +{ + CORE_ADDR sp, sigcontext_addr, addr; + int regnum; + + /* We find the appropriate instance of `struct sigcontext' at a + fixed offset in the signal frame. */ + sp = get_frame_register_signed (this_frame, ARM_SP_REGNUM); + sigcontext_addr = sp + 16; + + /* PC. */ + trad_frame_set_reg_addr (cache, ARM_PC_REGNUM, sigcontext_addr + 76); + + /* GPRs. */ + for (regnum = ARM_A1_REGNUM, addr = sigcontext_addr + 12; + regnum <= ARM_LR_REGNUM; regnum++, addr += 4) + trad_frame_set_reg_addr (cache, regnum, addr); + + trad_frame_set_id (cache, frame_id_build (sp, func)); +} + +static const struct tramp_frame armobsd_sigframe = +{ + SIGTRAMP_FRAME, + 4, + { + { 0xe28d0010, -1 }, /* add r0, sp, #16 */ + { 0xef000067, -1 }, /* swi SYS_sigreturn */ + { 0xef000001, -1 }, /* swi SYS_exit */ + { 0xeafffffc, -1 }, /* b . - 8 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + armobsd_sigframe_init +}; + + +/* Override default thumb breakpoints. */ +static const gdb_byte arm_obsd_thumb_le_breakpoint[] = {0xfe, 0xdf}; +static const gdb_byte arm_obsd_thumb_be_breakpoint[] = {0xdf, 0xfe}; + +static void +armobsd_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (tdep->fp_model == ARM_FLOAT_AUTO) + tdep->fp_model = ARM_FLOAT_SOFT_VFP; + + tramp_frame_prepend_unwinder (gdbarch, &armobsd_sigframe); + + /* OpenBSD/arm uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); + + tdep->jb_pc = 24; + tdep->jb_elt_size = 4; + + set_gdbarch_iterate_over_regset_sections + (gdbarch, armbsd_iterate_over_regset_sections); + + /* OpenBSD/arm uses -fpcc-struct-return by default. */ + tdep->struct_return = pcc_struct_return; + + /* Single stepping. */ + set_gdbarch_software_single_step (gdbarch, arm_software_single_step); + + /* Breakpoints. */ + switch (info.byte_order) + { + case BFD_ENDIAN_BIG: + tdep->thumb_breakpoint = arm_obsd_thumb_be_breakpoint; + tdep->thumb_breakpoint_size = sizeof (arm_obsd_thumb_be_breakpoint); + break; + + case BFD_ENDIAN_LITTLE: + tdep->thumb_breakpoint = arm_obsd_thumb_le_breakpoint; + tdep->thumb_breakpoint_size = sizeof (arm_obsd_thumb_le_breakpoint); + break; + } +} + + +static enum gdb_osabi +armobsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_OPENBSD_ELF; + + return GDB_OSABI_UNKNOWN; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_armobsd_tdep; + +void +_initialize_armobsd_tdep (void) +{ + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_unknown_flavour, + armobsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_OPENBSD_ELF, + armobsd_init_abi); +} diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h index 6af44a9f9b6..6fb417b9b98 100644 --- a/gdb/arm-tdep.h +++ b/gdb/arm-tdep.h @@ -276,7 +276,7 @@ extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR); extern int arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache, CORE_ADDR addr); -/* Functions exported from armbsd-tdep.h. */ +/* Functions exported from arm-bsd-tdep.h. */ /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ diff --git a/gdb/armbsd-tdep.c b/gdb/armbsd-tdep.c deleted file mode 100644 index be0c0bbc266..00000000000 --- a/gdb/armbsd-tdep.c +++ /dev/null @@ -1,122 +0,0 @@ -/* Target-dependent code for ARM BSD's. - - Copyright (C) 2006-2016 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 "arm-tdep.h" - -/* Core file support. */ - -/* Sizeof `struct reg' in . */ -#define ARMBSD_SIZEOF_GREGS (17 * 4) - -/* Sizeof `struct fpreg' in = ARMBSD_SIZEOF_FPREGS); - - for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + armbsd_fpreg_offset (i)); - } -} - -/* 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 -armbsd_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 >= ARMBSD_SIZEOF_GREGS); - - for (i = ARM_A1_REGNUM; i <= ARM_PC_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + i * 4); - } - - if (regnum == ARM_PS_REGNUM || regnum == -1) - regcache_raw_supply (regcache, i, regs + 16 * 4); - - if (len >= ARMBSD_SIZEOF_GREGS + ARMBSD_SIZEOF_FPREGS) - { - regs += ARMBSD_SIZEOF_GREGS; - len -= ARMBSD_SIZEOF_GREGS; - armbsd_supply_fpregset (regset, regcache, regnum, regs, len); - } -} - -/* ARM register sets. */ - -static const struct regset armbsd_gregset = -{ - NULL, - armbsd_supply_gregset, - NULL, - REGSET_VARIABLE_SIZE -}; - -static const struct regset armbsd_fpregset = -{ - NULL, - armbsd_supply_fpregset -}; - -/* Iterate over supported core file register note sections. */ - -void -armbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", ARMBSD_SIZEOF_GREGS, &armbsd_gregset, NULL, cb_data); - cb (".reg2", ARMBSD_SIZEOF_FPREGS, &armbsd_fpregset, NULL, cb_data); -} diff --git a/gdb/armnbsd-nat.c b/gdb/armnbsd-nat.c deleted file mode 100644 index c8b549e47f9..00000000000 --- a/gdb/armnbsd-nat.c +++ /dev/null @@ -1,501 +0,0 @@ -/* Native-dependent code for BSD Unix running on ARM's, for GDB. - - Copyright (C) 1988-2016 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 "inferior.h" -#include "regcache.h" -#include "target.h" -#include -#include -#include -#include - -#include "arm-tdep.h" -#include "inf-ptrace.h" - -extern int arm_apcs_32; - -static void -arm_supply_gregset (struct regcache *regcache, struct reg *gregset) -{ - int regno; - CORE_ADDR r_pc; - - /* Integer registers. */ - for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) - regcache_raw_supply (regcache, regno, (char *) &gregset->r[regno]); - - regcache_raw_supply (regcache, ARM_SP_REGNUM, - (char *) &gregset->r_sp); - regcache_raw_supply (regcache, ARM_LR_REGNUM, - (char *) &gregset->r_lr); - /* This is ok: we're running native... */ - r_pc = gdbarch_addr_bits_remove (get_regcache_arch (regcache), gregset->r_pc); - regcache_raw_supply (regcache, ARM_PC_REGNUM, (char *) &r_pc); - - if (arm_apcs_32) - regcache_raw_supply (regcache, ARM_PS_REGNUM, - (char *) &gregset->r_cpsr); - else - regcache_raw_supply (regcache, ARM_PS_REGNUM, - (char *) &gregset->r_pc); -} - -static void -arm_supply_fparegset (struct regcache *regcache, struct fpreg *fparegset) -{ - int regno; - - for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) - regcache_raw_supply (regcache, regno, - (char *) &fparegset->fpr[regno - ARM_F0_REGNUM]); - - regcache_raw_supply (regcache, ARM_FPS_REGNUM, - (char *) &fparegset->fpr_fpsr); -} - -static void -fetch_register (struct regcache *regcache, int regno) -{ - struct reg inferior_registers; - int ret; - - ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0); - - if (ret < 0) - { - warning (_("unable to fetch general register")); - return; - } - - switch (regno) - { - case ARM_SP_REGNUM: - regcache_raw_supply (regcache, ARM_SP_REGNUM, - (char *) &inferior_registers.r_sp); - break; - - case ARM_LR_REGNUM: - regcache_raw_supply (regcache, ARM_LR_REGNUM, - (char *) &inferior_registers.r_lr); - break; - - case ARM_PC_REGNUM: - /* This is ok: we're running native... */ - inferior_registers.r_pc = gdbarch_addr_bits_remove - (get_regcache_arch (regcache), - inferior_registers.r_pc); - regcache_raw_supply (regcache, ARM_PC_REGNUM, - (char *) &inferior_registers.r_pc); - break; - - case ARM_PS_REGNUM: - if (arm_apcs_32) - regcache_raw_supply (regcache, ARM_PS_REGNUM, - (char *) &inferior_registers.r_cpsr); - else - regcache_raw_supply (regcache, ARM_PS_REGNUM, - (char *) &inferior_registers.r_pc); - break; - - default: - regcache_raw_supply (regcache, regno, - (char *) &inferior_registers.r[regno]); - break; - } -} - -static void -fetch_regs (struct regcache *regcache) -{ - struct reg inferior_registers; - int ret; - int regno; - - ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0); - - if (ret < 0) - { - warning (_("unable to fetch general registers")); - return; - } - - arm_supply_gregset (regcache, &inferior_registers); -} - -static void -fetch_fp_register (struct regcache *regcache, int regno) -{ - struct fpreg inferior_fp_registers; - int ret; - - ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); - - if (ret < 0) - { - warning (_("unable to fetch floating-point register")); - return; - } - - switch (regno) - { - case ARM_FPS_REGNUM: - regcache_raw_supply (regcache, ARM_FPS_REGNUM, - (char *) &inferior_fp_registers.fpr_fpsr); - break; - - default: - regcache_raw_supply (regcache, regno, - (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); - break; - } -} - -static void -fetch_fp_regs (struct regcache *regcache) -{ - struct fpreg inferior_fp_registers; - int ret; - int regno; - - ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); - - if (ret < 0) - { - warning (_("unable to fetch general registers")); - return; - } - - arm_supply_fparegset (regcache, &inferior_fp_registers); -} - -static void -armnbsd_fetch_registers (struct target_ops *ops, - 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_regs (regcache); - fetch_fp_regs (regcache); - } -} - - -static void -store_register (const struct regcache *regcache, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct reg inferior_registers; - int ret; - - ret = ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0); - - if (ret < 0) - { - warning (_("unable to fetch general registers")); - return; - } - - switch (regno) - { - case ARM_SP_REGNUM: - regcache_raw_collect (regcache, ARM_SP_REGNUM, - (char *) &inferior_registers.r_sp); - break; - - case ARM_LR_REGNUM: - regcache_raw_collect (regcache, ARM_LR_REGNUM, - (char *) &inferior_registers.r_lr); - break; - - case ARM_PC_REGNUM: - if (arm_apcs_32) - regcache_raw_collect (regcache, ARM_PC_REGNUM, - (char *) &inferior_registers.r_pc); - else - { - unsigned pc_val; - - regcache_raw_collect (regcache, 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 (regcache, ARM_PS_REGNUM, - (char *) &inferior_registers.r_cpsr); - else - { - unsigned psr_val; - - regcache_raw_collect (regcache, 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 (regcache, regno, - (char *) &inferior_registers.r[regno]); - break; - } - - ret = ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0); - - if (ret < 0) - warning (_("unable to write register %d to inferior"), regno); -} - -static void -store_regs (const struct regcache *regcache) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct reg inferior_registers; - int ret; - int regno; - - - for (regno = ARM_A1_REGNUM; regno < ARM_SP_REGNUM; regno++) - regcache_raw_collect (regcache, regno, - (char *) &inferior_registers.r[regno]); - - regcache_raw_collect (regcache, ARM_SP_REGNUM, - (char *) &inferior_registers.r_sp); - regcache_raw_collect (regcache, ARM_LR_REGNUM, - (char *) &inferior_registers.r_lr); - - if (arm_apcs_32) - { - regcache_raw_collect (regcache, ARM_PC_REGNUM, - (char *) &inferior_registers.r_pc); - regcache_raw_collect (regcache, ARM_PS_REGNUM, - (char *) &inferior_registers.r_cpsr); - } - else - { - unsigned pc_val; - unsigned psr_val; - - regcache_raw_collect (regcache, ARM_PC_REGNUM, - (char *) &pc_val); - regcache_raw_collect (regcache, 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, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0); - - 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 ret; - - ret = ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); - - if (ret < 0) - { - warning (_("unable to fetch floating-point registers")); - return; - } - - switch (regno) - { - case ARM_FPS_REGNUM: - regcache_raw_collect (regcache, ARM_FPS_REGNUM, - (char *) &inferior_fp_registers.fpr_fpsr); - break; - - default: - regcache_raw_collect (regcache, regno, - (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); - break; - } - - ret = ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); - - if (ret < 0) - warning (_("unable to write register %d to inferior"), regno); -} - -static void -store_fp_regs (const struct regcache *regcache) -{ - struct fpreg inferior_fp_registers; - int ret; - int regno; - - - for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++) - regcache_raw_collect (regcache, regno, - (char *) &inferior_fp_registers.fpr[regno - ARM_F0_REGNUM]); - - regcache_raw_collect (regcache, ARM_FPS_REGNUM, - (char *) &inferior_fp_registers.fpr_fpsr); - - ret = ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_fp_registers, 0); - - if (ret < 0) - warning (_("unable to store floating-point registers")); -} - -static void -armnbsd_store_registers (struct target_ops *ops, - 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); - } -} - -struct md_core -{ - struct reg intreg; - struct fpreg freg; -}; - -static void -fetch_core_registers (struct regcache *regcache, - char *core_reg_sect, unsigned core_reg_size, - int which, CORE_ADDR ignore) -{ - struct md_core *core_reg = (struct md_core *) core_reg_sect; - int regno; - CORE_ADDR r_pc; - - arm_supply_gregset (regcache, &core_reg->intreg); - arm_supply_fparegset (regcache, &core_reg->freg); -} - -static void -fetch_elfcore_registers (struct regcache *regcache, - char *core_reg_sect, unsigned core_reg_size, - int which, CORE_ADDR ignore) -{ - struct reg gregset; - struct fpreg fparegset; - - switch (which) - { - case 0: /* Integer registers. */ - if (core_reg_size != sizeof (struct reg)) - warning (_("wrong size of register set in core file")); - else - { - /* The memcpy may be unnecessary, but we can't really be sure - of the alignment of the data in the core file. */ - memcpy (&gregset, core_reg_sect, sizeof (gregset)); - arm_supply_gregset (regcache, &gregset); - } - break; - - case 2: - if (core_reg_size != sizeof (struct fpreg)) - warning (_("wrong size of FPA register set in core file")); - else - { - /* The memcpy may be unnecessary, but we can't really be sure - of the alignment of the data in the core file. */ - memcpy (&fparegset, core_reg_sect, sizeof (fparegset)); - arm_supply_fparegset (regcache, &fparegset); - } - break; - - default: - /* Don't know what kind of register request this is; just ignore it. */ - break; - } -} - -static struct core_fns arm_netbsd_core_fns = -{ - bfd_target_unknown_flavour, /* core_flovour. */ - default_check_format, /* check_format. */ - default_core_sniffer, /* core_sniffer. */ - fetch_core_registers, /* core_read_registers. */ - NULL -}; - -static struct core_fns arm_netbsd_elfcore_fns = -{ - bfd_target_elf_flavour, /* core_flovour. */ - default_check_format, /* check_format. */ - default_core_sniffer, /* core_sniffer. */ - fetch_elfcore_registers, /* core_read_registers. */ - NULL -}; - -void -_initialize_arm_netbsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = armnbsd_fetch_registers; - t->to_store_registers = armnbsd_store_registers; - add_target (t); - - deprecated_add_core_fns (&arm_netbsd_core_fns); - deprecated_add_core_fns (&arm_netbsd_elfcore_fns); -} diff --git a/gdb/armnbsd-tdep.c b/gdb/armnbsd-tdep.c deleted file mode 100644 index 259853c6465..00000000000 --- a/gdb/armnbsd-tdep.c +++ /dev/null @@ -1,121 +0,0 @@ -/* Target-dependent code for NetBSD/arm. - - Copyright (C) 2002-2016 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-tdep.h" -#include "solib-svr4.h" - -/* Description of the longjmp buffer. */ -#define ARM_NBSD_JB_PC 24 -#define ARM_NBSD_JB_ELEMENT_SIZE INT_REGISTER_SIZE - -/* For compatibility with previous implemenations 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}; - -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; - - /* Single stepping. */ - set_gdbarch_software_single_step (gdbarch, arm_software_single_step); -} - -static void -arm_netbsd_aout_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - arm_netbsd_init_abi_common (info, gdbarch); - if (tdep->fp_model == ARM_FLOAT_AUTO) - tdep->fp_model = ARM_FLOAT_SOFT_FPA; -} - -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); - 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); -} - -static enum gdb_osabi -arm_netbsd_aout_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "a.out-arm-netbsd") == 0) - return GDB_OSABI_NETBSD_AOUT; - - return GDB_OSABI_UNKNOWN; -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_arm_netbsd_tdep; - -void -_initialize_arm_netbsd_tdep (void) -{ - gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_aout_flavour, - arm_netbsd_aout_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD_AOUT, - arm_netbsd_aout_init_abi); - gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_NETBSD_ELF, - arm_netbsd_elf_init_abi); -} diff --git a/gdb/armobsd-tdep.c b/gdb/armobsd-tdep.c deleted file mode 100644 index 5ccf1d146d1..00000000000 --- a/gdb/armobsd-tdep.c +++ /dev/null @@ -1,140 +0,0 @@ -/* Target-dependent code for OpenBSD/arm. - - Copyright (C) 2006-2016 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 "trad-frame.h" -#include "tramp-frame.h" - -#include "obsd-tdep.h" -#include "arm-tdep.h" -#include "solib-svr4.h" - -/* Signal trampolines. */ - -static void -armobsd_sigframe_init (const struct tramp_frame *self, - struct frame_info *this_frame, - struct trad_frame_cache *cache, - CORE_ADDR func) -{ - CORE_ADDR sp, sigcontext_addr, addr; - int regnum; - - /* We find the appropriate instance of `struct sigcontext' at a - fixed offset in the signal frame. */ - sp = get_frame_register_signed (this_frame, ARM_SP_REGNUM); - sigcontext_addr = sp + 16; - - /* PC. */ - trad_frame_set_reg_addr (cache, ARM_PC_REGNUM, sigcontext_addr + 76); - - /* GPRs. */ - for (regnum = ARM_A1_REGNUM, addr = sigcontext_addr + 12; - regnum <= ARM_LR_REGNUM; regnum++, addr += 4) - trad_frame_set_reg_addr (cache, regnum, addr); - - trad_frame_set_id (cache, frame_id_build (sp, func)); -} - -static const struct tramp_frame armobsd_sigframe = -{ - SIGTRAMP_FRAME, - 4, - { - { 0xe28d0010, -1 }, /* add r0, sp, #16 */ - { 0xef000067, -1 }, /* swi SYS_sigreturn */ - { 0xef000001, -1 }, /* swi SYS_exit */ - { 0xeafffffc, -1 }, /* b . - 8 */ - { TRAMP_SENTINEL_INSN, -1 } - }, - armobsd_sigframe_init -}; - - -/* Override default thumb breakpoints. */ -static const gdb_byte arm_obsd_thumb_le_breakpoint[] = {0xfe, 0xdf}; -static const gdb_byte arm_obsd_thumb_be_breakpoint[] = {0xdf, 0xfe}; - -static void -armobsd_init_abi (struct gdbarch_info info, - struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - if (tdep->fp_model == ARM_FLOAT_AUTO) - tdep->fp_model = ARM_FLOAT_SOFT_VFP; - - tramp_frame_prepend_unwinder (gdbarch, &armobsd_sigframe); - - /* OpenBSD/arm uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); - set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); - - tdep->jb_pc = 24; - tdep->jb_elt_size = 4; - - set_gdbarch_iterate_over_regset_sections - (gdbarch, armbsd_iterate_over_regset_sections); - - /* OpenBSD/arm uses -fpcc-struct-return by default. */ - tdep->struct_return = pcc_struct_return; - - /* Single stepping. */ - set_gdbarch_software_single_step (gdbarch, arm_software_single_step); - - /* Breakpoints. */ - switch (info.byte_order) - { - case BFD_ENDIAN_BIG: - tdep->thumb_breakpoint = arm_obsd_thumb_be_breakpoint; - tdep->thumb_breakpoint_size = sizeof (arm_obsd_thumb_be_breakpoint); - break; - - case BFD_ENDIAN_LITTLE: - tdep->thumb_breakpoint = arm_obsd_thumb_le_breakpoint; - tdep->thumb_breakpoint_size = sizeof (arm_obsd_thumb_le_breakpoint); - break; - } -} - - -static enum gdb_osabi -armobsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_OPENBSD_ELF; - - return GDB_OSABI_UNKNOWN; -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_armobsd_tdep; - -void -_initialize_armobsd_tdep (void) -{ - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_unknown_flavour, - armobsd_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_OPENBSD_ELF, - armobsd_init_abi); -} diff --git a/gdb/config/alpha/fbsd.mh b/gdb/config/alpha/fbsd.mh index 6d1fe29c1d5..9cd6912716f 100644 --- a/gdb/config/alpha/fbsd.mh +++ b/gdb/config/alpha/fbsd.mh @@ -1,6 +1,6 @@ # Host: FreeBSD/alpha NATDEPFILES= fork-child.o inf-ptrace.o \ - fbsd-nat.o alphabsd-nat.o bsd-kvm.o \ + fbsd-nat.o alpha-bsd-nat.o bsd-kvm.o \ core-regset.o LOADLIBES= -lkvm diff --git a/gdb/config/alpha/nbsd.mh b/gdb/config/alpha/nbsd.mh index b4185a78deb..a46739e9b4a 100644 --- a/gdb/config/alpha/nbsd.mh +++ b/gdb/config/alpha/nbsd.mh @@ -1,4 +1,4 @@ # Host: NetBSD/alpha -NATDEPFILES= fork-child.o inf-ptrace.o alphabsd-nat.o bsd-kvm.o +NATDEPFILES= fork-child.o inf-ptrace.o alpha-bsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/arm/nbsdelf.mh b/gdb/config/arm/nbsdelf.mh index 4efb8a37cc5..042b583a912 100644 --- a/gdb/config/arm/nbsdelf.mh +++ b/gdb/config/arm/nbsdelf.mh @@ -1,2 +1,2 @@ # Host: NetBSD/arm -NATDEPFILES= fork-child.o inf-ptrace.o armnbsd-nat.o +NATDEPFILES= fork-child.o inf-ptrace.o arm-nbsd-nat.o diff --git a/gdb/config/djgpp/fnchange.lst b/gdb/config/djgpp/fnchange.lst index 21a80717367..3addd67be69 100644 --- a/gdb/config/djgpp/fnchange.lst +++ b/gdb/config/djgpp/fnchange.lst @@ -118,21 +118,21 @@ @V@/gdb/ada-exp.tab.c @V@/gdb/ada-exp_tab.c @V@/gdb/amd64-windows-nat.c @V@/gdb/a64w-nat.c @V@/gdb/amd64-windows-tdep.c @V@/gdb/a64w-tdep.c -@V@/gdb/amd64fbsd-nat.c @V@/gdb/a64fb-nat.c -@V@/gdb/amd64fbsd-tdep.c @V@/gdb/a64fb-tdep.c -@V@/gdb/amd64nbsd-nat.c @V@/gdb/a64nb-nat.c -@V@/gdb/amd64nbsd-tdep.c @V@/gdb/a64nb-tdep.c -@V@/gdb/amd64obsd-nat.c @V@/gdb/a64ob-nat.c -@V@/gdb/amd64obsd-tdep.c @V@/gdb/a64ob-tdep.c -@V@/gdb/alphabsd-nat.c @V@/gdb/alphb-nat.c -@V@/gdb/alphabsd-tdep.c @V@/gdb/alphb-tdep.c -@V@/gdb/alphanbsd-tdep.c @V@/gdb/alphnb-tdep.c +@V@/gdb/amd64-fbsd-nat.c @V@/gdb/a64fb-nat.c +@V@/gdb/amd64-fbsd-tdep.c @V@/gdb/a64fb-tdep.c +@V@/gdb/amd64-nbsd-nat.c @V@/gdb/a64nb-nat.c +@V@/gdb/amd64-nbsd-tdep.c @V@/gdb/a64nb-tdep.c +@V@/gdb/amd64-obsd-nat.c @V@/gdb/a64ob-nat.c +@V@/gdb/amd64-obsd-tdep.c @V@/gdb/a64ob-tdep.c +@V@/gdb/alpha-bsd-nat.c @V@/gdb/alphb-nat.c +@V@/gdb/alpha-bsd-tdep.c @V@/gdb/alphb-tdep.c +@V@/gdb/alpha-nbsd-tdep.c @V@/gdb/alphnb-tdep.c @V@/gdb/alpha-linux-nat.c @V@/gdb/alphl-nat.c @V@/gdb/alpha-linux-tdep.c @V@/gdb/alphl-tdep.c @V@/gdb/arm-linux-nat.c @V@/gdb/armlin-nat.c @V@/gdb/arm-linux-tdep.c @V@/gdb/armlin-tdep.c -@V@/gdb/armnbsd-nat.c @V@/gdb/armnbd-nat.c -@V@/gdb/armnbsd-tdep.c @V@/gdb/armnbd-tdep.c +@V@/gdb/arm-nbsd-nat.c @V@/gdb/armnbd-nat.c +@V@/gdb/arm-nbsd-tdep.c @V@/gdb/armnbd-tdep.c @V@/gdb/c-exp.tab.c @V@/gdb/c-exp_tab.c @V@/gdb/config/alpha/tm-alphalinux.h @V@/gdb/config/alpha/tm-alplinux.h @V@/gdb/config/i386/nm-cygwin64.h @V@/gdb/config/i386/nm-cyg64.h @@ -276,23 +276,23 @@ @V@/gdb/gdbtk/library/ChangeLog-2000 @V@/gdb/gdbtk/library/ChangeLog.000 @V@/gdb/gdbtk/plugins/intel-pentium/intel-pentium.tcl.in @V@/gdb/gdbtk/plugins/intel-pentium/intel-pentium.t-in @V@/gdb/gdbtk/plugins/rhabout/rhabout.tcl.in @V@/gdb/gdbtk/plugins/rhabout/rhabout.t-in -@V@/gdb/hppabsd-nat.c @V@/gdb/hppab-nat.c -@V@/gdb/hppabsd-tdep.c @V@/gdb/hppab-tdep.c -@V@/gdb/hppnbsd-nat.c @V@/gdb/hppnb-nat.c -@V@/gdb/hppnbsd-tdep.c @V@/gdb/hppnb-tdep.c +@V@/gdb/hppa-bsd-nat.c @V@/gdb/hppab-nat.c +@V@/gdb/hppa-bsd-tdep.c @V@/gdb/hppab-tdep.c +@V@/gdb/hpp-nbsd-nat.c @V@/gdb/hppnb-nat.c +@V@/gdb/hpp-nbsd-tdep.c @V@/gdb/hppnb-tdep.c @V@/gdb/i386-darwin-nat.c @V@/gdb/i386dw-nat.c @V@/gdb/i386-darwin-tdep.c @V@/gdb/i386dw-tdep.c @V@/gdb/i386-linux-tdep.c @V@/gdb/i386lx-tdep.c @V@/gdb/i386-linux-nat.c @V@/gdb/i386lx-nat.c -@V@/gdb/i386bsd-nat.c @V@/gdb/i3bsd-nat.c -@V@/gdb/i386bsd-tdep.c @V@/gdb/i3bsd-tdep.c -@V@/gdb/i386fbsd-nat.c @V@/gdb/i3fbsd-nat.c -@V@/gdb/i386fbsd-tdep.c @V@/gdb/i3fbsd-tdep.c -@V@/gdb/i386gnu-nat.c @V@/gdb/i3gnu-nat.c -@V@/gdb/i386gnu-tdep.c @V@/gdb/i3gnu-tdep.c -@V@/gdb/i386nbsd-tdep.c @V@/gdb/i3nbsd-tdep.c -@V@/gdb/i386obsd-nat.c @V@/gdb/i3obsd-nat.c -@V@/gdb/i386obsd-tdep.c @V@/gdb/i3obsd-tdep.c +@V@/gdb/i386-bsd-nat.c @V@/gdb/i3bsd-nat.c +@V@/gdb/i386-bsd-tdep.c @V@/gdb/i3bsd-tdep.c +@V@/gdb/i386-fbsd-nat.c @V@/gdb/i3fbsd-nat.c +@V@/gdb/i386-fbsd-tdep.c @V@/gdb/i3fbsd-tdep.c +@V@/gdb/i386-gnu-nat.c @V@/gdb/i3gnu-nat.c +@V@/gdb/i386-gnu-tdep.c @V@/gdb/i3gnu-tdep.c +@V@/gdb/i386-nbsd-tdep.c @V@/gdb/i3nbsd-tdep.c +@V@/gdb/i386-obsd-nat.c @V@/gdb/i3obsd-nat.c +@V@/gdb/i386-obsd-tdep.c @V@/gdb/i3obsd-tdep.c @V@/gdb/i386-sol2-nat.c @V@/gdb/i3sol2-nat.c @V@/gdb/i386-sol2-tdep.c @V@/gdb/i3sol2-tdep.c @V@/gdb/ia64-aix-nat.c @V@/gdb/ia64ax-nat.c @@ -303,33 +303,33 @@ @V@/gdb/m2-exp.tab.c @V@/gdb/m2-exp_tab.c @V@/gdb/m32r-linux-nat.c @V@/gdb/m32rlnxnat.c @V@/gdb/m32r-linux-tdep.c @V@/gdb/m32rlnxtdep.c -@V@/gdb/m68klinux-nat.c @V@/gdb/m68kl-nat.c -@V@/gdb/m68klinux-tdep.c @V@/gdb/m68kl-tdep.c -@V@/gdb/m68kbsd-nat.c @V@/gdb/m68bsd-nat.c -@V@/gdb/m68kbsd-tdep.c @V@/gdb/m68bsd-tdep.c -@V@/gdb/m68knbsd-nat.c @V@/gdb/m6nbsd-nat.c -@V@/gdb/m68knbsd-tdep.c @V@/gdb/m6nbsd-tdep.c +@V@/gdb/m68k-linux-nat.c @V@/gdb/m68kl-nat.c +@V@/gdb/m68k-linux-tdep.c @V@/gdb/m68kl-tdep.c +@V@/gdb/m68k-bsd-nat.c @V@/gdb/m68bsd-nat.c +@V@/gdb/m68k-bsd-tdep.c @V@/gdb/m68bsd-tdep.c +@V@/gdb/m68k-nbsd-nat.c @V@/gdb/m6nbsd-nat.c +@V@/gdb/m68k-nbsd-tdep.c @V@/gdb/m6nbsd-tdep.c @V@/gdb/microblaze-rom.c @V@/gdb/mb-rom.c @V@/gdb/microblaze-linux-tdep.c @V@/gdb/mbl-tdep.c @V@/gdb/microblaze-tdep.h @V@/gdb/mb-tdep.h @V@/gdb/microblaze-tdep.c @V@/gdb/mb-tdep.c @V@/gdb/mips-linux-nat.c @V@/gdb/mipslnxnat.c @V@/gdb/mips-linux-tdep.c @V@/gdb/mipslnxtdep.c -@V@/gdb/mipsnbsd-nat.c @V@/gdb/mipsnbnat.c -@V@/gdb/mipsnbsd-tdep.c @V@/gdb/mipsnbtdep.c -@V@/gdb/mips64obsd-nat.c @V@/gdb/mipsobnat.c -@V@/gdb/mips64obsd-tdep.c @V@/gdb/mipsobtdep.c +@V@/gdb/mips-nbsd-nat.c @V@/gdb/mipsnbnat.c +@V@/gdb/mips-nbsd-tdep.c @V@/gdb/mipsnbtdep.c +@V@/gdb/mips64-obsd-nat.c @V@/gdb/mipsobnat.c +@V@/gdb/mips64-obsd-tdep.c @V@/gdb/mipsobtdep.c @V@/gdb/mn10300-linux-tdep.c @V@/gdb/mn10300linux-tdep.c -@V@/gdb/ns32knbsd-nat.c @V@/gdb/ns32nb-nat.c -@V@/gdb/ns32knbsd-tdep.c @V@/gdb/ns32nb-tdep.c +@V@/gdb/ns32k-nbsd-nat.c @V@/gdb/ns32nb-nat.c +@V@/gdb/ns32k-nbsd-tdep.c @V@/gdb/ns32nb-tdep.c @V@/gdb/objc-exp.tab.c @V@/gdb/objc-exp_tab.c @V@/gdb/p-exp.tab.c @V@/gdb/p-exp_tab.c @V@/gdb/ppc-linux-tdep.c @V@/gdb/ppc-lx-tdep.c @V@/gdb/ppc-linux-nat.c @V@/gdb/ppc-lx-nat.c -@V@/gdb/ppcnbsd-nat.c @V@/gdb/ppcnb-nat.c -@V@/gdb/ppcnbsd-tdep.c @V@/gdb/ppcnb-tdep.c -@V@/gdb/ppcobsd-nat.c @V@/gdb/ppcob-nat.c -@V@/gdb/ppcobsd-tdep.c @V@/gdb/ppcob-tdep.c +@V@/gdb/ppc-nbsd-nat.c @V@/gdb/ppcnb-nat.c +@V@/gdb/ppc-nbsd-tdep.c @V@/gdb/ppcnb-tdep.c +@V@/gdb/ppc-obsd-nat.c @V@/gdb/ppcob-nat.c +@V@/gdb/ppc-obsd-tdep.c @V@/gdb/ppcob-tdep.c @V@/gdb/regformats/arm-with-vfpv2.dat @V@/gdb/regformats/arm-wv2.dat @V@/gdb/regformats/arm-with-vfpv3.dat @V@/gdb/regformats/arm-wv3.dat @V@/gdb/regformats/arm-with-iwmmxt.dat @V@/gdb/regformats/arm-iwmmxt.dat @@ -373,17 +373,17 @@ @V@/gdb/remote-vx68.c @V@/gdb/rmt-vx68.c @V@/gdb/remote-vxmips.c @V@/gdb/rmt-vxmips.c @V@/gdb/remote-vxsparc.c @V@/gdb/rmt-vxsparc.c -@V@/gdb/sparc64fbsd-nat.c @V@/gdb/sp64fb-nat.c -@V@/gdb/sparc64fbsd-tdep.c @V@/gdb/sp64fb-tdep.c -@V@/gdb/sparc64nbsd-nat.c @V@/gdb/sp64nb-nat.c -@V@/gdb/sparc64nbsd-tdep.c @V@/gdb/sp64nb-tdep.c +@V@/gdb/sparc64-fbsd-nat.c @V@/gdb/sp64fb-nat.c +@V@/gdb/sparc64-fbsd-tdep.c @V@/gdb/sp64fb-tdep.c +@V@/gdb/sparc64-nbsd-nat.c @V@/gdb/sp64nb-nat.c +@V@/gdb/sparc64-nbsd-tdep.c @V@/gdb/sp64nb-tdep.c @V@/gdb/sparc64-linux-nat.c @V@/gdb/sp64lx-nat.c @V@/gdb/sparc64-linux-tdep.c @V@/gdb/sp64lx-tdep.c @V@/gdb/sparc64-nat.c @V@/gdb/sp64-nat.c @V@/gdb/sparc64-tdep.c @V@/gdb/sp64-tdep.c @V@/gdb/sparc64-sol2-tdep.c @V@/gdb/sp64s2-tdep.c -@V@/gdb/sparcnbsd-nat.c @V@/gdb/spnb-nat.c -@V@/gdb/sparcnbsd-tdep.c @V@/gdb/spnb-tdep.c +@V@/gdb/sparc-nbsd-nat.c @V@/gdb/spnb-nat.c +@V@/gdb/sparc-nbsd-tdep.c @V@/gdb/spnb-tdep.c @V@/gdb/sparc-linux-nat.c @V@/gdb/splx-nat.c @V@/gdb/sparc-linux-tdep.c @V@/gdb/splx-tdep.c @V@/gdb/sparc-sol2-nat.c @V@/gdb/spsol2-nat.c @@ -513,8 +513,8 @@ @V@/gdb/amd64-linux-nat.c @V@/gdb/amd64-lnat.c @V@/gdb/hppa-linux-tdep.c @V@/gdb/palnxtdep.c @V@/gdb/hppa-linux-nat.c @V@/gdb/palnxnat.c -@V@/gdb/hppanbsd-nat.c @V@/gdb/panbsd-nat.c -@V@/gdb/hppanbsd-tdep.c @V@/gdb/panbsd-tdep.c +@V@/gdb/hppa-nbsd-nat.c @V@/gdb/panbsd-nat.c +@V@/gdb/hppa-nbsd-tdep.c @V@/gdb/panbsd-tdep.c @V@/gdb/amd64-windows-nat.c @V@/gdb/amd64-wnat.c @V@/gdb/amd64-windows-tdep.c @V@/gdb/amd64-wtdep.c @V@/gdb/i386-windows-nat.c @V@/gdb/i386-wnat.c diff --git a/gdb/config/i386/fbsd.mh b/gdb/config/i386/fbsd.mh index 1db666072b9..69e0a8b617e 100644 --- a/gdb/config/i386/fbsd.mh +++ b/gdb/config/i386/fbsd.mh @@ -1,7 +1,7 @@ # Host: FreeBSD/i386 NATDEPFILES= fork-child.o inf-ptrace.o \ - fbsd-nat.o x86-nat.o x86-dregs.o x86bsd-nat.o i386bsd-nat.o \ - i386fbsd-nat.o bsd-kvm.o + fbsd-nat.o x86-nat.o x86-dregs.o x86-bsd-nat.o i386-bsd-nat.o \ + i386-fbsd-nat.o bsd-kvm.o NAT_FILE= nm-fbsd.h HAVE_NATIVE_GCORE_HOST = 1 diff --git a/gdb/config/i386/fbsd64.mh b/gdb/config/i386/fbsd64.mh index e196c00acfd..461ff9a9515 100644 --- a/gdb/config/i386/fbsd64.mh +++ b/gdb/config/i386/fbsd64.mh @@ -1,7 +1,7 @@ # Host: FreeBSD/amd64 NATDEPFILES= fork-child.o inf-ptrace.o \ - fbsd-nat.o amd64-nat.o amd64bsd-nat.o amd64fbsd-nat.o \ - bsd-kvm.o x86-nat.o x86-dregs.o x86bsd-nat.o + fbsd-nat.o amd64-nat.o amd64-bsd-nat.o amd64-fbsd-nat.o \ + bsd-kvm.o x86-nat.o x86-dregs.o x86-bsd-nat.o HAVE_NATIVE_GCORE_HOST = 1 LOADLIBES= -lkvm diff --git a/gdb/config/i386/i386gnu.mh b/gdb/config/i386/i386gnu.mh index f1c0c5fe6ba..24e817eff51 100644 --- a/gdb/config/i386/i386gnu.mh +++ b/gdb/config/i386/i386gnu.mh @@ -1,5 +1,5 @@ # Host: Intel 386 running the GNU Hurd -NATDEPFILES= i386gnu-nat.o gnu-nat.o \ +NATDEPFILES= i386-gnu-nat.o gnu-nat.o \ x86-nat.o x86-dregs.o fork-child.o \ notify_S.o process_reply_S.o msg_reply_S.o \ msg_U.o exc_request_U.o exc_request_S.o diff --git a/gdb/config/i386/i386sol2.mh b/gdb/config/i386/i386sol2.mh index 2f7c3c5f089..787a3c1234c 100644 --- a/gdb/config/i386/i386sol2.mh +++ b/gdb/config/i386/i386sol2.mh @@ -1,4 +1,4 @@ # Host: Solaris x86 -NATDEPFILES= fork-child.o i386v4-nat.o i386-sol2-nat.o \ +NATDEPFILES= fork-child.o i386-v4-nat.o i386-sol2-nat.o \ procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o HAVE_NATIVE_GCORE_HOST = 1 diff --git a/gdb/config/i386/nbsd64.mh b/gdb/config/i386/nbsd64.mh index 5fa369f8f98..91d21f34606 100644 --- a/gdb/config/i386/nbsd64.mh +++ b/gdb/config/i386/nbsd64.mh @@ -1,3 +1,3 @@ # Host: NetBSD/amd64 NATDEPFILES= fork-child.o inf-ptrace.o \ - nbsd-nat.o amd64-nat.o x86bsd-nat.o amd64bsd-nat.o amd64nbsd-nat.o + nbsd-nat.o amd64-nat.o x86-bsd-nat.o amd64-bsd-nat.o amd64-nbsd-nat.o diff --git a/gdb/config/i386/nbsdelf.mh b/gdb/config/i386/nbsdelf.mh index f8b9d6c9f13..5954b3f865a 100644 --- a/gdb/config/i386/nbsdelf.mh +++ b/gdb/config/i386/nbsdelf.mh @@ -1,5 +1,5 @@ # Host: NetBSD/i386 ELF NATDEPFILES= fork-child.o inf-ptrace.o \ - nbsd-nat.o x86bsd-nat.o i386bsd-nat.o i386nbsd-nat.o bsd-kvm.o + nbsd-nat.o x86-bsd-nat.o i386-bsd-nat.o i386-nbsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/i386/obsd.mh b/gdb/config/i386/obsd.mh index 3845d269ec0..fac72826bc6 100644 --- a/gdb/config/i386/obsd.mh +++ b/gdb/config/i386/obsd.mh @@ -1,5 +1,5 @@ # Host: OpenBSD/i386 ELF NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o \ - x86bsd-nat.o i386bsd-nat.o i386obsd-nat.o bsd-kvm.o + x86-bsd-nat.o i386-bsd-nat.o i386-obsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/i386/obsd64.mh b/gdb/config/i386/obsd64.mh index 2a8c42ce42f..51deea7ac9b 100644 --- a/gdb/config/i386/obsd64.mh +++ b/gdb/config/i386/obsd64.mh @@ -1,5 +1,5 @@ # Host: OpenBSD/amd64 NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o \ - amd64-nat.o x86bsd-nat.o amd64bsd-nat.o amd64obsd-nat.o bsd-kvm.o + amd64-nat.o x86-bsd-nat.o amd64-bsd-nat.o amd64-obsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/i386/sol2-64.mh b/gdb/config/i386/sol2-64.mh index 7a8304d6dfe..7a3ab73630c 100644 --- a/gdb/config/i386/sol2-64.mh +++ b/gdb/config/i386/sol2-64.mh @@ -1,4 +1,4 @@ # Host: Solaris x86_64 -NATDEPFILES= fork-child.o amd64-nat.o i386v4-nat.o i386-sol2-nat.o \ +NATDEPFILES= fork-child.o amd64-nat.o i386-v4-nat.o i386-sol2-nat.o \ procfs.o proc-api.o proc-events.o proc-flags.o proc-why.o HAVE_NATIVE_GCORE_HOST = 1 diff --git a/gdb/config/m68k/linux.mh b/gdb/config/m68k/linux.mh index 60d5ce4c186..7c1f4acf027 100644 --- a/gdb/config/m68k/linux.mh +++ b/gdb/config/m68k/linux.mh @@ -2,7 +2,7 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o \ - m68klinux-nat.o \ + m68k-linux-nat.o \ proc-service.o linux-thread-db.o \ linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \ linux-personality.o \ diff --git a/gdb/config/m68k/nbsdelf.mh b/gdb/config/m68k/nbsdelf.mh index f2d97a14292..1d00cbc01f6 100644 --- a/gdb/config/m68k/nbsdelf.mh +++ b/gdb/config/m68k/nbsdelf.mh @@ -1,4 +1,4 @@ # Host: NetBSD/m68k ELF -NATDEPFILES= m68kbsd-nat.o bsd-kvm.o fork-child.o inf-ptrace.o +NATDEPFILES= m68k-bsd-nat.o bsd-kvm.o fork-child.o inf-ptrace.o LOADLIBES= -lkvm diff --git a/gdb/config/m68k/obsd.mh b/gdb/config/m68k/obsd.mh index 7930e3b704b..902a24b6108 100644 --- a/gdb/config/m68k/obsd.mh +++ b/gdb/config/m68k/obsd.mh @@ -1,4 +1,4 @@ # Host: OpenBSD/m68k -NATDEPFILES= m68kbsd-nat.o bsd-kvm.o fork-child.o inf-ptrace.o +NATDEPFILES= m68k-bsd-nat.o bsd-kvm.o fork-child.o inf-ptrace.o LOADLIBES= -lkvm diff --git a/gdb/config/m88k/obsd.mh b/gdb/config/m88k/obsd.mh index 2978edfc492..3c4d8d58d97 100644 --- a/gdb/config/m88k/obsd.mh +++ b/gdb/config/m88k/obsd.mh @@ -1,2 +1,2 @@ # Host: OpenBSD/m88k -NATDEPFILES= fork-child.o inf-ptrace.o m88kbsd-nat.o +NATDEPFILES= fork-child.o inf-ptrace.o m88k-bsd-nat.o diff --git a/gdb/config/mips/nbsd.mh b/gdb/config/mips/nbsd.mh index b76df132b15..a80da955f33 100644 --- a/gdb/config/mips/nbsd.mh +++ b/gdb/config/mips/nbsd.mh @@ -1,2 +1,2 @@ # Host: NetBSD/mips -NATDEPFILES= fork-child.o inf-ptrace.o mipsnbsd-nat.o +NATDEPFILES= fork-child.o inf-ptrace.o mips-nbsd-nat.o diff --git a/gdb/config/mips/obsd64.mh b/gdb/config/mips/obsd64.mh index ed04f9eea3a..6aeac342e38 100644 --- a/gdb/config/mips/obsd64.mh +++ b/gdb/config/mips/obsd64.mh @@ -1,2 +1,2 @@ # Host: OpenBSD/mips64 -NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o mips64obsd-nat.o +NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o mips64-obsd-nat.o diff --git a/gdb/config/pa/nbsd.mh b/gdb/config/pa/nbsd.mh index 5cff6989e73..791cd9f32bb 100644 --- a/gdb/config/pa/nbsd.mh +++ b/gdb/config/pa/nbsd.mh @@ -1,2 +1,2 @@ # Host: NetBSD/hppa -NATDEPFILES= fork-child.o inf-ptrace.o nbsd-nat.o hppanbsd-nat.o +NATDEPFILES= fork-child.o inf-ptrace.o nbsd-nat.o hppa-nbsd-nat.o diff --git a/gdb/config/pa/obsd.mh b/gdb/config/pa/obsd.mh index 50a11921236..95dd416ac5e 100644 --- a/gdb/config/pa/obsd.mh +++ b/gdb/config/pa/obsd.mh @@ -1,2 +1,2 @@ # Host: OpenBSD/hppa -NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o hppaobsd-nat.o +NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o hppa-obsd-nat.o diff --git a/gdb/config/powerpc/fbsd.mh b/gdb/config/powerpc/fbsd.mh index 32ba4ae3fa6..3553acc0fff 100644 --- a/gdb/config/powerpc/fbsd.mh +++ b/gdb/config/powerpc/fbsd.mh @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . */ -NATDEPFILES= fbsd-nat.o fork-child.o inf-ptrace.o ppcfbsd-nat.o bsd-kvm.o +NATDEPFILES= fbsd-nat.o fork-child.o inf-ptrace.o ppc-fbsd-nat.o bsd-kvm.o HAVE_NATIVE_GCORE_HOST = 1 LOADLIBES= -lkvm diff --git a/gdb/config/powerpc/nbsd.mh b/gdb/config/powerpc/nbsd.mh index db0390c8070..f02a0f9070c 100644 --- a/gdb/config/powerpc/nbsd.mh +++ b/gdb/config/powerpc/nbsd.mh @@ -1,4 +1,4 @@ # Host: NetBSD/powerpc -NATDEPFILES= fork-child.o inf-ptrace.o ppcnbsd-nat.o bsd-kvm.o +NATDEPFILES= fork-child.o inf-ptrace.o ppc-nbsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/powerpc/obsd.mh b/gdb/config/powerpc/obsd.mh index 2af667a2f93..374325446a8 100644 --- a/gdb/config/powerpc/obsd.mh +++ b/gdb/config/powerpc/obsd.mh @@ -1,4 +1,4 @@ # Host: OpenBSD/powerpc -NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o ppcobsd-nat.o bsd-kvm.o +NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o ppc-obsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/sh/nbsd.mh b/gdb/config/sh/nbsd.mh index d5e67cbd6bc..14d7e8c35d4 100644 --- a/gdb/config/sh/nbsd.mh +++ b/gdb/config/sh/nbsd.mh @@ -1,2 +1,2 @@ # Host: NetBSD/sh -NATDEPFILES= fork-child.o inf-ptrace.o shnbsd-nat.o +NATDEPFILES= fork-child.o inf-ptrace.o sh-nbsd-nat.o diff --git a/gdb/config/sparc/fbsd.mh b/gdb/config/sparc/fbsd.mh index 2774efb6403..bdc272c1319 100644 --- a/gdb/config/sparc/fbsd.mh +++ b/gdb/config/sparc/fbsd.mh @@ -1,6 +1,6 @@ # Host: FreeBSD/sparc64 NATDEPFILES= fork-child.o inf-ptrace.o \ - fbsd-nat.o sparc-nat.o sparc64-nat.o sparc64fbsd-nat.o \ + fbsd-nat.o sparc-nat.o sparc64-nat.o sparc64-fbsd-nat.o \ bsd-kvm.o HAVE_NATIVE_GCORE_HOST = 1 diff --git a/gdb/config/sparc/nbsd64.mh b/gdb/config/sparc/nbsd64.mh index 056b74d4e6d..aa15b1dbfa8 100644 --- a/gdb/config/sparc/nbsd64.mh +++ b/gdb/config/sparc/nbsd64.mh @@ -1,5 +1,5 @@ # Host: NetBSD/sparc64 NATDEPFILES= fork-child.o inf-ptrace.o \ - sparc64nbsd-nat.o sparc-nat.o bsd-kvm.o + sparc64-nbsd-nat.o sparc-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/sparc/nbsdelf.mh b/gdb/config/sparc/nbsdelf.mh index 6bf898ff603..97d07b3d2dd 100644 --- a/gdb/config/sparc/nbsdelf.mh +++ b/gdb/config/sparc/nbsdelf.mh @@ -1,5 +1,5 @@ # Host: NetBSD/sparc ELF NATDEPFILES= fork-child.o inf-ptrace.o \ - sparc-nat.o sparcnbsd-nat.o bsd-kvm.o + sparc-nat.o sparc-nbsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/sparc/obsd64.mh b/gdb/config/sparc/obsd64.mh index d15e34dccc9..e9f2fb99db1 100644 --- a/gdb/config/sparc/obsd64.mh +++ b/gdb/config/sparc/obsd64.mh @@ -1,5 +1,5 @@ # Host: OpenBSD/sparc64 NATDEPFILES= fork-child.o inf-ptrace.o obsd-nat.o \ - sparc64obsd-nat.o sparc-nat.o bsd-kvm.o + sparc64-obsd-nat.o sparc-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/vax/nbsdelf.mh b/gdb/config/vax/nbsdelf.mh index dd9441bab25..bf0f0b9588d 100644 --- a/gdb/config/vax/nbsdelf.mh +++ b/gdb/config/vax/nbsdelf.mh @@ -1,5 +1,5 @@ # Host: NetBSD/vax ELF NATDEPFILES= fork-child.o inf-ptrace.o \ - vaxbsd-nat.o bsd-kvm.o + vax-bsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/config/vax/obsd.mh b/gdb/config/vax/obsd.mh index d4d444f7939..cef99d3e945 100644 --- a/gdb/config/vax/obsd.mh +++ b/gdb/config/vax/obsd.mh @@ -1,5 +1,5 @@ # Host: OpenBSD/vax NATDEPFILES= fork-child.o inf-ptrace.o \ - vaxbsd-nat.o bsd-kvm.o + vax-bsd-nat.o bsd-kvm.o LOADLIBES= -lkvm diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 79473c9dba0..3a1ea6ffc2e 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -59,18 +59,18 @@ alpha*-*-linux*) ;; alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu) # Target: FreeBSD/alpha - gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alphabsd-tdep.o \ - alphafbsd-tdep.o solib-svr4.o" + gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-bsd-tdep.o \ + alpha-fbsd-tdep.o solib-svr4.o" ;; alpha*-*-netbsd* | alpha*-*-knetbsd*-gnu) # Target: NetBSD/alpha - gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alphabsd-tdep.o \ - alphanbsd-tdep.o nbsd-tdep.o solib-svr4.o" + gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-bsd-tdep.o \ + alpha-nbsd-tdep.o nbsd-tdep.o solib-svr4.o" ;; alpha*-*-openbsd*) # Target: OpenBSD/alpha - gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alphabsd-tdep.o \ - alphanbsd-tdep.o alphaobsd-tdep.o nbsd-tdep.o \ + gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-bsd-tdep.o \ + alpha-nbsd-tdep.o alpha-obsd-tdep.o nbsd-tdep.o \ obsd-tdep.o solib-svr4.o" ;; alpha*-*-*) @@ -109,13 +109,13 @@ arm*-*-linux*) ;; arm*-*-netbsd* | arm*-*-knetbsd*-gnu) # Target: NetBSD/arm - gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o armnbsd-tdep.o \ + gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o arm-nbsd-tdep.o \ solib-svr4.o" ;; arm*-*-openbsd*) # Target: OpenBSD/arm - gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o armbsd-tdep.o \ - armobsd-tdep.o obsd-tdep.o solib-svr4.o" + gdb_target_obs="arm.o arm-get-next-pcs.o arm-tdep.o arm-bsd-tdep.o \ + arm-obsd-tdep.o obsd-tdep.o solib-svr4.o" ;; arm*-*-symbianelf*) # Target: SymbianOS/arm @@ -174,11 +174,11 @@ hppa*-*-linux*) ;; hppa*-*-netbsd*) # Target: NetBSD/hppa - gdb_target_obs="hppa-tdep.o hppabsd-tdep.o hppanbsd-tdep.o solib-svr4.o" + gdb_target_obs="hppa-tdep.o hppa-bsd-tdep.o hppa-nbsd-tdep.o solib-svr4.o" ;; hppa*-*-openbsd*) # Target: OpenBSD/hppa - gdb_target_obs="hppa-tdep.o hppabsd-tdep.o hppaobsd-tdep.o solib-svr4.o" + gdb_target_obs="hppa-tdep.o hppa-bsd-tdep.o hppa-obsd-tdep.o solib-svr4.o" ;; hppa*-*-*) # Target: HP PA-RISC @@ -200,17 +200,17 @@ i[34567]86-*-dicos*) ;; i[34567]86-*-freebsd* | i[34567]86-*-kfreebsd*-gnu) # Target: FreeBSD/i386 - gdb_target_obs="i386-tdep.o i387-tdep.o i386bsd-tdep.o i386fbsd-tdep.o \ + gdb_target_obs="i386-tdep.o i387-tdep.o i386-bsd-tdep.o i386-fbsd-tdep.o \ bsd-uthread.o fbsd-tdep.o solib-svr4.o" ;; i[34567]86-*-netbsd* | i[34567]86-*-knetbsd*-gnu) # Target: NetBSD/i386 - gdb_target_obs="i386-tdep.o i387-tdep.o i386bsd-tdep.o i386nbsd-tdep.o \ + gdb_target_obs="i386-tdep.o i387-tdep.o i386-bsd-tdep.o i386-nbsd-tdep.o \ nbsd-tdep.o solib-svr4.o" ;; i[34567]86-*-openbsd*) # Target: OpenBSD/i386 - gdb_target_obs="i386-tdep.o i387-tdep.o i386bsd-tdep.o i386obsd-tdep.o \ + gdb_target_obs="i386-tdep.o i387-tdep.o i386-bsd-tdep.o i386-obsd-tdep.o \ obsd-tdep.o bsd-uthread.o solib-svr4.o" ;; i[34567]86-*-nto*) @@ -242,7 +242,7 @@ i[34567]86-*-linux*) ;; i[34567]86-*-gnu*) # Target: Intel 386 running the GNU Hurd - gdb_target_obs="i386-tdep.o i387-tdep.o i386gnu-tdep.o solib-svr4.o" + gdb_target_obs="i386-tdep.o i387-tdep.o i386-gnu-tdep.o solib-svr4.o" ;; i[34567]86-*-cygwin*) # Target: Intel 386 running win32 @@ -321,17 +321,17 @@ fido-*-elf*) ;; m68*-*-linux*) # Target: Motorola m68k with a.out and ELF - gdb_target_obs="m68k-tdep.o m68klinux-tdep.o solib-svr4.o \ + gdb_target_obs="m68k-tdep.o m68k-linux-tdep.o solib-svr4.o \ linux-tdep.o glibc-tdep.o symfile-mem.o" build_gdbserver=yes ;; m68*-*-netbsd* | m68*-*-knetbsd*-gnu) # Target: NetBSD/m68k - gdb_target_obs="m68k-tdep.o m68kbsd-tdep.o solib-svr4.o" + gdb_target_obs="m68k-tdep.o m68k-bsd-tdep.o solib-svr4.o" ;; m68*-*-openbsd*) # Target: OpenBSD/m68k - gdb_target_obs="m68k-tdep.o m68kbsd-tdep.o solib-svr4.o" + gdb_target_obs="m68k-tdep.o m68k-bsd-tdep.o solib-svr4.o" ;; m88*-*-openbsd*) @@ -366,12 +366,12 @@ mips*-*-linux*) ;; mips*-*-netbsd* | mips*-*-knetbsd*-gnu) # Target: MIPS running NetBSD - gdb_target_obs="mips-tdep.o mipsnbsd-tdep.o solib-svr4.o nbsd-tdep.o" + gdb_target_obs="mips-tdep.o mips-nbsd-tdep.o solib-svr4.o nbsd-tdep.o" gdb_sim=../sim/mips/libsim.a ;; mips64*-*-openbsd*) # Target: OpenBSD/mips64 - gdb_target_obs="mips-tdep.o mips64obsd-tdep.o obsd-tdep.o solib-svr4.o" + gdb_target_obs="mips-tdep.o mips64-obsd-tdep.o obsd-tdep.o solib-svr4.o" ;; mips*-sde*-elf*) # Target: MIPS SDE @@ -424,20 +424,20 @@ nios2*-*-*) powerpc*-*-freebsd*) # Target: FreeBSD/powerpc gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc64-tdep.o \ - ppcfbsd-tdep.o fbsd-tdep.o solib-svr4.o \ + ppc-fbsd-tdep.o fbsd-tdep.o solib-svr4.o \ ravenscar-thread.o ppc-ravenscar-thread.o" ;; powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu) # Target: NetBSD/powerpc - gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppcnbsd-tdep.o \ + gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc-nbsd-tdep.o \ solib-svr4.o \ ravenscar-thread.o ppc-ravenscar-thread.o" gdb_sim=../sim/ppc/libsim.a ;; powerpc-*-openbsd*) # Target: OpenBSD/powerpc - gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppcobsd-tdep.o \ + gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc-obsd-tdep.o \ solib-svr4.o \ ravenscar-thread.o ppc-ravenscar-thread.o" ;; @@ -506,12 +506,12 @@ sh*-*-linux*) ;; sh*-*-netbsdelf* | sh*-*-knetbsd*-gnu) # Target: NetBSD/sh - gdb_target_obs="sh-tdep.o shnbsd-tdep.o solib-svr4.o" + gdb_target_obs="sh-tdep.o sh-nbsd-tdep.o solib-svr4.o" gdb_sim=../sim/sh/libsim.a ;; sh*-*-openbsd*) # Target: OpenBSD/sh - gdb_target_obs="sh-tdep.o sh64-tdep.o shnbsd-tdep.o solib-svr4.o" + gdb_target_obs="sh-tdep.o sh64-tdep.o sh-nbsd-tdep.o solib-svr4.o" ;; sh64-*-elf*) # Target: Renesas/Super-H 64 bit with simulator @@ -547,32 +547,32 @@ sparc64-*-linux*) ;; sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu) # Target: FreeBSD/sparc64 - gdb_target_obs="sparc-tdep.o sparc64-tdep.o sparc64fbsd-tdep.o \ + gdb_target_obs="sparc-tdep.o sparc64-tdep.o sparc64-fbsd-tdep.o \ fbsd-tdep.o solib-svr4.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; sparc-*-netbsd* | sparc-*-knetbsd*-gnu) # Target: NetBSD/sparc - gdb_target_obs="sparc-tdep.o sparcnbsd-tdep.o nbsd-tdep.o \ + gdb_target_obs="sparc-tdep.o sparc-nbsd-tdep.o nbsd-tdep.o \ solib-svr4.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; sparc64-*-netbsd* | sparc64-*-knetbsd*-gnu) # Target: NetBSD/sparc64 - gdb_target_obs="sparc64-tdep.o sparc64nbsd-tdep.o sparc-tdep.o \ - sparcnbsd-tdep.o nbsd-tdep.o solib-svr4.o \ + gdb_target_obs="sparc64-tdep.o sparc64-nbsd-tdep.o sparc-tdep.o \ + sparc-nbsd-tdep.o nbsd-tdep.o solib-svr4.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; sparc-*-openbsd*) # Target: OpenBSD/sparc - gdb_target_obs="sparc-tdep.o sparcnbsd-tdep.o sparcobsd-tdep.o \ + gdb_target_obs="sparc-tdep.o sparc-nbsd-tdep.o sparc-obsd-tdep.o \ nbsd-tdep.o obsd-tdep.o bsd-uthread.o solib-svr4.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; sparc64-*-openbsd*) # Target: OpenBSD/sparc64 - gdb_target_obs="sparc64-tdep.o sparc64nbsd-tdep.o sparc64obsd-tdep.o \ - sparc-tdep.o sparcnbsd-tdep.o sparcobsd-tdep.o \ + 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 \ nbsd-tdep.o obsd-tdep.o bsd-uthread.o solib-svr4.o \ ravenscar-thread.o sparc-ravenscar-thread.o" ;; @@ -643,11 +643,11 @@ v850*-*-elf | v850*-*-rtems*) vax-*-netbsd* | vax-*-knetbsd*-gnu) # Target: NetBSD/vax - gdb_target_obs="vax-tdep.o vaxnbsd-tdep.o solib-svr4.o" + gdb_target_obs="vax-tdep.o vax-nbsd-tdep.o solib-svr4.o" ;; vax-*-openbsd*) # Target: OpenBSD/vax - gdb_target_obs="vax-tdep.o vaxobsd-tdep.o" + gdb_target_obs="vax-tdep.o vax-obsd-tdep.o" ;; vax-*-*) # Target: VAX @@ -678,8 +678,8 @@ x86_64-*-linux*) ;; x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) # Target: FreeBSD/amd64 - gdb_target_obs="amd64-tdep.o amd64fbsd-tdep.o i386-tdep.o \ - i387-tdep.o i386bsd-tdep.o i386fbsd-tdep.o \ + gdb_target_obs="amd64-tdep.o amd64-fbsd-tdep.o i386-tdep.o \ + i387-tdep.o i386-bsd-tdep.o i386-fbsd-tdep.o \ bsd-uthread.o fbsd-tdep.o solib-svr4.o" ;; x86_64-*-mingw* | x86_64-*-cygwin*) @@ -691,17 +691,17 @@ x86_64-*-mingw* | x86_64-*-cygwin*) ;; x86_64-*-netbsd* | x86_64-*-knetbsd*-gnu) # Target: NetBSD/amd64 - gdb_target_obs="amd64-tdep.o amd64nbsd-tdep.o i386-tdep.o i387-tdep.o \ + gdb_target_obs="amd64-tdep.o amd64-nbsd-tdep.o i386-tdep.o i387-tdep.o \ nbsd-tdep.o solib-svr4.o" ;; x86_64-*-openbsd*) # Target: OpenBSD/amd64 - gdb_target_obs="amd64-tdep.o amd64obsd-tdep.o i386-tdep.o \ - i387-tdep.o i386bsd-tdep.o i386obsd-tdep.o \ + gdb_target_obs="amd64-tdep.o amd64-obsd-tdep.o i386-tdep.o \ + i387-tdep.o i386-bsd-tdep.o i386-obsd-tdep.o \ obsd-tdep.o bsd-uthread.o solib-svr4.o" ;; x86_64-*-rtems*) - gdb_target_obs="amd64-tdep.o i386-tdep.o i387-tdep.o i386bsd-tdep.o" + gdb_target_obs="amd64-tdep.o i386-tdep.o i387-tdep.o i386-bsd-tdep.o" ;; xtensa*-*-linux*) gdb_target=linux # Target: GNU/Linux Xtensa diff --git a/gdb/hppa-bsd-tdep.c b/gdb/hppa-bsd-tdep.c new file mode 100644 index 00000000000..2c581c48e4a --- /dev/null +++ b/gdb/hppa-bsd-tdep.c @@ -0,0 +1,141 @@ +/* Target-dependent code for HP PA-RISC BSD's. + + Copyright (C) 2004-2016 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 "objfiles.h" +#include "target.h" +#include "value.h" + +#include "elf/common.h" + +#include "hppa-tdep.h" +#include "hppa-bsd-tdep.h" +#include "dwarf2-frame.h" +#include "solib-svr4.h" + +static CORE_ADDR +hppabsd_find_global_pointer (struct gdbarch *gdbarch, struct value *function) +{ + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR faddr = value_as_address (function); + struct obj_section *faddr_sec; + gdb_byte buf[4]; + + /* Is this a plabel? If so, dereference it to get the Global Pointer + value. */ + if (faddr & 2) + { + if (target_read_memory ((faddr & ~3) + 4, buf, sizeof buf) == 0) + return extract_unsigned_integer (buf, sizeof buf, byte_order); + } + + /* If the address is in the .plt section, then the real function + hasn't yet been fixed up by the linker so we cannot determine the + Global Pointer for that function. */ + if (in_plt_section (faddr)) + return 0; + + faddr_sec = find_pc_section (faddr); + if (faddr_sec != NULL) + { + struct obj_section *sec; + + ALL_OBJFILE_OSECTIONS (faddr_sec->objfile, sec) + { + if (strcmp (sec->the_bfd_section->name, ".dynamic") == 0) + break; + } + + if (sec < faddr_sec->objfile->sections_end) + { + CORE_ADDR addr = obj_section_addr (sec); + CORE_ADDR endaddr = obj_section_endaddr (sec); + + while (addr < endaddr) + { + gdb_byte buf[4]; + LONGEST tag; + + if (target_read_memory (addr, buf, sizeof buf) != 0) + break; + + tag = extract_signed_integer (buf, sizeof buf, byte_order); + if (tag == DT_PLTGOT) + { + CORE_ADDR pltgot; + + if (target_read_memory (addr + 4, buf, sizeof buf) != 0) + break; + + /* The NetBSD/OpenBSD ld.so doesn't relocate DT_PLTGOT, so + we have to do it ourselves. */ + pltgot = extract_unsigned_integer (buf, sizeof buf, + byte_order); + pltgot += ANOFFSET (sec->objfile->section_offsets, + SECT_OFF_TEXT (sec->objfile)); + + return pltgot; + } + + if (tag == DT_NULL) + break; + + addr += 8; + } + } + } + + return 0; +} + + +static void +hppabsd_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, + struct dwarf2_frame_state_reg *reg, + struct frame_info *this_frame) +{ + if (regnum == HPPA_PCOQ_HEAD_REGNUM) + reg->how = DWARF2_FRAME_REG_RA; + else if (regnum == HPPA_SP_REGNUM) + reg->how = DWARF2_FRAME_REG_CFA; +} + +void +hppabsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* OpenBSD and NetBSD have a 64-bit 'long double'. */ + set_gdbarch_long_double_bit (gdbarch, 64); + set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); + + /* OpenBSD and NetBSD use ELF. */ + tdep->is_elf = 1; + tdep->find_global_pointer = hppabsd_find_global_pointer; + tdep->in_solib_call_trampoline = hppa_in_solib_call_trampoline; + set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code); + + /* OpenBSD and NetBSD use SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + /* Hook in the DWARF CFI frame unwinder. */ + dwarf2_frame_set_init_reg (gdbarch, hppabsd_dwarf2_frame_init_reg); + dwarf2_append_unwinders (gdbarch); +} diff --git a/gdb/hppa-bsd-tdep.h b/gdb/hppa-bsd-tdep.h new file mode 100644 index 00000000000..7d630a8c769 --- /dev/null +++ b/gdb/hppa-bsd-tdep.h @@ -0,0 +1,25 @@ +/* Target-dependent code for HP PA-RISC BSD's. + + Copyright (C) 2009-2016 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 HPPA_BSD_TDEP_H +#define HPPA_BSD_TDEP_H + +extern void hppabsd_init_abi (struct gdbarch_info, struct gdbarch *); + +#endif /* hppa-bsd-tdep.h */ diff --git a/gdb/hppa-nbsd-nat.c b/gdb/hppa-nbsd-nat.c new file mode 100644 index 00000000000..dd12eb01114 --- /dev/null +++ b/gdb/hppa-nbsd-nat.c @@ -0,0 +1,245 @@ +/* Native-dependent code for NetBSD/hppa. + + Copyright (C) 2008-2016 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" + +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 (regcache, regnum, regs + regnum * 4); + + regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); + regcache_raw_supply (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); + regcache_raw_supply (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); + regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + regcache_raw_supply (regcache, HPPA_IPSW_REGNUM, regs); + regcache_raw_supply (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); + regcache_raw_supply (regcache, HPPA_SR4_REGNUM + 1, regs + 37 * 4); + regcache_raw_supply (regcache, HPPA_SR4_REGNUM + 2, regs + 38 * 4); + regcache_raw_supply (regcache, HPPA_SR4_REGNUM + 3, regs + 39 * 4); + regcache_raw_supply (regcache, 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 (regcache, regnum, regs); + regcache_raw_supply (regcache, 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 (regcache, i, regs + i * 4); + } + + if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) + regcache_raw_collect (regcache, HPPA_IPSW_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache_raw_collect (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) + regcache_raw_collect (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) + regcache_raw_collect (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) + regcache_raw_collect (regcache, HPPA_IPSW_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM) + regcache_raw_collect (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 1) + regcache_raw_collect (regcache, HPPA_SR4_REGNUM + 1, regs + 37 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 2) + regcache_raw_collect (regcache, HPPA_SR4_REGNUM + 2, regs + 38 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 3) + regcache_raw_collect (regcache, HPPA_SR4_REGNUM + 3, regs + 39 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 4) + regcache_raw_collect (regcache, 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 (regcache, i, regs); + regcache_raw_collect (regcache, i + 1, regs + 4); + } + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +static void +hppanbsd_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) + +{ + if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -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, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -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). */ + +static void +hppanbsd_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + hppanbsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + hppanbsd_collect_fpregset (regcache, &fpregs, regnum); + + if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_hppanbsd_nat (void); + +void +_initialize_hppanbsd_nat (void) +{ + struct target_ops *t; + + /* Add some extra features to the ptrace target. */ + t = inf_ptrace_target (); + + t->to_fetch_registers = hppanbsd_fetch_registers; + t->to_store_registers = hppanbsd_store_registers; + + t->to_pid_to_exec_file = nbsd_pid_to_exec_file; + + add_target (t); +} diff --git a/gdb/hppa-nbsd-tdep.c b/gdb/hppa-nbsd-tdep.c new file mode 100644 index 00000000000..6165bb57a05 --- /dev/null +++ b/gdb/hppa-nbsd-tdep.c @@ -0,0 +1,218 @@ +/* Target-dependent code for NetBSD/hppa + + Copyright (C) 2008-2016 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" + +/* 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, -1 }, /* bb,>=,n %arg3, 30, 1f */ + { 0xd6e01c1e, -1 }, /* depwi 0,31,2,%arg3 */ + { 0x0ee81093, -1 }, /* ldw 4(%arg3), %r19 */ + { 0x0ee01097, -1 }, /* ldw 0(%arg3), %arg3 */ + /* 1: */ + { 0xe8404000, -1 }, /* blr %r0, %rp */ + { 0xeae0c002, -1 }, /* bv,n %r0(%arg3) */ + { 0x08000240, -1 }, /* nop */ + + { 0x0803025a, -1 }, /* copy %r3, %arg0 */ + { 0x20200801, -1 }, /* ldil -40000000, %r1 */ + { 0xe420e008, -1 }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ + { 0x34160268, -1 }, /* ldi 134, %t1 ; SYS_setcontext */ + + { 0x081c025a, -1 }, /* copy ret0, %arg0 */ + { 0x20200801, -1 }, /* ldil -40000000, %r1 */ + { 0xe420e008, -1 }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ + { 0x34160002, -1 }, /* ldi 1, %t1 ; SYS_exit */ + { TRAMP_SENTINEL_INSN, -1 } + }, + 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 (regcache, 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_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); + + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, hppanbsd_iterate_over_regset_sections); + + tramp_frame_prepend_unwinder (gdbarch, &hppanbsd_sigtramp_si4); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_hppanbsd_tdep; + +void +_initialize_hppanbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD_ELF, + hppanbsd_init_abi); +} diff --git a/gdb/hppa-obsd-nat.c b/gdb/hppa-obsd-nat.c new file mode 100644 index 00000000000..30683b19db1 --- /dev/null +++ b/gdb/hppa-obsd-nat.c @@ -0,0 +1,265 @@ +/* Native-dependent code for OpenBSD/hppa. + + Copyright (C) 2004-2016 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 "target.h" + +#include +#include +#include + +#include "hppa-tdep.h" +#include "inf-ptrace.h" + +#include "obsd-nat.h" + +static int +hppaobsd_gregset_supplies_p (int regnum) +{ + return (regnum >= HPPA_R0_REGNUM && regnum <= HPPA_CR27_REGNUM); +} + +static int +hppaobsd_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 +hppaobsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + gdb_byte zero[4] = { 0 }; + const char *regs = gregs; + int regnum; + + regcache_raw_supply (regcache, HPPA_R0_REGNUM, &zero); + for (regnum = HPPA_R1_REGNUM; regnum <= HPPA_R31_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); + + if (sizeof(struct reg) >= 46 * 4) + { + regcache_raw_supply (regcache, HPPA_IPSW_REGNUM, regs); + regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); + regcache_raw_supply (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); + regcache_raw_supply (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); + regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + regcache_raw_supply (regcache, HPPA_SR0_REGNUM, regs + 37 * 4); + regcache_raw_supply (regcache, HPPA_SR1_REGNUM, regs + 38 * 4); + regcache_raw_supply (regcache, HPPA_SR2_REGNUM, regs + 39 * 4); + regcache_raw_supply (regcache, HPPA_SR3_REGNUM, regs + 40 * 4); + regcache_raw_supply (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); + regcache_raw_supply (regcache, HPPA_SR5_REGNUM, regs + 42 * 4); + regcache_raw_supply (regcache, HPPA_SR6_REGNUM, regs + 43 * 4); + regcache_raw_supply (regcache, HPPA_SR7_REGNUM, regs + 44 * 4); + regcache_raw_supply (regcache, HPPA_CR26_REGNUM, regs + 45 * 4); + regcache_raw_supply (regcache, HPPA_CR27_REGNUM, regs + 46 * 4); + } + else + { + regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs); + regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); + regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); + } +} + +/* Supply the floating-point registers stored in FPREGS to REGCACHE. */ + +static void +hppaobsd_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 (regcache, regnum, regs); + regcache_raw_supply (regcache, regnum + 1, regs + 4); + } +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +hppaobsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = HPPA_R1_REGNUM; i <= HPPA_R31_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } + + if (sizeof(struct reg) >= 46 * 4) + { + if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) + regcache_raw_collect (regcache, HPPA_IPSW_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache_raw_collect (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) + regcache_raw_collect (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) + regcache_raw_collect (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + if (regnum == -1 || regnum == HPPA_SR0_REGNUM) + regcache_raw_collect (regcache, HPPA_SR0_REGNUM, regs + 37 * 4); + if (regnum == -1 || regnum == HPPA_SR1_REGNUM) + regcache_raw_collect (regcache, HPPA_SR1_REGNUM, regs + 38 * 4); + if (regnum == -1 || regnum == HPPA_SR2_REGNUM) + regcache_raw_collect (regcache, HPPA_SR2_REGNUM, regs + 39 * 4); + if (regnum == -1 || regnum == HPPA_SR3_REGNUM) + regcache_raw_collect (regcache, HPPA_SR3_REGNUM, regs + 40 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM) + regcache_raw_collect (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); + if (regnum == -1 || regnum == HPPA_SR5_REGNUM) + regcache_raw_collect (regcache, HPPA_SR5_REGNUM, regs + 42 * 4); + if (regnum == -1 || regnum == HPPA_SR6_REGNUM) + regcache_raw_collect (regcache, HPPA_SR6_REGNUM, regs + 43 * 4); + if (regnum == -1 || regnum == HPPA_SR7_REGNUM) + regcache_raw_collect (regcache, HPPA_SR7_REGNUM, regs + 44 * 4); + if (regnum == -1 || regnum == HPPA_CR26_REGNUM) + regcache_raw_collect (regcache, HPPA_CR26_REGNUM, regs + 45 * 4); + if (regnum == -1 || regnum == HPPA_CR27_REGNUM) + regcache_raw_collect (regcache, HPPA_CR27_REGNUM, regs + 46 * 4); + } + else + { + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache_raw_collect (regcache, HPPA_SAR_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); + } +} + +/* Collect the floating-point registers from REGCACHE and store them + in FPREGS. */ + +static void +hppaobsd_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 (regcache, i, regs); + regcache_raw_collect (regcache, i + 1, regs + 4); + } + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +static void +hppaobsd_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + if (regnum == -1 || hppaobsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + hppaobsd_supply_gregset (regcache, ®s); + } + + if (regnum == -1 || hppaobsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + hppaobsd_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). */ + +static void +hppaobsd_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + if (regnum == -1 || hppaobsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + hppaobsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || hppaobsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + hppaobsd_collect_fpregset (regcache, &fpregs, regnum); + + if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_hppaobsd_nat (void); + +void +_initialize_hppaobsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = hppaobsd_fetch_registers; + t->to_store_registers = hppaobsd_store_registers; + obsd_add_target (t); +} diff --git a/gdb/hppa-obsd-tdep.c b/gdb/hppa-obsd-tdep.c new file mode 100644 index 00000000000..65364fec338 --- /dev/null +++ b/gdb/hppa-obsd-tdep.c @@ -0,0 +1,195 @@ +/* Target-dependent code for OpenBSD/hppa + + Copyright (C) 2004-2016 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 "hppa-tdep.h" +#include "hppa-bsd-tdep.h" + +/* Core file support. */ + +/* Sizeof `struct reg' in . */ +#define HPPAOBSD_SIZEOF_GREGS (34 * 4) /* OpenBSD 5.1 and earlier. */ +#define HPPANBSD_SIZEOF_GREGS (46 * 4) /* NetBSD and OpenBSD 5.2 and later. */ + +/* Sizeof `struct fpreg' in . */ +#define HPPAOBSD_SIZEOF_FPREGS (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 +hppaobsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + gdb_byte zero[4] = { 0 }; + const gdb_byte *regs = (const gdb_byte *) gregs; + size_t offset; + int i; + + gdb_assert (len >= HPPAOBSD_SIZEOF_GREGS); + + if (regnum == -1 || regnum == HPPA_R0_REGNUM) + regcache_raw_supply (regcache, HPPA_R0_REGNUM, &zero); + for (i = HPPA_R1_REGNUM, offset = 4; i <= HPPA_R31_REGNUM; i++, offset += 4) + { + if (regnum == -1 || regnum == i) + regcache_raw_supply (regcache, i, regs + offset); + } + + if (len >= HPPANBSD_SIZEOF_GREGS) + { + if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) + regcache_raw_supply (regcache, HPPA_IPSW_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) + regcache_raw_supply (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); + if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) + regcache_raw_supply (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); + if (regnum == -1 || regnum == HPPA_SR0_REGNUM) + regcache_raw_supply (regcache, HPPA_SR0_REGNUM, regs + 37 * 4); + if (regnum == -1 || regnum == HPPA_SR1_REGNUM) + regcache_raw_supply (regcache, HPPA_SR1_REGNUM, regs + 38 * 4); + if (regnum == -1 || regnum == HPPA_SR2_REGNUM) + regcache_raw_supply (regcache, HPPA_SR2_REGNUM, regs + 39 * 4); + if (regnum == -1 || regnum == HPPA_SR3_REGNUM) + regcache_raw_supply (regcache, HPPA_SR3_REGNUM, regs + 40 * 4); + if (regnum == -1 || regnum == HPPA_SR4_REGNUM) + regcache_raw_supply (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); + if (regnum == -1 || regnum == HPPA_SR5_REGNUM) + regcache_raw_supply (regcache, HPPA_SR5_REGNUM, regs + 42 * 4); + if (regnum == -1 || regnum == HPPA_SR6_REGNUM) + regcache_raw_supply (regcache, HPPA_SR6_REGNUM, regs + 43 * 4); + if (regnum == -1 || regnum == HPPA_SR7_REGNUM) + regcache_raw_supply (regcache, HPPA_SR7_REGNUM, regs + 44 * 4); + if (regnum == -1 || regnum == HPPA_CR26_REGNUM) + regcache_raw_supply (regcache, HPPA_CR26_REGNUM, regs + 45 * 4); + if (regnum == -1 || regnum == HPPA_CR27_REGNUM) + regcache_raw_supply (regcache, HPPA_CR27_REGNUM, regs + 46 * 4); + } + else + { + if (regnum == -1 || regnum == HPPA_SAR_REGNUM) + regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs); + if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) + regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); + if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) + regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); + } +} + +/* 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 +hppaobsd_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + const gdb_byte *regs = (const gdb_byte *) fpregs; + int i; + + gdb_assert (len >= HPPAOBSD_SIZEOF_FPREGS); + + for (i = HPPA_FP0_REGNUM; i <= HPPA_FP31R_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + (i - HPPA_FP0_REGNUM) * 4); + } +} + +/* OpenBSD/hppa register sets. */ + +static const struct regset hppaobsd_gregset = +{ + NULL, + hppaobsd_supply_gregset, + NULL, + REGSET_VARIABLE_SIZE +}; + +static const struct regset hppaobsd_fpregset = +{ + NULL, + hppaobsd_supply_fpregset +}; + +/* Iterate over supported core file register note sections. */ + +static void +hppaobsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", HPPAOBSD_SIZEOF_GREGS, &hppaobsd_gregset, NULL, cb_data); + cb (".reg2", HPPAOBSD_SIZEOF_FPREGS, &hppaobsd_fpregset, NULL, cb_data); +} + + +static void +hppaobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* Obviously OpenBSD is BSD-based. */ + hppabsd_init_abi (info, gdbarch); + + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, hppaobsd_iterate_over_regset_sections); +} + + +/* OpenBSD uses uses the traditional NetBSD core file format, even for + ports that use ELF. */ +#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF + +static enum gdb_osabi +hppaobsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_CORE; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_hppabsd_tdep (void); + +void +_initialize_hppabsd_tdep (void) +{ + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_hppa, bfd_target_unknown_flavour, + hppaobsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_OPENBSD_ELF, + hppaobsd_init_abi); +} diff --git a/gdb/hppabsd-tdep.c b/gdb/hppabsd-tdep.c deleted file mode 100644 index a6feefbff46..00000000000 --- a/gdb/hppabsd-tdep.c +++ /dev/null @@ -1,141 +0,0 @@ -/* Target-dependent code for HP PA-RISC BSD's. - - Copyright (C) 2004-2016 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 "objfiles.h" -#include "target.h" -#include "value.h" - -#include "elf/common.h" - -#include "hppa-tdep.h" -#include "hppabsd-tdep.h" -#include "dwarf2-frame.h" -#include "solib-svr4.h" - -static CORE_ADDR -hppabsd_find_global_pointer (struct gdbarch *gdbarch, struct value *function) -{ - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR faddr = value_as_address (function); - struct obj_section *faddr_sec; - gdb_byte buf[4]; - - /* Is this a plabel? If so, dereference it to get the Global Pointer - value. */ - if (faddr & 2) - { - if (target_read_memory ((faddr & ~3) + 4, buf, sizeof buf) == 0) - return extract_unsigned_integer (buf, sizeof buf, byte_order); - } - - /* If the address is in the .plt section, then the real function - hasn't yet been fixed up by the linker so we cannot determine the - Global Pointer for that function. */ - if (in_plt_section (faddr)) - return 0; - - faddr_sec = find_pc_section (faddr); - if (faddr_sec != NULL) - { - struct obj_section *sec; - - ALL_OBJFILE_OSECTIONS (faddr_sec->objfile, sec) - { - if (strcmp (sec->the_bfd_section->name, ".dynamic") == 0) - break; - } - - if (sec < faddr_sec->objfile->sections_end) - { - CORE_ADDR addr = obj_section_addr (sec); - CORE_ADDR endaddr = obj_section_endaddr (sec); - - while (addr < endaddr) - { - gdb_byte buf[4]; - LONGEST tag; - - if (target_read_memory (addr, buf, sizeof buf) != 0) - break; - - tag = extract_signed_integer (buf, sizeof buf, byte_order); - if (tag == DT_PLTGOT) - { - CORE_ADDR pltgot; - - if (target_read_memory (addr + 4, buf, sizeof buf) != 0) - break; - - /* The NetBSD/OpenBSD ld.so doesn't relocate DT_PLTGOT, so - we have to do it ourselves. */ - pltgot = extract_unsigned_integer (buf, sizeof buf, - byte_order); - pltgot += ANOFFSET (sec->objfile->section_offsets, - SECT_OFF_TEXT (sec->objfile)); - - return pltgot; - } - - if (tag == DT_NULL) - break; - - addr += 8; - } - } - } - - return 0; -} - - -static void -hppabsd_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, - struct dwarf2_frame_state_reg *reg, - struct frame_info *this_frame) -{ - if (regnum == HPPA_PCOQ_HEAD_REGNUM) - reg->how = DWARF2_FRAME_REG_RA; - else if (regnum == HPPA_SP_REGNUM) - reg->how = DWARF2_FRAME_REG_CFA; -} - -void -hppabsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* OpenBSD and NetBSD have a 64-bit 'long double'. */ - set_gdbarch_long_double_bit (gdbarch, 64); - set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); - - /* OpenBSD and NetBSD use ELF. */ - tdep->is_elf = 1; - tdep->find_global_pointer = hppabsd_find_global_pointer; - tdep->in_solib_call_trampoline = hppa_in_solib_call_trampoline; - set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code); - - /* OpenBSD and NetBSD use SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); - - /* Hook in the DWARF CFI frame unwinder. */ - dwarf2_frame_set_init_reg (gdbarch, hppabsd_dwarf2_frame_init_reg); - dwarf2_append_unwinders (gdbarch); -} diff --git a/gdb/hppabsd-tdep.h b/gdb/hppabsd-tdep.h deleted file mode 100644 index f9e84927dc9..00000000000 --- a/gdb/hppabsd-tdep.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Target-dependent code for HP PA-RISC BSD's. - - Copyright (C) 2009-2016 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 HPPABSD_TDEP_H -#define HPPABSD_TDEP_H - -extern void hppabsd_init_abi (struct gdbarch_info, struct gdbarch *); - -#endif /* hppabsd-tdep.h */ diff --git a/gdb/hppanbsd-nat.c b/gdb/hppanbsd-nat.c deleted file mode 100644 index dd12eb01114..00000000000 --- a/gdb/hppanbsd-nat.c +++ /dev/null @@ -1,245 +0,0 @@ -/* Native-dependent code for NetBSD/hppa. - - Copyright (C) 2008-2016 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" - -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 (regcache, regnum, regs + regnum * 4); - - regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); - regcache_raw_supply (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); - regcache_raw_supply (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); - regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - regcache_raw_supply (regcache, HPPA_IPSW_REGNUM, regs); - regcache_raw_supply (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); - regcache_raw_supply (regcache, HPPA_SR4_REGNUM + 1, regs + 37 * 4); - regcache_raw_supply (regcache, HPPA_SR4_REGNUM + 2, regs + 38 * 4); - regcache_raw_supply (regcache, HPPA_SR4_REGNUM + 3, regs + 39 * 4); - regcache_raw_supply (regcache, 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 (regcache, regnum, regs); - regcache_raw_supply (regcache, 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 (regcache, i, regs + i * 4); - } - - if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) - regcache_raw_collect (regcache, HPPA_IPSW_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - - if (regnum == -1 || regnum == HPPA_SAR_REGNUM) - regcache_raw_collect (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) - regcache_raw_collect (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) - regcache_raw_collect (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) - regcache_raw_collect (regcache, HPPA_IPSW_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM) - regcache_raw_collect (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 1) - regcache_raw_collect (regcache, HPPA_SR4_REGNUM + 1, regs + 37 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 2) - regcache_raw_collect (regcache, HPPA_SR4_REGNUM + 2, regs + 38 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 3) - regcache_raw_collect (regcache, HPPA_SR4_REGNUM + 3, regs + 39 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM + 4) - regcache_raw_collect (regcache, 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 (regcache, i, regs); - regcache_raw_collect (regcache, i + 1, regs + 4); - } - } -} - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers (including the floating-point registers). */ - -static void -hppanbsd_fetch_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) - -{ - if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -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, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -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). */ - -static void -hppanbsd_store_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1 || hppanbsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - hppanbsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - } - - if (regnum == -1 || hppanbsd_fpregset_supplies_p (regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - hppanbsd_collect_fpregset (regcache, &fpregs, regnum); - - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_hppanbsd_nat (void); - -void -_initialize_hppanbsd_nat (void) -{ - struct target_ops *t; - - /* Add some extra features to the ptrace target. */ - t = inf_ptrace_target (); - - t->to_fetch_registers = hppanbsd_fetch_registers; - t->to_store_registers = hppanbsd_store_registers; - - t->to_pid_to_exec_file = nbsd_pid_to_exec_file; - - add_target (t); -} diff --git a/gdb/hppanbsd-tdep.c b/gdb/hppanbsd-tdep.c deleted file mode 100644 index 33d9ca8284d..00000000000 --- a/gdb/hppanbsd-tdep.c +++ /dev/null @@ -1,218 +0,0 @@ -/* Target-dependent code for NetBSD/hppa - - Copyright (C) 2008-2016 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 "hppabsd-tdep.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, -1 }, /* bb,>=,n %arg3, 30, 1f */ - { 0xd6e01c1e, -1 }, /* depwi 0,31,2,%arg3 */ - { 0x0ee81093, -1 }, /* ldw 4(%arg3), %r19 */ - { 0x0ee01097, -1 }, /* ldw 0(%arg3), %arg3 */ - /* 1: */ - { 0xe8404000, -1 }, /* blr %r0, %rp */ - { 0xeae0c002, -1 }, /* bv,n %r0(%arg3) */ - { 0x08000240, -1 }, /* nop */ - - { 0x0803025a, -1 }, /* copy %r3, %arg0 */ - { 0x20200801, -1 }, /* ldil -40000000, %r1 */ - { 0xe420e008, -1 }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ - { 0x34160268, -1 }, /* ldi 134, %t1 ; SYS_setcontext */ - - { 0x081c025a, -1 }, /* copy ret0, %arg0 */ - { 0x20200801, -1 }, /* ldil -40000000, %r1 */ - { 0xe420e008, -1 }, /* be,l 4(%sr7, %r1), %sr0, %r31 */ - { 0x34160002, -1 }, /* ldi 1, %t1 ; SYS_exit */ - { TRAMP_SENTINEL_INSN, -1 } - }, - 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 (regcache, 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_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); - - /* Core file support. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, hppanbsd_iterate_over_regset_sections); - - tramp_frame_prepend_unwinder (gdbarch, &hppanbsd_sigtramp_si4); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_hppanbsd_tdep; - -void -_initialize_hppanbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_NETBSD_ELF, - hppanbsd_init_abi); -} diff --git a/gdb/hppaobsd-nat.c b/gdb/hppaobsd-nat.c deleted file mode 100644 index 30683b19db1..00000000000 --- a/gdb/hppaobsd-nat.c +++ /dev/null @@ -1,265 +0,0 @@ -/* Native-dependent code for OpenBSD/hppa. - - Copyright (C) 2004-2016 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 "target.h" - -#include -#include -#include - -#include "hppa-tdep.h" -#include "inf-ptrace.h" - -#include "obsd-nat.h" - -static int -hppaobsd_gregset_supplies_p (int regnum) -{ - return (regnum >= HPPA_R0_REGNUM && regnum <= HPPA_CR27_REGNUM); -} - -static int -hppaobsd_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 -hppaobsd_supply_gregset (struct regcache *regcache, const void *gregs) -{ - gdb_byte zero[4] = { 0 }; - const char *regs = gregs; - int regnum; - - regcache_raw_supply (regcache, HPPA_R0_REGNUM, &zero); - for (regnum = HPPA_R1_REGNUM; regnum <= HPPA_R31_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, regs + regnum * 4); - - if (sizeof(struct reg) >= 46 * 4) - { - regcache_raw_supply (regcache, HPPA_IPSW_REGNUM, regs); - regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); - regcache_raw_supply (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); - regcache_raw_supply (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); - regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - regcache_raw_supply (regcache, HPPA_SR0_REGNUM, regs + 37 * 4); - regcache_raw_supply (regcache, HPPA_SR1_REGNUM, regs + 38 * 4); - regcache_raw_supply (regcache, HPPA_SR2_REGNUM, regs + 39 * 4); - regcache_raw_supply (regcache, HPPA_SR3_REGNUM, regs + 40 * 4); - regcache_raw_supply (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); - regcache_raw_supply (regcache, HPPA_SR5_REGNUM, regs + 42 * 4); - regcache_raw_supply (regcache, HPPA_SR6_REGNUM, regs + 43 * 4); - regcache_raw_supply (regcache, HPPA_SR7_REGNUM, regs + 44 * 4); - regcache_raw_supply (regcache, HPPA_CR26_REGNUM, regs + 45 * 4); - regcache_raw_supply (regcache, HPPA_CR27_REGNUM, regs + 46 * 4); - } - else - { - regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs); - regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); - regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); - } -} - -/* Supply the floating-point registers stored in FPREGS to REGCACHE. */ - -static void -hppaobsd_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 (regcache, regnum, regs); - regcache_raw_supply (regcache, regnum + 1, regs + 4); - } -} - -/* Collect the general-purpose registers from REGCACHE and store them - in GREGS. */ - -static void -hppaobsd_collect_gregset (const struct regcache *regcache, - void *gregs, int regnum) -{ - char *regs = gregs; - int i; - - for (i = HPPA_R1_REGNUM; i <= HPPA_R31_REGNUM; i++) - { - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, regs + i * 4); - } - - if (sizeof(struct reg) >= 46 * 4) - { - if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) - regcache_raw_collect (regcache, HPPA_IPSW_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_SAR_REGNUM) - regcache_raw_collect (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) - regcache_raw_collect (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) - regcache_raw_collect (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - if (regnum == -1 || regnum == HPPA_SR0_REGNUM) - regcache_raw_collect (regcache, HPPA_SR0_REGNUM, regs + 37 * 4); - if (regnum == -1 || regnum == HPPA_SR1_REGNUM) - regcache_raw_collect (regcache, HPPA_SR1_REGNUM, regs + 38 * 4); - if (regnum == -1 || regnum == HPPA_SR2_REGNUM) - regcache_raw_collect (regcache, HPPA_SR2_REGNUM, regs + 39 * 4); - if (regnum == -1 || regnum == HPPA_SR3_REGNUM) - regcache_raw_collect (regcache, HPPA_SR3_REGNUM, regs + 40 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM) - regcache_raw_collect (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); - if (regnum == -1 || regnum == HPPA_SR5_REGNUM) - regcache_raw_collect (regcache, HPPA_SR5_REGNUM, regs + 42 * 4); - if (regnum == -1 || regnum == HPPA_SR6_REGNUM) - regcache_raw_collect (regcache, HPPA_SR6_REGNUM, regs + 43 * 4); - if (regnum == -1 || regnum == HPPA_SR7_REGNUM) - regcache_raw_collect (regcache, HPPA_SR7_REGNUM, regs + 44 * 4); - if (regnum == -1 || regnum == HPPA_CR26_REGNUM) - regcache_raw_collect (regcache, HPPA_CR26_REGNUM, regs + 45 * 4); - if (regnum == -1 || regnum == HPPA_CR27_REGNUM) - regcache_raw_collect (regcache, HPPA_CR27_REGNUM, regs + 46 * 4); - } - else - { - if (regnum == -1 || regnum == HPPA_SAR_REGNUM) - regcache_raw_collect (regcache, HPPA_SAR_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache_raw_collect (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); - } -} - -/* Collect the floating-point registers from REGCACHE and store them - in FPREGS. */ - -static void -hppaobsd_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 (regcache, i, regs); - regcache_raw_collect (regcache, i + 1, regs + 4); - } - } -} - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers (including the floating-point registers). */ - -static void -hppaobsd_fetch_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1 || hppaobsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - hppaobsd_supply_gregset (regcache, ®s); - } - - if (regnum == -1 || hppaobsd_fpregset_supplies_p (regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - hppaobsd_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). */ - -static void -hppaobsd_store_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1 || hppaobsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - hppaobsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - } - - if (regnum == -1 || hppaobsd_fpregset_supplies_p (regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - hppaobsd_collect_fpregset (regcache, &fpregs, regnum); - - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_hppaobsd_nat (void); - -void -_initialize_hppaobsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = hppaobsd_fetch_registers; - t->to_store_registers = hppaobsd_store_registers; - obsd_add_target (t); -} diff --git a/gdb/hppaobsd-tdep.c b/gdb/hppaobsd-tdep.c deleted file mode 100644 index ad914e17f35..00000000000 --- a/gdb/hppaobsd-tdep.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Target-dependent code for OpenBSD/hppa - - Copyright (C) 2004-2016 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 "hppa-tdep.h" -#include "hppabsd-tdep.h" - -/* Core file support. */ - -/* Sizeof `struct reg' in . */ -#define HPPAOBSD_SIZEOF_GREGS (34 * 4) /* OpenBSD 5.1 and earlier. */ -#define HPPANBSD_SIZEOF_GREGS (46 * 4) /* NetBSD and OpenBSD 5.2 and later. */ - -/* Sizeof `struct fpreg' in . */ -#define HPPAOBSD_SIZEOF_FPREGS (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 -hppaobsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - gdb_byte zero[4] = { 0 }; - const gdb_byte *regs = (const gdb_byte *) gregs; - size_t offset; - int i; - - gdb_assert (len >= HPPAOBSD_SIZEOF_GREGS); - - if (regnum == -1 || regnum == HPPA_R0_REGNUM) - regcache_raw_supply (regcache, HPPA_R0_REGNUM, &zero); - for (i = HPPA_R1_REGNUM, offset = 4; i <= HPPA_R31_REGNUM; i++, offset += 4) - { - if (regnum == -1 || regnum == i) - regcache_raw_supply (regcache, i, regs + offset); - } - - if (len >= HPPANBSD_SIZEOF_GREGS) - { - if (regnum == -1 || regnum == HPPA_IPSW_REGNUM) - regcache_raw_supply (regcache, HPPA_IPSW_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_SAR_REGNUM) - regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs + 32 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_HEAD_REGNUM) - regcache_raw_supply (regcache, HPPA_PCSQ_HEAD_REGNUM, regs + 33 * 4); - if (regnum == -1 || regnum == HPPA_PCSQ_TAIL_REGNUM) - regcache_raw_supply (regcache, HPPA_PCSQ_TAIL_REGNUM, regs + 34 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 35 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 36 * 4); - if (regnum == -1 || regnum == HPPA_SR0_REGNUM) - regcache_raw_supply (regcache, HPPA_SR0_REGNUM, regs + 37 * 4); - if (regnum == -1 || regnum == HPPA_SR1_REGNUM) - regcache_raw_supply (regcache, HPPA_SR1_REGNUM, regs + 38 * 4); - if (regnum == -1 || regnum == HPPA_SR2_REGNUM) - regcache_raw_supply (regcache, HPPA_SR2_REGNUM, regs + 39 * 4); - if (regnum == -1 || regnum == HPPA_SR3_REGNUM) - regcache_raw_supply (regcache, HPPA_SR3_REGNUM, regs + 40 * 4); - if (regnum == -1 || regnum == HPPA_SR4_REGNUM) - regcache_raw_supply (regcache, HPPA_SR4_REGNUM, regs + 41 * 4); - if (regnum == -1 || regnum == HPPA_SR5_REGNUM) - regcache_raw_supply (regcache, HPPA_SR5_REGNUM, regs + 42 * 4); - if (regnum == -1 || regnum == HPPA_SR6_REGNUM) - regcache_raw_supply (regcache, HPPA_SR6_REGNUM, regs + 43 * 4); - if (regnum == -1 || regnum == HPPA_SR7_REGNUM) - regcache_raw_supply (regcache, HPPA_SR7_REGNUM, regs + 44 * 4); - if (regnum == -1 || regnum == HPPA_CR26_REGNUM) - regcache_raw_supply (regcache, HPPA_CR26_REGNUM, regs + 45 * 4); - if (regnum == -1 || regnum == HPPA_CR27_REGNUM) - regcache_raw_supply (regcache, HPPA_CR27_REGNUM, regs + 46 * 4); - } - else - { - if (regnum == -1 || regnum == HPPA_SAR_REGNUM) - regcache_raw_supply (regcache, HPPA_SAR_REGNUM, regs); - if (regnum == -1 || regnum == HPPA_PCOQ_HEAD_REGNUM) - regcache_raw_supply (regcache, HPPA_PCOQ_HEAD_REGNUM, regs + 32 * 4); - if (regnum == -1 || regnum == HPPA_PCOQ_TAIL_REGNUM) - regcache_raw_supply (regcache, HPPA_PCOQ_TAIL_REGNUM, regs + 33 * 4); - } -} - -/* 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 -hppaobsd_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *fpregs, size_t len) -{ - const gdb_byte *regs = (const gdb_byte *) fpregs; - int i; - - gdb_assert (len >= HPPAOBSD_SIZEOF_FPREGS); - - for (i = HPPA_FP0_REGNUM; i <= HPPA_FP31R_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + (i - HPPA_FP0_REGNUM) * 4); - } -} - -/* OpenBSD/hppa register sets. */ - -static const struct regset hppaobsd_gregset = -{ - NULL, - hppaobsd_supply_gregset, - NULL, - REGSET_VARIABLE_SIZE -}; - -static const struct regset hppaobsd_fpregset = -{ - NULL, - hppaobsd_supply_fpregset -}; - -/* Iterate over supported core file register note sections. */ - -static void -hppaobsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", HPPAOBSD_SIZEOF_GREGS, &hppaobsd_gregset, NULL, cb_data); - cb (".reg2", HPPAOBSD_SIZEOF_FPREGS, &hppaobsd_fpregset, NULL, cb_data); -} - - -static void -hppaobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* Obviously OpenBSD is BSD-based. */ - hppabsd_init_abi (info, gdbarch); - - /* Core file support. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, hppaobsd_iterate_over_regset_sections); -} - - -/* OpenBSD uses uses the traditional NetBSD core file format, even for - ports that use ELF. */ -#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF - -static enum gdb_osabi -hppaobsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_NETBSD_CORE; - - return GDB_OSABI_UNKNOWN; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_hppabsd_tdep (void); - -void -_initialize_hppabsd_tdep (void) -{ - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_hppa, bfd_target_unknown_flavour, - hppaobsd_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_hppa, 0, GDB_OSABI_OPENBSD_ELF, - hppaobsd_init_abi); -} diff --git a/gdb/i386-bsd-nat.c b/gdb/i386-bsd-nat.c new file mode 100644 index 00000000000..492bd775737 --- /dev/null +++ b/gdb/i386-bsd-nat.c @@ -0,0 +1,367 @@ +/* Native-dependent code for modern i386 BSD's. + + Copyright (C) 2000-2016 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 +#include + +#include "i386-tdep.h" +#include "i387-tdep.h" +#include "x86-bsd-nat.h" +#include "i386-bsd-nat.h" +#include "inf-ptrace.h" + + +/* In older BSD versions we cannot get at some of the segment + registers. FreeBSD for example didn't support the %fs and %gs + registers until the 3.0 release. We have autoconf checks for their + presence, and deal gracefully with their absence. */ + +/* Offset in `struct reg' where MEMBER is stored. */ +#define REG_OFFSET(member) offsetof (struct reg, member) + +/* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct + reg' where the GDB register REGNUM is stored. Unsupported + registers are marked with `-1'. */ +static int i386bsd_r_reg_offset[] = +{ + REG_OFFSET (r_eax), + REG_OFFSET (r_ecx), + REG_OFFSET (r_edx), + REG_OFFSET (r_ebx), + REG_OFFSET (r_esp), + REG_OFFSET (r_ebp), + REG_OFFSET (r_esi), + REG_OFFSET (r_edi), + REG_OFFSET (r_eip), + REG_OFFSET (r_eflags), + REG_OFFSET (r_cs), + REG_OFFSET (r_ss), + REG_OFFSET (r_ds), + REG_OFFSET (r_es), +#ifdef HAVE_STRUCT_REG_R_FS + REG_OFFSET (r_fs), +#else + -1, +#endif +#ifdef HAVE_STRUCT_REG_R_GS + REG_OFFSET (r_gs) +#else + -1 +#endif +}; + +/* Macro to determine if a register is fetched with PT_GETREGS. */ +#define GETREGS_SUPPLIES(regnum) \ + ((0 <= (regnum) && (regnum) <= 15)) + +#ifdef HAVE_PT_GETXMMREGS +/* Set to 1 if the kernel supports PT_GETXMMREGS. Initialized to -1 + so that we try PT_GETXMMREGS the first time around. */ +static int have_ptrace_xmmregs = -1; +#endif + + +/* Supply the general-purpose registers in GREGS, to REGCACHE. */ + +static void +i386bsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = (const char *) gregs; + int regnum; + + for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++) + { + int offset = i386bsd_r_reg_offset[regnum]; + + if (offset != -1) + regcache_raw_supply (regcache, regnum, regs + offset); + } +} + +/* Collect register REGNUM from REGCACHE and store its contents in + GREGS. If REGNUM is -1, collect and store all appropriate + registers. */ + +static void +i386bsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = (char *) gregs; + int i; + + for (i = 0; i < ARRAY_SIZE (i386bsd_r_reg_offset); i++) + { + if (regnum == -1 || regnum == i) + { + int offset = i386bsd_r_reg_offset[i]; + + if (offset != -1) + regcache_raw_collect (regcache, i, regs + offset); + } + } +} + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating point registers). */ + +static void +i386bsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + if (regnum == -1 || GETREGS_SUPPLIES (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + i386bsd_supply_gregset (regcache, ®s); + if (regnum != -1) + return; + } + + if (regnum == -1 || regnum >= I386_ST0_REGNUM) + { + struct fpreg fpregs; +#ifdef HAVE_PT_GETXMMREGS + char xmmregs[512]; +#endif + +#ifdef PT_GETXSTATE_INFO + if (x86bsd_xsave_len != 0) + { + void *xstateregs; + + xstateregs = alloca (x86bsd_xsave_len); + if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) + perror_with_name (_("Couldn't get extended state status")); + + i387_supply_xsave (regcache, -1, xstateregs); + return; + } +#endif + +#ifdef HAVE_PT_GETXMMREGS + if (have_ptrace_xmmregs != 0 + && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) + { + have_ptrace_xmmregs = 1; + i387_supply_fxsave (regcache, -1, xmmregs); + } + else + { + have_ptrace_xmmregs = 0; +#endif + if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + i387_supply_fsave (regcache, -1, &fpregs); +#ifdef HAVE_PT_GETXMMREGS + } +#endif + } +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers (including the floating point registers). */ + +static void +i386bsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + if (regnum == -1 || GETREGS_SUPPLIES (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + i386bsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + + if (regnum != -1) + return; + } + + if (regnum == -1 || regnum >= I386_ST0_REGNUM) + { + struct fpreg fpregs; +#ifdef HAVE_PT_GETXMMREGS + char xmmregs[512]; +#endif + +#ifdef PT_GETXSTATE_INFO + if (x86bsd_xsave_len != 0) + { + void *xstateregs; + + xstateregs = alloca (x86bsd_xsave_len); + if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) + perror_with_name (_("Couldn't get extended state status")); + + i387_collect_xsave (regcache, -1, xstateregs, 0); + + if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xstateregs, x86bsd_xsave_len) == -1) + perror_with_name (_("Couldn't write extended state status")); + return; + } +#endif + +#ifdef HAVE_PT_GETXMMREGS + if (have_ptrace_xmmregs != 0 + && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) + { + have_ptrace_xmmregs = 1; + + i387_collect_fxsave (regcache, regnum, xmmregs); + + if (ptrace (PT_SETXMMREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) xmmregs, 0) == -1) + perror_with_name (_("Couldn't write XMM registers")); + } + else + { + have_ptrace_xmmregs = 0; +#endif + if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + i387_collect_fsave (regcache, regnum, &fpregs); + + if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); +#ifdef HAVE_PT_GETXMMREGS + } +#endif + } +} + +/* Create a prototype *BSD/i386 target. The client can override it + with local methods. */ + +struct target_ops * +i386bsd_target (void) +{ + struct target_ops *t; + + t = x86bsd_target (); + t->to_fetch_registers = i386bsd_fetch_inferior_registers; + t->to_store_registers = i386bsd_store_inferior_registers; + return t; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_i386bsd_nat (void); + +void +_initialize_i386bsd_nat (void) +{ + int offset; + + /* To support the recognition of signal handlers, i386-bsd-tdep.c + hardcodes some constants. Inclusion of this file means that we + are compiling a native debugger, which means that we can use the + system header files and sysctl(3) to get at the relevant + information. */ + +#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011 +#define SC_REG_OFFSET i386fbsd4_sc_reg_offset +#elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005 +#define SC_REG_OFFSET i386fbsd_sc_reg_offset +#elif defined (NetBSD) || defined (__NetBSD_Version__) +#define SC_REG_OFFSET i386nbsd_sc_reg_offset +#elif defined (OpenBSD) +#define SC_REG_OFFSET i386obsd_sc_reg_offset +#endif + +#ifdef SC_REG_OFFSET + + /* We only check the program counter, stack pointer and frame + pointer since these members of `struct sigcontext' are essential + for providing backtraces. More checks could be added, but would + involve adding configure checks for the appropriate structure + members, since older BSD's don't provide all of them. */ + +#define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM] +#define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM] +#define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM] + + /* Override the default value for the offset of the program counter + in the sigcontext structure. */ + offset = offsetof (struct sigcontext, sc_pc); + + if (SC_PC_OFFSET != offset) + { + warning (_("\ +offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\ +Please report this to ."), + offset, SC_PC_OFFSET); + } + + SC_PC_OFFSET = offset; + + /* Likewise for the stack pointer. */ + offset = offsetof (struct sigcontext, sc_sp); + + if (SC_SP_OFFSET != offset) + { + warning (_("\ +offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\ +Please report this to ."), + offset, SC_SP_OFFSET); + } + + SC_SP_OFFSET = offset; + + /* And the frame pointer. */ + offset = offsetof (struct sigcontext, sc_fp); + + if (SC_FP_OFFSET != offset) + { + warning (_("\ +offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\ +Please report this to ."), + offset, SC_FP_OFFSET); + } + + SC_FP_OFFSET = offset; + +#endif /* SC_REG_OFFSET */ +} diff --git a/gdb/i386-bsd-nat.h b/gdb/i386-bsd-nat.h new file mode 100644 index 00000000000..a0291a0a030 --- /dev/null +++ b/gdb/i386-bsd-nat.h @@ -0,0 +1,28 @@ +/* Native-dependent code for modern i386 BSD's. + + Copyright (C) 2004-2016 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 I386_BSD_NAT_H +#define I386_BSD_NAT_H + +/* Create a prototype *BSD/i386 target. The client can override it + with local methods. */ + +extern struct target_ops *i386bsd_target (void); + +#endif /* i386-bsd-nat.h */ diff --git a/gdb/i386-bsd-tdep.c b/gdb/i386-bsd-tdep.c new file mode 100644 index 00000000000..15809b3b9a6 --- /dev/null +++ b/gdb/i386-bsd-tdep.c @@ -0,0 +1,123 @@ +/* Target-dependent code for i386 BSD's. + + Copyright (C) 2001-2016 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 "osabi.h" + +#include "i386-tdep.h" + +/* Support for signal handlers. */ + +/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the + address of the associated sigcontext structure. */ + +static CORE_ADDR +i386bsd_sigcontext_addr (struct frame_info *this_frame) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + gdb_byte buf[4]; + CORE_ADDR sp; + + get_frame_register (this_frame, I386_ESP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 4, byte_order); + + return read_memory_unsigned_integer (sp + 8, 4, byte_order); +} + + +/* Support for shared libraries. */ + +/* Traditional BSD (4.3 BSD, still used for BSDI and 386BSD). */ + +/* From . */ +int i386bsd_sc_reg_offset[] = +{ + -1, /* %eax */ + -1, /* %ecx */ + -1, /* %edx */ + -1, /* %ebx */ + 8 + 0 * 4, /* %esp */ + 8 + 1 * 4, /* %ebp */ + -1, /* %esi */ + -1, /* %edi */ + 8 + 3 * 4, /* %eip */ + 8 + 4 * 4, /* %eflags */ + -1, /* %cs */ + -1, /* %ss */ + -1, /* %ds */ + -1, /* %es */ + -1, /* %fs */ + -1 /* %gs */ +}; + +void +i386bsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + tdep->jb_pc_offset = 0; + + tdep->sigtramp_start = 0xfdbfdfc0; + tdep->sigtramp_end = 0xfdbfe000; + tdep->sigcontext_addr = i386bsd_sigcontext_addr; + tdep->sc_reg_offset = i386bsd_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (i386bsd_sc_reg_offset); +} + + +static enum gdb_osabi +i386bsd_aout_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "a.out-i386-netbsd") == 0) + return GDB_OSABI_NETBSD_AOUT; + + if (strcmp (bfd_get_target (abfd), "a.out-i386-freebsd") == 0) + return GDB_OSABI_FREEBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + +static enum gdb_osabi +i386bsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_i386bsd_tdep (void); + +void +_initialize_i386bsd_tdep (void) +{ + gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_aout_flavour, + i386bsd_aout_osabi_sniffer); + + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_unknown_flavour, + i386bsd_core_osabi_sniffer); +} diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c new file mode 100644 index 00000000000..a9bf2b172a1 --- /dev/null +++ b/gdb/i386-fbsd-nat.c @@ -0,0 +1,197 @@ +/* Native-dependent code for FreeBSD/i386. + + Copyright (C) 2001-2016 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 "target.h" + +#include +#include +#include +#include + +#include "fbsd-nat.h" +#include "i386-tdep.h" +#include "x86-nat.h" +#include "x86-bsd-nat.h" +#include "i386-bsd-nat.h" + +/* Resume execution of the inferior process. If STEP is nonzero, + single-step it. If SIGNAL is nonzero, give it that signal. */ + +static void +i386fbsd_resume (struct target_ops *ops, + ptid_t ptid, int step, enum gdb_signal signal) +{ + pid_t pid = ptid_get_pid (ptid); + int request = PT_STEP; + + if (pid == -1) + /* Resume all threads. This only gets used in the non-threaded + case, where "resume all threads" and "resume inferior_ptid" are + the same. */ + pid = ptid_get_pid (inferior_ptid); + + if (!step) + { + struct regcache *regcache = get_current_regcache (); + ULONGEST eflags; + + /* Workaround for a bug in FreeBSD. Make sure that the trace + flag is off when doing a continue. There is a code path + through the kernel which leaves the flag set when it should + have been cleared. If a process has a signal pending (such + as SIGALRM) and we do a PT_STEP, the process never really has + a chance to run because the kernel needs to notify the + debugger that a signal is being sent. Therefore, the process + never goes through the kernel's trap() function which would + normally clear it. */ + + regcache_cooked_read_unsigned (regcache, I386_EFLAGS_REGNUM, + &eflags); + if (eflags & 0x0100) + regcache_cooked_write_unsigned (regcache, I386_EFLAGS_REGNUM, + eflags & ~0x0100); + + request = PT_CONTINUE; + } + + /* An addres of (caddr_t) 1 tells ptrace to continue from where it + was. (If GDB wanted it to start some other way, we have already + written a new PC value to the child.) */ + if (ptrace (request, pid, (caddr_t) 1, + gdb_signal_to_host (signal)) == -1) + perror_with_name (("ptrace")); +} + + +/* Support for debugging kernel virtual memory images. */ + +#include + +#include "bsd-kvm.h" + +static int +i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + /* The following is true for FreeBSD 4.7: + + The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs. + This accounts for all callee-saved registers specified by the + psABI and then some. Here %esp contains the stack pointer at the + point just after the call to cpu_switch(). 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_esp == 0) + return 0; + + pcb->pcb_esp += 4; + regcache_raw_supply (regcache, I386_EDI_REGNUM, &pcb->pcb_edi); + regcache_raw_supply (regcache, I386_ESI_REGNUM, &pcb->pcb_esi); + regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); + regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); + regcache_raw_supply (regcache, I386_EBX_REGNUM, &pcb->pcb_ebx); + regcache_raw_supply (regcache, I386_EIP_REGNUM, &pcb->pcb_eip); + regcache_raw_supply (regcache, I386_GS_REGNUM, &pcb->pcb_gs); + + return 1; +} + + +#ifdef PT_GETXSTATE_INFO +/* Implement the to_read_description method. */ + +static const struct target_desc * +i386fbsd_read_description (struct target_ops *ops) +{ + static int xsave_probed; + static uint64_t xcr0; + + if (!xsave_probed) + { + struct ptrace_xstate_info info; + + if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) + { + x86bsd_xsave_len = info.xsave_len; + xcr0 = info.xsave_mask; + } + xsave_probed = 1; + } + + if (x86bsd_xsave_len != 0) + { + return i386_target_description (xcr0); + } + else + return tdesc_i386; +} +#endif + +/* Prevent warning from -Wmissing-prototypes. */ +void _initialize_i386fbsd_nat (void); + +void +_initialize_i386fbsd_nat (void) +{ + struct target_ops *t; + + /* Add some extra features to the common *BSD/i386 target. */ + t = i386bsd_target (); + +#ifdef PT_GETXSTATE_INFO + t->to_read_description = i386fbsd_read_description; +#endif + + t->to_resume = i386fbsd_resume; + fbsd_nat_add_target (t); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (i386fbsd_supply_pcb); + +#ifdef KERN_PROC_SIGTRAMP + /* Normally signal frames are detected via i386fbsd_sigtramp_p. + However, FreeBSD 9.2 through 10.1 do not include the page holding + the signal code in core dumps. These releases do provide a + kern.proc.sigtramp. sysctl that returns the location of the + signal trampoline for a running process. We fetch the location + of the current (gdb) process and use this to identify signal + frames in core dumps from these releases. */ + { + int mib[4]; + struct kinfo_sigtramp kst; + size_t len; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_SIGTRAMP; + mib[3] = getpid (); + len = sizeof (kst); + if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) + { + i386fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start; + i386fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end; + } + } +#endif +} diff --git a/gdb/i386-fbsd-tdep.c b/gdb/i386-fbsd-tdep.c new file mode 100644 index 00000000000..a08523a6313 --- /dev/null +++ b/gdb/i386-fbsd-tdep.c @@ -0,0 +1,498 @@ +/* Target-dependent code for FreeBSD/i386. + + Copyright (C) 2003-2016 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 "gdbcore.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "i386-fbsd-tdep.h" +#include "x86-xstate.h" + +#include "i386-tdep.h" +#include "i387-tdep.h" +#include "bsd-uthread.h" +#include "fbsd-tdep.h" +#include "solib-svr4.h" + +/* Support for signal handlers. */ + +/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp + routine. */ + +/* FreeBSD/i386 supports three different signal trampolines, one for + versions before 4.0, a second for 4.x, and a third for 5.0 and + later. To complicate matters, FreeBSD/i386 binaries running under + an amd64 kernel use a different set of trampolines. These + trampolines differ from the i386 kernel trampolines in that they + omit a middle section that conditionally restores %gs. */ + +static const gdb_byte i386fbsd_sigtramp_start[] = +{ + 0x8d, 0x44, 0x24, 0x20, /* lea SIGF_UC(%esp),%eax */ + 0x50 /* pushl %eax */ +}; + +static const gdb_byte i386fbsd_sigtramp_middle[] = +{ + 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00, + /* testl $PSL_VM,UC_EFLAGS(%eax) */ + 0x75, 0x03, /* jne +3 */ + 0x8e, 0x68, 0x14 /* mov UC_GS(%eax),%gs */ +}; + +static const gdb_byte i386fbsd_sigtramp_end[] = +{ + 0xb8, 0xa1, 0x01, 0x00, 0x00, /* movl $SYS_sigreturn,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80 /* int $0x80 */ +}; + +static const gdb_byte i386fbsd_freebsd4_sigtramp_start[] = +{ + 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC4(%esp),%eax */ + 0x50 /* pushl %eax */ +}; + +static const gdb_byte i386fbsd_freebsd4_sigtramp_middle[] = +{ + 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00, + /* testl $PSL_VM,UC4_EFLAGS(%eax) */ + 0x75, 0x03, /* jne +3 */ + 0x8e, 0x68, 0x14 /* mov UC4_GS(%eax),%gs */ +}; + +static const gdb_byte i386fbsd_freebsd4_sigtramp_end[] = +{ + 0xb8, 0x58, 0x01, 0x00, 0x00, /* movl $344,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80 /* int $0x80 */ +}; + +static const gdb_byte i386fbsd_osigtramp_start[] = +{ + 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_SC(%esp),%eax */ + 0x50 /* pushl %eax */ +}; + +static const gdb_byte i386fbsd_osigtramp_middle[] = +{ + 0xf7, 0x40, 0x18, 0x00, 0x00, 0x02, 0x00, + /* testl $PSL_VM,SC_PS(%eax) */ + 0x75, 0x03, /* jne +3 */ + 0x8e, 0x68, 0x44 /* mov SC_GS(%eax),%gs */ +}; + +static const gdb_byte i386fbsd_osigtramp_end[] = +{ + 0xb8, 0x67, 0x00, 0x00, 0x00, /* movl $103,%eax */ + 0x50, /* pushl %eax */ + 0xcd, 0x80 /* int $0x80 */ +}; + +/* The three different trampolines are all the same size. */ +gdb_static_assert (sizeof i386fbsd_sigtramp_start + == sizeof i386fbsd_freebsd4_sigtramp_start); +gdb_static_assert (sizeof i386fbsd_sigtramp_start + == sizeof i386fbsd_osigtramp_start); +gdb_static_assert (sizeof i386fbsd_sigtramp_middle + == sizeof i386fbsd_freebsd4_sigtramp_middle); +gdb_static_assert (sizeof i386fbsd_sigtramp_middle + == sizeof i386fbsd_osigtramp_middle); +gdb_static_assert (sizeof i386fbsd_sigtramp_end + == sizeof i386fbsd_freebsd4_sigtramp_end); +gdb_static_assert (sizeof i386fbsd_sigtramp_end + == sizeof i386fbsd_osigtramp_end); + +/* We assume that the middle is the largest chunk below. */ +gdb_static_assert (sizeof i386fbsd_sigtramp_middle + > sizeof i386fbsd_sigtramp_start); +gdb_static_assert (sizeof i386fbsd_sigtramp_middle + > sizeof i386fbsd_sigtramp_end); + +static int +i386fbsd_sigtramp_p (struct frame_info *this_frame) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + gdb_byte buf[sizeof i386fbsd_sigtramp_middle]; + const gdb_byte *middle, *end; + + /* Look for a matching start. */ + if (!safe_frame_unwind_memory (this_frame, pc, buf, + sizeof i386fbsd_sigtramp_start)) + return 0; + if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start) + == 0) + { + middle = i386fbsd_sigtramp_middle; + end = i386fbsd_sigtramp_end; + } + else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start, + sizeof i386fbsd_freebsd4_sigtramp_start) == 0) + { + middle = i386fbsd_freebsd4_sigtramp_middle; + end = i386fbsd_freebsd4_sigtramp_end; + } + else if (memcmp (buf, i386fbsd_osigtramp_start, + sizeof i386fbsd_osigtramp_start) == 0) + { + middle = i386fbsd_osigtramp_middle; + end = i386fbsd_osigtramp_end; + } + else + return 0; + + /* Since the end is shorter than the middle, check for a matching end + next. */ + pc += sizeof i386fbsd_sigtramp_start; + if (!safe_frame_unwind_memory (this_frame, pc, buf, + sizeof i386fbsd_sigtramp_end)) + return 0; + if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) == 0) + return 1; + + /* If the end didn't match, check for a matching middle. */ + if (!safe_frame_unwind_memory (this_frame, pc, buf, + sizeof i386fbsd_sigtramp_middle)) + return 0; + if (memcmp (buf, middle, sizeof i386fbsd_sigtramp_middle) != 0) + return 0; + + /* The middle matched, check for a matching end. */ + pc += sizeof i386fbsd_sigtramp_middle; + if (!safe_frame_unwind_memory (this_frame, pc, buf, + sizeof i386fbsd_sigtramp_end)) + return 0; + if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) != 0) + return 0; + + return 1; +} + +/* FreeBSD 3.0-RELEASE or later. */ + +/* From . */ +static int i386fbsd_r_reg_offset[] = +{ + 9 * 4, 8 * 4, 7 * 4, 6 * 4, /* %eax, %ecx, %edx, %ebx */ + 15 * 4, 4 * 4, /* %esp, %ebp */ + 3 * 4, 2 * 4, /* %esi, %edi */ + 12 * 4, 14 * 4, /* %eip, %eflags */ + 13 * 4, 16 * 4, /* %cs, %ss */ + 1 * 4, 0 * 4, -1, -1 /* %ds, %es, %fs, %gs */ +}; + +/* Sigtramp routine location. */ +CORE_ADDR i386fbsd_sigtramp_start_addr; +CORE_ADDR i386fbsd_sigtramp_end_addr; + +/* From . */ +int i386fbsd_sc_reg_offset[] = +{ + 8 + 14 * 4, /* %eax */ + 8 + 13 * 4, /* %ecx */ + 8 + 12 * 4, /* %edx */ + 8 + 11 * 4, /* %ebx */ + 8 + 0 * 4, /* %esp */ + 8 + 1 * 4, /* %ebp */ + 8 + 10 * 4, /* %esi */ + 8 + 9 * 4, /* %edi */ + 8 + 3 * 4, /* %eip */ + 8 + 4 * 4, /* %eflags */ + 8 + 7 * 4, /* %cs */ + 8 + 8 * 4, /* %ss */ + 8 + 6 * 4, /* %ds */ + 8 + 5 * 4, /* %es */ + 8 + 15 * 4, /* %fs */ + 8 + 16 * 4 /* %gs */ +}; + +/* From /usr/src/lib/libc/i386/gen/_setjmp.S. */ +static int i386fbsd_jmp_buf_reg_offset[] = +{ + -1, /* %eax */ + -1, /* %ecx */ + -1, /* %edx */ + 1 * 4, /* %ebx */ + 2 * 4, /* %esp */ + 3 * 4, /* %ebp */ + 4 * 4, /* %esi */ + 5 * 4, /* %edi */ + 0 * 4 /* %eip */ +}; + +/* Get XSAVE extended state xcr0 from core dump. */ + +uint64_t +i386fbsd_core_read_xcr0 (bfd *abfd) +{ + asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate"); + uint64_t xcr0; + + if (xstate) + { + size_t size = bfd_section_size (abfd, xstate); + + /* Check extended state size. */ + if (size < X86_XSTATE_AVX_SIZE) + xcr0 = X86_XSTATE_SSE_MASK; + else + { + char contents[8]; + + if (! bfd_get_section_contents (abfd, xstate, contents, + I386_FBSD_XSAVE_XCR0_OFFSET, + 8)) + { + warning (_("Couldn't read `xcr0' bytes from " + "`.reg-xstate' section in core file.")); + return 0; + } + + xcr0 = bfd_get_64 (abfd, contents); + } + } + else + xcr0 = 0; + + return xcr0; +} + +/* Implement the core_read_description gdbarch method. */ + +static const struct target_desc * +i386fbsd_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, + bfd *abfd) +{ + return i386_target_description (i386fbsd_core_read_xcr0 (abfd)); +} + +/* Similar to i386_supply_fpregset, but use XSAVE extended state. */ + +static void +i386fbsd_supply_xstateregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *xstateregs, size_t len) +{ + i387_supply_xsave (regcache, regnum, xstateregs); +} + +/* Similar to i386_collect_fpregset, but use XSAVE extended state. */ + +static void +i386fbsd_collect_xstateregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *xstateregs, size_t len) +{ + i387_collect_xsave (regcache, regnum, xstateregs, 1); +} + +/* Register set definitions. */ + +static const struct regset i386fbsd_xstateregset = + { + NULL, + i386fbsd_supply_xstateregset, + i386fbsd_collect_xstateregset + }; + +/* Iterate over core file register note sections. */ + +static void +i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); + cb (".reg2", tdep->sizeof_fpregset, &i386_fpregset, NULL, cb_data); + + if (tdep->xcr0 & X86_XSTATE_AVX) + cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), + &i386fbsd_xstateregset, "XSAVE extended state", cb_data); +} + +static void +i386fbsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + gdb_byte buf[4]; + int i; + + gdb_assert (regnum >= -1); + + for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++) + { + if (i386fbsd_jmp_buf_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + read_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4); + regcache_raw_supply (regcache, i, buf); + } + } +} + +static void +i386fbsd_collect_uthread (const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + gdb_byte buf[4]; + int i; + + gdb_assert (regnum >= -1); + + for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++) + { + if (i386fbsd_jmp_buf_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + regcache_raw_collect (regcache, i, buf); + write_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4); + } + } +} + +static void +i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Obviously FreeBSD is BSD-based. */ + i386bsd_init_abi (info, gdbarch); + + /* FreeBSD has a different `struct reg', and reserves some space for + its FPU emulator in `struct fpreg'. */ + tdep->gregset_reg_offset = i386fbsd_r_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset); + tdep->sizeof_gregset = 18 * 4; + tdep->sizeof_fpregset = 176; + + /* FreeBSD uses -freg-struct-return by default. */ + tdep->struct_return = reg_struct_return; + + tdep->sigtramp_p = i386fbsd_sigtramp_p; + + /* FreeBSD uses a different memory layout. */ + tdep->sigtramp_start = i386fbsd_sigtramp_start_addr; + tdep->sigtramp_end = i386fbsd_sigtramp_end_addr; + + /* FreeBSD has a more complete `struct sigcontext'. */ + tdep->sc_reg_offset = i386fbsd_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset); + + /* FreeBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, i386fbsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, i386fbsd_collect_uthread); +} + +static void +i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* It's almost identical to FreeBSD a.out. */ + i386fbsdaout_init_abi (info, gdbarch); + + /* Except that it uses ELF. */ + i386_elf_init_abi (info, gdbarch); + + /* FreeBSD ELF uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +/* FreeBSD 4.0-RELEASE or later. */ + +/* From . */ +static int i386fbsd4_r_reg_offset[] = +{ + 10 * 4, 9 * 4, 8 * 4, 7 * 4, /* %eax, %ecx, %edx, %ebx */ + 16 * 4, 5 * 4, /* %esp, %ebp */ + 4 * 4, 3 * 4, /* %esi, %edi */ + 13 * 4, 15 * 4, /* %eip, %eflags */ + 14 * 4, 17 * 4, /* %cs, %ss */ + 2 * 4, 1 * 4, 0 * 4, 18 * 4 /* %ds, %es, %fs, %gs */ +}; + +/* From . */ +int i386fbsd4_sc_reg_offset[] = +{ + 20 + 11 * 4, /* %eax */ + 20 + 10 * 4, /* %ecx */ + 20 + 9 * 4, /* %edx */ + 20 + 8 * 4, /* %ebx */ + 20 + 17 * 4, /* %esp */ + 20 + 6 * 4, /* %ebp */ + 20 + 5 * 4, /* %esi */ + 20 + 4 * 4, /* %edi */ + 20 + 14 * 4, /* %eip */ + 20 + 16 * 4, /* %eflags */ + 20 + 15 * 4, /* %cs */ + 20 + 18 * 4, /* %ss */ + 20 + 3 * 4, /* %ds */ + 20 + 2 * 4, /* %es */ + 20 + 1 * 4, /* %fs */ + 20 + 0 * 4 /* %gs */ +}; + +static void +i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Generic FreeBSD support. */ + fbsd_init_abi (info, gdbarch); + + /* Inherit stuff from older releases. We assume that FreeBSD + 4.0-RELEASE always uses ELF. */ + i386fbsd_init_abi (info, gdbarch); + + /* FreeBSD 4.0 introduced a new `struct reg'. */ + tdep->gregset_reg_offset = i386fbsd4_r_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset); + tdep->sizeof_gregset = 19 * 4; + + /* FreeBSD 4.0 introduced a new `struct sigcontext'. */ + tdep->sc_reg_offset = i386fbsd4_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset); + + tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; + + /* Iterate over core file register note sections. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, i386fbsd_iterate_over_regset_sections); + + set_gdbarch_core_read_description (gdbarch, + i386fbsd_core_read_description); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_i386fbsd_tdep (void); + +void +_initialize_i386fbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_AOUT, + i386fbsdaout_init_abi); + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_ELF, + i386fbsd4_init_abi); +} diff --git a/gdb/i386-fbsd-tdep.h b/gdb/i386-fbsd-tdep.h new file mode 100644 index 00000000000..70224e68408 --- /dev/null +++ b/gdb/i386-fbsd-tdep.h @@ -0,0 +1,31 @@ +/* Target-dependent code for FreeBSD x86. + + Copyright (C) 2015-2016 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 I386_FBSD_TDEP_H +#define I386_FBSD_TDEP_H + +/* Get XSAVE extended state xcr0 from core dump. */ +extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd); + +/* The format of the XSAVE extended area is determined by hardware. + Cores store the XSAVE extended area in a NT_X86_XSTATE note that + matches the layout on Linux. */ +#define I386_FBSD_XSAVE_XCR0_OFFSET 464 + +#endif /* i386-fbsd-tdep.h */ diff --git a/gdb/i386-gnu-nat.c b/gdb/i386-gnu-nat.c new file mode 100644 index 00000000000..e14a181564f --- /dev/null +++ b/gdb/i386-gnu-nat.c @@ -0,0 +1,436 @@ +/* Low level interface to i386 running the GNU Hurd. + + Copyright (C) 1992-2016 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 "x86-nat.h" +#include "inferior.h" +#include "floatformat.h" +#include "regcache.h" + +#include +#include +#include +#include + +#include "i386-tdep.h" + +#include "gnu-nat.h" +#include "inf-child.h" +#include "i387-tdep.h" + +/* Offset to the thread_state_t location where REG is stored. */ +#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg) + +/* At REG_OFFSET[N] is the offset to the thread_state_t location where + the GDB register N is stored. */ +static int reg_offset[] = +{ + REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx), + REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi), + REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss), + REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs) +}; + +#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum]) + + +/* Get the whole floating-point state of THREAD and record the values + of the corresponding (pseudo) registers. */ + +static void +fetch_fpregs (struct regcache *regcache, struct proc *thread) +{ + mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; + struct i386_float_state state; + error_t err; + + err = thread_get_state (thread->port, i386_FLOAT_STATE, + (thread_state_t) &state, &count); + if (err) + { + warning (_("Couldn't fetch floating-point state from %s"), + proc_string (thread)); + return; + } + + if (!state.initialized) + { + /* The floating-point state isn't initialized. */ + i387_supply_fsave (regcache, -1, NULL); + } + else + { + /* Supply the floating-point registers. */ + i387_supply_fsave (regcache, -1, state.hw_state); + } +} + +/* Fetch register REGNO, or all regs if REGNO is -1. */ +static void +gnu_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + struct proc *thread; + + /* Make sure we know about new threads. */ + inf_update_procs (gnu_current_inf); + + thread = inf_tid_to_thread (gnu_current_inf, + ptid_get_lwp (inferior_ptid)); + if (!thread) + error (_("Can't fetch registers from thread %s: No such thread"), + target_pid_to_str (inferior_ptid)); + + if (regno < I386_NUM_GREGS || regno == -1) + { + thread_state_t state; + + /* This does the dirty work for us. */ + state = proc_get_state (thread, 0); + if (!state) + { + warning (_("Couldn't fetch registers from %s"), + proc_string (thread)); + return; + } + + if (regno == -1) + { + int i; + + proc_debug (thread, "fetching all register"); + + for (i = 0; i < I386_NUM_GREGS; i++) + regcache_raw_supply (regcache, i, REG_ADDR (state, i)); + thread->fetched_regs = ~0; + } + else + { + proc_debug (thread, "fetching register %s", + gdbarch_register_name (get_regcache_arch (regcache), + regno)); + + regcache_raw_supply (regcache, regno, + REG_ADDR (state, regno)); + thread->fetched_regs |= (1 << regno); + } + } + + if (regno >= I386_NUM_GREGS || regno == -1) + { + proc_debug (thread, "fetching floating-point registers"); + + fetch_fpregs (regcache, thread); + } +} + + +/* Store the whole floating-point state into THREAD using information + from the corresponding (pseudo) registers. */ +static void +store_fpregs (const struct regcache *regcache, struct proc *thread, int regno) +{ + mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; + struct i386_float_state state; + error_t err; + + err = thread_get_state (thread->port, i386_FLOAT_STATE, + (thread_state_t) &state, &count); + if (err) + { + warning (_("Couldn't fetch floating-point state from %s"), + proc_string (thread)); + return; + } + + /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow + take into account DEPRECATED_REGISTER_VALID like the old code did? */ + i387_collect_fsave (regcache, regno, state.hw_state); + + err = thread_set_state (thread->port, i386_FLOAT_STATE, + (thread_state_t) &state, i386_FLOAT_STATE_COUNT); + if (err) + { + warning (_("Couldn't store floating-point state into %s"), + proc_string (thread)); + return; + } +} + +/* Store at least register REGNO, or all regs if REGNO == -1. */ +static void +gnu_store_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + struct proc *thread; + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + /* Make sure we know about new threads. */ + inf_update_procs (gnu_current_inf); + + thread = inf_tid_to_thread (gnu_current_inf, + ptid_get_lwp (inferior_ptid)); + if (!thread) + error (_("Couldn't store registers into thread %s: No such thread"), + target_pid_to_str (inferior_ptid)); + + if (regno < I386_NUM_GREGS || regno == -1) + { + thread_state_t state; + thread_state_data_t old_state; + int was_aborted = thread->aborted; + int was_valid = thread->state_valid; + int trace; + + if (!was_aborted && was_valid) + memcpy (&old_state, &thread->state, sizeof (old_state)); + + state = proc_get_state (thread, 1); + if (!state) + { + warning (_("Couldn't store registers into %s"), + proc_string (thread)); + return; + } + + /* Save the T bit. We might try to restore the %eflags register + below, but changing the T bit would seriously confuse GDB. */ + trace = ((struct i386_thread_state *)state)->efl & 0x100; + + if (!was_aborted && was_valid) + /* See which registers have changed after aborting the thread. */ + { + int check_regno; + + for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++) + if ((thread->fetched_regs & (1 << check_regno)) + && memcpy (REG_ADDR (&old_state, check_regno), + REG_ADDR (state, check_regno), + register_size (gdbarch, check_regno))) + /* Register CHECK_REGNO has changed! Ack! */ + { + warning (_("Register %s changed after the thread was aborted"), + gdbarch_register_name (gdbarch, check_regno)); + if (regno >= 0 && regno != check_regno) + /* Update GDB's copy of the register. */ + regcache_raw_supply (regcache, check_regno, + REG_ADDR (state, check_regno)); + else + warning (_("... also writing this register! " + "Suspicious...")); + } + } + + if (regno == -1) + { + int i; + + proc_debug (thread, "storing all registers"); + + for (i = 0; i < I386_NUM_GREGS; i++) + if (REG_VALID == regcache_register_status (regcache, i)) + regcache_raw_collect (regcache, i, REG_ADDR (state, i)); + } + else + { + proc_debug (thread, "storing register %s", + gdbarch_register_name (gdbarch, regno)); + + gdb_assert (REG_VALID == regcache_register_status (regcache, regno)); + regcache_raw_collect (regcache, regno, REG_ADDR (state, regno)); + } + + /* Restore the T bit. */ + ((struct i386_thread_state *)state)->efl &= ~0x100; + ((struct i386_thread_state *)state)->efl |= trace; + } + + if (regno >= I386_NUM_GREGS || regno == -1) + { + proc_debug (thread, "storing floating-point registers"); + + store_fpregs (regcache, thread, regno); + } +} + + +/* Support for debug registers. */ + +#ifdef i386_DEBUG_STATE +/* Get debug registers for thread THREAD. */ + +static void +i386_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread) +{ + mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT; + error_t err; + + err = thread_get_state (thread->port, i386_DEBUG_STATE, + (thread_state_t) regs, &count); + if (err != 0 || count != i386_DEBUG_STATE_COUNT) + warning (_("Couldn't fetch debug state from %s"), + proc_string (thread)); +} + +/* Set debug registers for thread THREAD. */ + +static void +i386_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread) +{ + error_t err; + + err = thread_set_state (thread->port, i386_DEBUG_STATE, + (thread_state_t) regs, i386_DEBUG_STATE_COUNT); + if (err != 0) + warning (_("Couldn't store debug state into %s"), + proc_string (thread)); +} + +/* Set DR_CONTROL in THREAD. */ + +static void +i386_gnu_dr_set_control_one (struct proc *thread, void *arg) +{ + unsigned long *control = arg; + struct i386_debug_state regs; + + i386_gnu_dr_get (®s, thread); + regs.dr[DR_CONTROL] = *control; + i386_gnu_dr_set (®s, thread); +} + +/* Set DR_CONTROL to CONTROL in all threads. */ + +static void +i386_gnu_dr_set_control (unsigned long control) +{ + inf_update_procs (gnu_current_inf); + inf_threads (gnu_current_inf, i386_gnu_dr_set_control_one, &control); +} + +/* Parameters to set a debugging address. */ + +struct reg_addr +{ + int regnum; /* Register number (zero based). */ + CORE_ADDR addr; /* Address. */ +}; + +/* Set address REGNUM (zero based) to ADDR in THREAD. */ + +static void +i386_gnu_dr_set_addr_one (struct proc *thread, void *arg) +{ + struct reg_addr *reg_addr = arg; + struct i386_debug_state regs; + + i386_gnu_dr_get (®s, thread); + regs.dr[reg_addr->regnum] = reg_addr->addr; + i386_gnu_dr_set (®s, thread); +} + +/* Set address REGNUM (zero based) to ADDR in all threads. */ + +static void +i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr) +{ + struct reg_addr reg_addr; + + gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); + + reg_addr.regnum = regnum; + reg_addr.addr = addr; + + inf_update_procs (gnu_current_inf); + inf_threads (gnu_current_inf, i386_gnu_dr_set_addr_one, ®_addr); +} + +/* Get debug register REGNUM value from only the one LWP of PTID. */ + +static unsigned long +i386_gnu_dr_get_reg (ptid_t ptid, int regnum) +{ + struct i386_debug_state regs; + struct proc *thread; + + /* Make sure we know about new threads. */ + inf_update_procs (gnu_current_inf); + + thread = inf_tid_to_thread (gnu_current_inf, ptid_get_lwp (ptid)); + i386_gnu_dr_get (®s, thread); + + return regs.dr[regnum]; +} + +/* Return the inferior's debug register REGNUM. */ + +static CORE_ADDR +i386_gnu_dr_get_addr (int regnum) +{ + gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); + + return i386_gnu_dr_get_reg (inferior_ptid, regnum); +} + +/* Get DR_STATUS from only the one thread of INFERIOR_PTID. */ + +static unsigned long +i386_gnu_dr_get_status (void) +{ + return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS); +} + +/* Return the inferior's DR7 debug control register. */ + +static unsigned long +i386_gnu_dr_get_control (void) +{ + return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL); +} +#endif /* i386_DEBUG_STATE */ + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_i386gnu_nat; + +void +_initialize_i386gnu_nat (void) +{ + struct target_ops *t; + + /* Fill in the generic GNU/Hurd methods. */ + t = gnu_target (); + +#ifdef i386_DEBUG_STATE + x86_use_watchpoints (t); + + x86_dr_low.set_control = i386_gnu_dr_set_control; + gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT); + x86_dr_low.set_addr = i386_gnu_dr_set_addr; + x86_dr_low.get_addr = i386_gnu_dr_get_addr; + x86_dr_low.get_status = i386_gnu_dr_get_status; + x86_dr_low.get_control = i386_gnu_dr_get_control; + x86_set_debug_register_length (4); +#endif /* i386_DEBUG_STATE */ + + t->to_fetch_registers = gnu_fetch_registers; + t->to_store_registers = gnu_store_registers; + + /* Register the target. */ + add_target (t); +} diff --git a/gdb/i386-gnu-tdep.c b/gdb/i386-gnu-tdep.c new file mode 100644 index 00000000000..acf772fb85b --- /dev/null +++ b/gdb/i386-gnu-tdep.c @@ -0,0 +1,71 @@ +/* Target-dependent code for the GNU Hurd. + Copyright (C) 2002-2016 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 "solib-svr4.h" + +#include "i386-tdep.h" + +/* From . */ +static int i386gnu_gregset_reg_offset[] = +{ + 11 * 4, /* %eax */ + 10 * 4, /* %ecx */ + 9 * 4, /* %edx */ + 8 * 4, /* %ebx */ + 17 * 4, /* %uesp */ + 6 * 4, /* %ebp */ + 5 * 4, /* %esi */ + 4 * 4, /* %edi */ + 14 * 4, /* %eip */ + 16 * 4, /* %efl */ + 15 * 4, /* %cs */ + 18 * 4, /* %ss */ + 3 * 4, /* %ds */ + 2 * 4, /* %es */ + 1 * 4, /* %fs */ + 0 * 4, /* %gs */ +}; + +static void +i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* GNU uses ELF. */ + i386_elf_init_abi (info, gdbarch); + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + tdep->gregset_reg_offset = i386gnu_gregset_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (i386gnu_gregset_reg_offset); + tdep->sizeof_gregset = 19 * 4; + + tdep->jb_pc_offset = 20; /* From . */ +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern void _initialize_i386gnu_tdep (void); + +void +_initialize_i386gnu_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_HURD, i386gnu_init_abi); +} diff --git a/gdb/i386-nbsd-nat.c b/gdb/i386-nbsd-nat.c new file mode 100644 index 00000000000..ee5a13c1fad --- /dev/null +++ b/gdb/i386-nbsd-nat.c @@ -0,0 +1,90 @@ +/* Native-dependent code for NetBSD/i386. + + Copyright (C) 2004-2016 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 (regcache, I386_EDI_REGNUM, &sf.sf_edi); + regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi); + regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); + regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); + regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx); + regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_i386nbsd_nat (void); + +void +_initialize_i386nbsd_nat (void) +{ + struct target_ops *t; + + /* Add some extra features to the common *BSD/i386 target. */ + t = i386bsd_target (); + t->to_pid_to_exec_file = nbsd_pid_to_exec_file; + add_target (t); + + /* 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 new file mode 100644 index 00000000000..f73e5c10274 --- /dev/null +++ b/gdb/i386-nbsd-tdep.c @@ -0,0 +1,327 @@ +/* Target-dependent code for NetBSD/i386. + + Copyright (C) 1988-2016 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 . */ +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, + { + { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x10, -1 }, + /* leal 0x10(%esp), %eax */ + { 0x50, -1 }, /* pushl %eax */ + { 0x50, -1 }, /* pushl %eax */ + { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x127, %eax # __sigreturn14 */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax # exit */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_sc2 = +{ + SIGTRAMP_FRAME, + 1, + { + { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x0c, -1 }, + /* leal 0x0c(%esp), %eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x127, %eax # __sigreturn14 */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_si2 = +{ + SIGTRAMP_FRAME, + 1, + { + { 0x8b, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x08, -1 }, + /* movl 8(%esp),%eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x134, %eax # setcontext */ + { 0xcd, -1 }, { 0x80, -1 }, + /* int $0x80 */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1 }, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_si31 = +{ + SIGTRAMP_FRAME, + 1, + { + { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, + { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* leal 0x8c(%esp), %eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x134, %eax # setcontext */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + i386nbsd_sigtramp_cache_init +}; + +static const struct tramp_frame i386nbsd_sigtramp_si4 = +{ + SIGTRAMP_FRAME, + 1, + { + { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, + { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* leal 0x8c(%esp), %eax */ + { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + /* movl %eax, 0x4(%esp) */ + { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, + /* movl $0x134, %eax # setcontext */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { 0xc7, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, + { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, + /* movl $0xffffffff,0x4(%esp) */ + { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, + /* movl $0x1, %eax */ + { 0xcd, -1 }, { 0x80, -1}, + /* int $0x80 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + 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); + + /* 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; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_i386nbsd_tdep; + +void +_initialize_i386nbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_ELF, + i386nbsdelf_init_abi); +} diff --git a/gdb/i386-obsd-nat.c b/gdb/i386-obsd-nat.c new file mode 100644 index 00000000000..42fedeee42b --- /dev/null +++ b/gdb/i386-obsd-nat.c @@ -0,0 +1,129 @@ +/* Native-dependent code for OpenBSD/i386. + + Copyright (C) 2002-2016 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 +#include +#include + +#include "i386-tdep.h" +#include "i386-bsd-nat.h" +#include "obsd-nat.h" +#include "bsd-kvm.h" + +static int +i386obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct switchframe sf; + + /* The following is true for OpenBSD 3.6: + + 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 OpenBSD 3.6 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 the stack frame, and check its validity. We do this by + checking if the saved interrupt priority level in the stack frame + looks reasonable.. */ +#ifdef PCB_SAVECTX + if ((pcb->pcb_flags & PCB_SAVECTX) == 0) + { + /* Yes, we have a frame that matches cpu_switch(). */ + read_memory (pcb->pcb_esp, (gdb_byte *) &sf, sizeof sf); + pcb->pcb_esp += sizeof (struct switchframe); + regcache_raw_supply (regcache, I386_EDI_REGNUM, &sf.sf_edi); + regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi); + regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx); + regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); + } + else +#endif + { + /* No, the pcb must have been last updated by savectx(). */ + pcb->pcb_esp = pcb->pcb_ebp; + pcb->pcb_ebp = read_memory_integer(pcb->pcb_esp, 4, byte_order); + sf.sf_eip = read_memory_integer(pcb->pcb_esp + 4, 4, byte_order); + regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); + } + + regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); + regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); + + return 1; +} + + +/* Prevent warning from -Wmissing-prototypes. */ +void _initialize_i386obsd_nat (void); + +void +_initialize_i386obsd_nat (void) +{ + /* Add some extra features to the common *BSD/i386 target. */ + obsd_add_target (i386bsd_target ()); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (i386obsd_supply_pcb); + + /* OpenBSD provides a vm.psstrings sysctl that we can use to locate + the sigtramp. That way we can still recognize a sigtramp if its + location is changed in a new kernel. This is especially + important for OpenBSD, since it uses a different memory layout + than NetBSD, yet we cannot distinguish between the two. + + Of course this is still based on the assumption that the sigtramp + is placed directly under the location where the program arguments + and environment can be found. */ +#ifdef VM_PSSTRINGS + { + struct _ps_strings _ps; + int mib[2]; + size_t len; + + mib[0] = CTL_VM; + mib[1] = VM_PSSTRINGS; + len = sizeof (_ps); + if (sysctl (mib, 2, &_ps, &len, NULL, 0) == 0) + { + i386obsd_sigtramp_start_addr = (u_long) _ps.val - 128; + i386obsd_sigtramp_end_addr = (u_long) _ps.val; + } + } +#endif +} diff --git a/gdb/i386-obsd-tdep.c b/gdb/i386-obsd-tdep.c new file mode 100644 index 00000000000..08becfa8296 --- /dev/null +++ b/gdb/i386-obsd-tdep.c @@ -0,0 +1,520 @@ +/* Target-dependent code for OpenBSD/i386. + + Copyright (C) 1988-2016 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 "frame-unwind.h" +#include "gdbcore.h" +#include "regcache.h" +#include "regset.h" +#include "symtab.h" +#include "objfiles.h" +#include "osabi.h" +#include "target.h" +#include "trad-frame.h" + +#include "obsd-tdep.h" +#include "i386-tdep.h" +#include "i387-tdep.h" +#include "solib-svr4.h" +#include "bsd-uthread.h" + +/* Support for signal handlers. */ + +/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page + in virtual memory. The randomness makes it somewhat tricky to + detect it, but fortunately we can rely on the fact that the start + of the sigtramp routine is page-aligned. We recognize the + trampoline by looking for the code that invokes the sigreturn + system call. The offset where we can find that code varies from + release to release. + + By the way, the mapping mentioned above is read-only, so you cannot + place a breakpoint in the signal trampoline. */ + +/* Default page size. */ +static const int i386obsd_page_size = 4096; + +/* Offset for sigreturn(2). */ +static const int i386obsd_sigreturn_offset[] = { + 0x0a, /* OpenBSD 3.2 */ + 0x14, /* OpenBSD 3.6 */ + 0x3a, /* OpenBSD 3.8 */ + -1 +}; + +/* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp + routine. */ + +static int +i386obsd_sigtramp_p (struct frame_info *this_frame) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); + /* The call sequence invoking sigreturn(2). */ + const gdb_byte sigreturn[] = + { + 0xb8, + 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */ + 0xcd, 0x80 /* int $0x80 */ + }; + size_t buflen = sizeof sigreturn; + const int *offset; + gdb_byte *buf; + const char *name; + + /* If the function has a valid symbol name, it isn't a + trampoline. */ + find_pc_partial_function (pc, &name, NULL, NULL); + if (name != NULL) + return 0; + + /* If the function lives in a valid section (even without a starting + point) it isn't a trampoline. */ + if (find_pc_section (pc) != NULL) + return 0; + + /* Allocate buffer. */ + buf = (gdb_byte *) alloca (buflen); + + /* Loop over all offsets. */ + for (offset = i386obsd_sigreturn_offset; *offset != -1; offset++) + { + /* If we can't read the instructions, return zero. */ + if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, + buf, buflen)) + return 0; + + /* Check for sigreturn(2). */ + if (memcmp (buf, sigreturn, buflen) == 0) + return 1; + } + + return 0; +} + +/* Mapping between the general-purpose registers in `struct reg' + format and GDB's register cache layout. */ + +/* From . */ +static int i386obsd_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 */ +}; + +static void +i386obsd_aout_supply_regset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *regs, size_t len) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + const gdb_byte *gregs = (const gdb_byte *) regs; + + gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE); + + i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset); + i387_supply_fsave (regcache, regnum, gregs + tdep->sizeof_gregset); +} + +static const struct regset i386obsd_aout_gregset = + { + NULL, i386obsd_aout_supply_regset, NULL + }; + +static void +i386obsd_aout_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* OpenBSD a.out core dumps don't use seperate register sets for the + general-purpose and floating-point registers. */ + + cb (".reg", tdep->sizeof_gregset + I387_SIZEOF_FSAVE, + &i386obsd_aout_gregset, NULL, cb_data); +} + + +/* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */ +CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20; +CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0; + +/* From . */ +int i386obsd_sc_reg_offset[I386_NUM_GREGS] = +{ + 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 /usr/src/lib/libpthread/arch/i386/uthread_machdep.c. */ +static int i386obsd_uthread_reg_offset[] = +{ + 11 * 4, /* %eax */ + 10 * 4, /* %ecx */ + 9 * 4, /* %edx */ + 8 * 4, /* %ebx */ + -1, /* %esp */ + 6 * 4, /* %ebp */ + 5 * 4, /* %esi */ + 4 * 4, /* %edi */ + 12 * 4, /* %eip */ + -1, /* %eflags */ + 13 * 4, /* %cs */ + -1, /* %ss */ + 3 * 4, /* %ds */ + 2 * 4, /* %es */ + 1 * 4, /* %fs */ + 0 * 4 /* %gs */ +}; + +/* Offset within the thread structure where we can find the saved + stack pointer (%esp). */ +#define I386OBSD_UTHREAD_ESP_OFFSET 176 + +static void +i386obsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET; + CORE_ADDR sp = 0; + gdb_byte buf[4]; + int i; + + gdb_assert (regnum >= -1); + + if (regnum == -1 || regnum == I386_ESP_REGNUM) + { + int offset; + + /* Fetch stack pointer from thread structure. */ + sp = read_memory_unsigned_integer (sp_addr, 4, byte_order); + + /* Adjust the stack pointer such that it looks as if we just + returned from _thread_machdep_switch. */ + offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4; + store_unsigned_integer (buf, 4, byte_order, sp + offset); + regcache_raw_supply (regcache, I386_ESP_REGNUM, buf); + } + + for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++) + { + if (i386obsd_uthread_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + /* Fetch stack pointer from thread structure (if we didn't + do so already). */ + if (sp == 0) + sp = read_memory_unsigned_integer (sp_addr, 4, byte_order); + + /* Read the saved register from the stack frame. */ + read_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4); + regcache_raw_supply (regcache, i, buf); + } + } +} + +static void +i386obsd_collect_uthread (const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET; + CORE_ADDR sp = 0; + gdb_byte buf[4]; + int i; + + gdb_assert (regnum >= -1); + + if (regnum == -1 || regnum == I386_ESP_REGNUM) + { + int offset; + + /* Calculate the stack pointer (frame pointer) that will be + stored into the thread structure. */ + offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4; + regcache_raw_collect (regcache, I386_ESP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 4, byte_order) - offset; + + /* Store the stack pointer. */ + write_memory_unsigned_integer (sp_addr, 4, byte_order, sp); + + /* The stack pointer was (potentially) modified. Make sure we + build a proper stack frame. */ + regnum = -1; + } + + for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++) + { + if (i386obsd_uthread_reg_offset[i] != -1 + && (regnum == -1 || regnum == i)) + { + /* Fetch stack pointer from thread structure (if we didn't + calculate it already). */ + if (sp == 0) + sp = read_memory_unsigned_integer (sp_addr, 4, byte_order); + + /* Write the register into the stack frame. */ + regcache_raw_collect (regcache, i, buf); + write_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4); + } + } +} + +/* Kernel debugging support. */ + +/* From . Note that %esp and %ess are only saved in + a trap frame when entering the kernel from user space. */ +static int i386obsd_tf_reg_offset[] = +{ + 10 * 4, /* %eax */ + 9 * 4, /* %ecx */ + 8 * 4, /* %edx */ + 7 * 4, /* %ebx */ + -1, /* %esp */ + 6 * 4, /* %ebp */ + 5 * 4, /* %esi */ + 4 * 4, /* %edi */ + 13 * 4, /* %eip */ + 15 * 4, /* %eflags */ + 14 * 4, /* %cs */ + -1, /* %ss */ + 3 * 4, /* %ds */ + 2 * 4, /* %es */ + 0 * 4, /* %fs */ + 1 * 4 /* %gs */ +}; + +static struct trad_frame_cache * +i386obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct trad_frame_cache *cache; + CORE_ADDR func, sp, addr; + ULONGEST cs; + const char *name; + int i; + + if (*this_cache) + return (struct trad_frame_cache *) *this_cache; + + cache = trad_frame_cache_zalloc (this_frame); + *this_cache = cache; + + func = get_frame_func (this_frame); + sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); + + find_pc_partial_function (func, &name, NULL, NULL); + if (name && startswith (name, "Xintr")) + addr = sp + 8; /* It's an interrupt frame. */ + else + addr = sp; + + for (i = 0; i < ARRAY_SIZE (i386obsd_tf_reg_offset); i++) + if (i386obsd_tf_reg_offset[i] != -1) + trad_frame_set_reg_addr (cache, i, addr + i386obsd_tf_reg_offset[i]); + + /* Read %cs from trap frame. */ + addr += i386obsd_tf_reg_offset[I386_CS_REGNUM]; + cs = read_memory_unsigned_integer (addr, 4, byte_order); + if ((cs & I386_SEL_RPL) == I386_SEL_UPL) + { + /* Trap from user space; terminate backtrace. */ + trad_frame_set_id (cache, outer_frame_id); + } + else + { + /* Construct the frame ID using the function start. */ + trad_frame_set_id (cache, frame_id_build (sp + 8, func)); + } + + return cache; +} + +static void +i386obsd_trapframe_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + struct trad_frame_cache *cache = + i386obsd_trapframe_cache (this_frame, this_cache); + + trad_frame_get_id (cache, this_id); +} + +static struct value * +i386obsd_trapframe_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct trad_frame_cache *cache = + i386obsd_trapframe_cache (this_frame, this_cache); + + return trad_frame_get_register (cache, this_frame, regnum); +} + +static int +i386obsd_trapframe_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + ULONGEST cs; + const char *name; + + /* Check Current Privilege Level and bail out if we're not executing + in kernel space. */ + cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM); + if ((cs & I386_SEL_RPL) == I386_SEL_UPL) + return 0; + + find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL); + return (name && (strcmp (name, "calltrap") == 0 + || strcmp (name, "syscall1") == 0 + || startswith (name, "Xintr") + || startswith (name, "Xsoft"))); +} + +static const struct frame_unwind i386obsd_trapframe_unwind = { + /* FIXME: kettenis/20051219: This really is more like an interrupt + frame, but SIGTRAMP_FRAME would print , + which really is not what we want here. */ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + i386obsd_trapframe_this_id, + i386obsd_trapframe_prev_register, + NULL, + i386obsd_trapframe_sniffer +}; + + +static void +i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Obviously OpenBSD is BSD-based. */ + i386bsd_init_abi (info, gdbarch); + obsd_init_abi (info, gdbarch); + + /* OpenBSD has a different `struct reg'. */ + tdep->gregset_reg_offset = i386obsd_r_reg_offset; + tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset); + tdep->sizeof_gregset = 16 * 4; + + /* OpenBSD uses -freg-struct-return by default. */ + tdep->struct_return = reg_struct_return; + + /* OpenBSD uses a different memory layout. */ + tdep->sigtramp_start = i386obsd_sigtramp_start_addr; + tdep->sigtramp_end = i386obsd_sigtramp_end_addr; + tdep->sigtramp_p = i386obsd_sigtramp_p; + + /* OpenBSD has a `struct sigcontext' that's different from the + original 4.3 BSD. */ + tdep->sc_reg_offset = i386obsd_sc_reg_offset; + tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset); + + /* OpenBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, i386obsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, i386obsd_collect_uthread); + + /* Unwind kernel trap frames correctly. */ + frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind); +} + +/* OpenBSD a.out. */ + +static void +i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + i386obsd_init_abi (info, gdbarch); + + /* OpenBSD a.out has a single register set. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, i386obsd_aout_iterate_over_regset_sections); +} + +/* OpenBSD ELF. */ + +static void +i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* It's still OpenBSD. */ + i386obsd_init_abi (info, gdbarch); + + /* But ELF-based. */ + i386_elf_init_abi (info, gdbarch); + + /* OpenBSD ELF uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_i386obsd_tdep (void); + +void +_initialize_i386obsd_tdep (void) +{ + /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are + indistingushable from NetBSD/i386 a.out binaries, building a GDB + that should support both these targets will probably not work as + expected. */ +#define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT + + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT, + i386obsd_aout_init_abi); + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF, + i386obsd_elf_init_abi); +} diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index 49dcce048d1..672a6cf9997 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -428,7 +428,7 @@ extern const struct target_desc *i386_target_description (uint64_t xcr0); extern int i386_mpx_enabled (void); -/* Functions and variables exported from i386bsd-tdep.c. */ +/* Functions and variables exported from i386-bsd-tdep.c. */ extern void i386bsd_init_abi (struct gdbarch_info, struct gdbarch *); extern CORE_ADDR i386fbsd_sigtramp_start_addr; diff --git a/gdb/i386-v4-nat.c b/gdb/i386-v4-nat.c new file mode 100644 index 00000000000..4d1020b8d63 --- /dev/null +++ b/gdb/i386-v4-nat.c @@ -0,0 +1,163 @@ +/* Native-dependent code for Unix SVR4 running on i386's. + + Copyright (C) 1988-2016 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 "value.h" +#include "inferior.h" +#include "regcache.h" + +#ifdef HAVE_SYS_REG_H +#include +#endif + +#include "i386-tdep.h" +#include "i387-tdep.h" + +#ifdef HAVE_SYS_PROCFS_H + +#include + +/* We must not compile this code for 64-bit Solaris x86. */ +#if !defined (PR_MODEL_NATIVE) || (PR_MODEL_NATIVE == PR_MODEL_ILP32) + +#include "gregset.h" + +/* The `/proc' interface divides the target machine's register set up + into two different sets, the general purpose register set (gregset) + and the floating-point register set (fpregset). For each set, + there is an ioctl to get the current register set and another ioctl + to set the current values. + + The actual structure passed through the ioctl interface is, of + course, naturally machine dependent, and is different for each set + of registers. For the i386 for example, the general-purpose + register set is typically defined by: + + typedef int gregset_t[19]; (in ) + + #define GS 0 (in ) + #define FS 1 + ... + #define UESP 17 + #define SS 18 + + and the floating-point set by: + + typedef struct fpregset { + union { + struct fpchip_state // fp extension state // + { + int state[27]; // 287/387 saved state // + int status; // status word saved at // + // exception // + } fpchip_state; + struct fp_emul_space // for emulators // + { + char fp_emul[246]; + char fp_epad[2]; + } fp_emul_space; + int f_fpregs[62]; // union of the above // + } fp_reg_set; + long f_wregs[33]; // saved weitek state // + } fpregset_t; + + Incidentally fpchip_state contains the FPU state in the same format + as used by the "fsave" instruction, and that's the only thing we + support here. I don't know how the emulator stores it state. The + Weitek stuff definitely isn't supported. + + The routines defined here, provide the packing and unpacking of + gregset_t and fpregset_t formatted data. */ + +#ifdef HAVE_GREGSET_T + +/* Mapping between the general-purpose registers in `/proc' + format and GDB's register array layout. */ +static int regmap[] = +{ + EAX, ECX, EDX, EBX, + UESP, EBP, ESI, EDI, + EIP, EFL, CS, SS, + DS, ES, FS, GS +}; + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) +{ + const greg_t *regp = (const greg_t *) gregsetp; + int regnum; + + for (regnum = 0; regnum < I386_NUM_GREGS; regnum++) + regcache_raw_supply (regcache, regnum, regp + regmap[regnum]); +} + +/* Fill register REGNUM (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNUM is -1, + do this for all registers. */ + +void +fill_gregset (const struct regcache *regcache, + gregset_t *gregsetp, int regnum) +{ + greg_t *regp = (greg_t *) gregsetp; + int i; + + for (i = 0; i < I386_NUM_GREGS; i++) + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regp + regmap[i]); +} + +#endif /* HAVE_GREGSET_T */ + +#ifdef HAVE_FPREGSET_T + +/* Fill GDB's register array with the floating-point register values in + *FPREGSETP. */ + +void +supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) +{ + if (gdbarch_fp0_regnum (get_regcache_arch (regcache)) == 0) + return; + + i387_supply_fsave (regcache, -1, fpregsetp); +} + +/* Fill register REGNO (if it is a floating-point register) in + *FPREGSETP with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_fpregset (const struct regcache *regcache, + fpregset_t *fpregsetp, int regno) +{ + if (gdbarch_fp0_regnum (get_regcache_arch (regcache)) == 0) + return; + + i387_collect_fsave (regcache, regno, fpregsetp); +} + +#endif /* HAVE_FPREGSET_T */ + +#endif /* not 64-bit. */ + +#endif /* HAVE_SYS_PROCFS_H */ diff --git a/gdb/i386bsd-nat.c b/gdb/i386bsd-nat.c deleted file mode 100644 index b6b143b6227..00000000000 --- a/gdb/i386bsd-nat.c +++ /dev/null @@ -1,367 +0,0 @@ -/* Native-dependent code for modern i386 BSD's. - - Copyright (C) 2000-2016 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 -#include - -#include "i386-tdep.h" -#include "i387-tdep.h" -#include "x86bsd-nat.h" -#include "i386bsd-nat.h" -#include "inf-ptrace.h" - - -/* In older BSD versions we cannot get at some of the segment - registers. FreeBSD for example didn't support the %fs and %gs - registers until the 3.0 release. We have autoconf checks for their - presence, and deal gracefully with their absence. */ - -/* Offset in `struct reg' where MEMBER is stored. */ -#define REG_OFFSET(member) offsetof (struct reg, member) - -/* At i386bsd_reg_offset[REGNUM] you'll find the offset in `struct - reg' where the GDB register REGNUM is stored. Unsupported - registers are marked with `-1'. */ -static int i386bsd_r_reg_offset[] = -{ - REG_OFFSET (r_eax), - REG_OFFSET (r_ecx), - REG_OFFSET (r_edx), - REG_OFFSET (r_ebx), - REG_OFFSET (r_esp), - REG_OFFSET (r_ebp), - REG_OFFSET (r_esi), - REG_OFFSET (r_edi), - REG_OFFSET (r_eip), - REG_OFFSET (r_eflags), - REG_OFFSET (r_cs), - REG_OFFSET (r_ss), - REG_OFFSET (r_ds), - REG_OFFSET (r_es), -#ifdef HAVE_STRUCT_REG_R_FS - REG_OFFSET (r_fs), -#else - -1, -#endif -#ifdef HAVE_STRUCT_REG_R_GS - REG_OFFSET (r_gs) -#else - -1 -#endif -}; - -/* Macro to determine if a register is fetched with PT_GETREGS. */ -#define GETREGS_SUPPLIES(regnum) \ - ((0 <= (regnum) && (regnum) <= 15)) - -#ifdef HAVE_PT_GETXMMREGS -/* Set to 1 if the kernel supports PT_GETXMMREGS. Initialized to -1 - so that we try PT_GETXMMREGS the first time around. */ -static int have_ptrace_xmmregs = -1; -#endif - - -/* Supply the general-purpose registers in GREGS, to REGCACHE. */ - -static void -i386bsd_supply_gregset (struct regcache *regcache, const void *gregs) -{ - const char *regs = (const char *) gregs; - int regnum; - - for (regnum = 0; regnum < ARRAY_SIZE (i386bsd_r_reg_offset); regnum++) - { - int offset = i386bsd_r_reg_offset[regnum]; - - if (offset != -1) - regcache_raw_supply (regcache, regnum, regs + offset); - } -} - -/* Collect register REGNUM from REGCACHE and store its contents in - GREGS. If REGNUM is -1, collect and store all appropriate - registers. */ - -static void -i386bsd_collect_gregset (const struct regcache *regcache, - void *gregs, int regnum) -{ - char *regs = (char *) gregs; - int i; - - for (i = 0; i < ARRAY_SIZE (i386bsd_r_reg_offset); i++) - { - if (regnum == -1 || regnum == i) - { - int offset = i386bsd_r_reg_offset[i]; - - if (offset != -1) - regcache_raw_collect (regcache, i, regs + offset); - } - } -} - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers (including the floating point registers). */ - -static void -i386bsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1 || GETREGS_SUPPLIES (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - i386bsd_supply_gregset (regcache, ®s); - if (regnum != -1) - return; - } - - if (regnum == -1 || regnum >= I386_ST0_REGNUM) - { - struct fpreg fpregs; -#ifdef HAVE_PT_GETXMMREGS - char xmmregs[512]; -#endif - -#ifdef PT_GETXSTATE_INFO - if (x86bsd_xsave_len != 0) - { - void *xstateregs; - - xstateregs = alloca (x86bsd_xsave_len); - if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) - perror_with_name (_("Couldn't get extended state status")); - - i387_supply_xsave (regcache, -1, xstateregs); - return; - } -#endif - -#ifdef HAVE_PT_GETXMMREGS - if (have_ptrace_xmmregs != 0 - && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) - { - have_ptrace_xmmregs = 1; - i387_supply_fxsave (regcache, -1, xmmregs); - } - else - { - have_ptrace_xmmregs = 0; -#endif - if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - i387_supply_fsave (regcache, -1, &fpregs); -#ifdef HAVE_PT_GETXMMREGS - } -#endif - } -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers (including the floating point registers). */ - -static void -i386bsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1 || GETREGS_SUPPLIES (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - i386bsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - - if (regnum != -1) - return; - } - - if (regnum == -1 || regnum >= I386_ST0_REGNUM) - { - struct fpreg fpregs; -#ifdef HAVE_PT_GETXMMREGS - char xmmregs[512]; -#endif - -#ifdef PT_GETXSTATE_INFO - if (x86bsd_xsave_len != 0) - { - void *xstateregs; - - xstateregs = alloca (x86bsd_xsave_len); - if (ptrace (PT_GETXSTATE, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, 0) == -1) - perror_with_name (_("Couldn't get extended state status")); - - i387_collect_xsave (regcache, -1, xstateregs, 0); - - if (ptrace (PT_SETXSTATE, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xstateregs, x86bsd_xsave_len) == -1) - perror_with_name (_("Couldn't write extended state status")); - return; - } -#endif - -#ifdef HAVE_PT_GETXMMREGS - if (have_ptrace_xmmregs != 0 - && ptrace(PT_GETXMMREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xmmregs, 0) == 0) - { - have_ptrace_xmmregs = 1; - - i387_collect_fxsave (regcache, regnum, xmmregs); - - if (ptrace (PT_SETXMMREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) xmmregs, 0) == -1) - perror_with_name (_("Couldn't write XMM registers")); - } - else - { - have_ptrace_xmmregs = 0; -#endif - if (ptrace (PT_GETFPREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - i387_collect_fsave (regcache, regnum, &fpregs); - - if (ptrace (PT_SETFPREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); -#ifdef HAVE_PT_GETXMMREGS - } -#endif - } -} - -/* Create a prototype *BSD/i386 target. The client can override it - with local methods. */ - -struct target_ops * -i386bsd_target (void) -{ - struct target_ops *t; - - t = x86bsd_target (); - t->to_fetch_registers = i386bsd_fetch_inferior_registers; - t->to_store_registers = i386bsd_store_inferior_registers; - return t; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_i386bsd_nat (void); - -void -_initialize_i386bsd_nat (void) -{ - int offset; - - /* To support the recognition of signal handlers, i386bsd-tdep.c - hardcodes some constants. Inclusion of this file means that we - are compiling a native debugger, which means that we can use the - system header files and sysctl(3) to get at the relevant - information. */ - -#if defined (__FreeBSD_version) && __FreeBSD_version >= 400011 -#define SC_REG_OFFSET i386fbsd4_sc_reg_offset -#elif defined (__FreeBSD_version) && __FreeBSD_version >= 300005 -#define SC_REG_OFFSET i386fbsd_sc_reg_offset -#elif defined (NetBSD) || defined (__NetBSD_Version__) -#define SC_REG_OFFSET i386nbsd_sc_reg_offset -#elif defined (OpenBSD) -#define SC_REG_OFFSET i386obsd_sc_reg_offset -#endif - -#ifdef SC_REG_OFFSET - - /* We only check the program counter, stack pointer and frame - pointer since these members of `struct sigcontext' are essential - for providing backtraces. More checks could be added, but would - involve adding configure checks for the appropriate structure - members, since older BSD's don't provide all of them. */ - -#define SC_PC_OFFSET SC_REG_OFFSET[I386_EIP_REGNUM] -#define SC_SP_OFFSET SC_REG_OFFSET[I386_ESP_REGNUM] -#define SC_FP_OFFSET SC_REG_OFFSET[I386_EBP_REGNUM] - - /* Override the default value for the offset of the program counter - in the sigcontext structure. */ - offset = offsetof (struct sigcontext, sc_pc); - - if (SC_PC_OFFSET != offset) - { - warning (_("\ -offsetof (struct sigcontext, sc_pc) yields %d instead of %d.\n\ -Please report this to ."), - offset, SC_PC_OFFSET); - } - - SC_PC_OFFSET = offset; - - /* Likewise for the stack pointer. */ - offset = offsetof (struct sigcontext, sc_sp); - - if (SC_SP_OFFSET != offset) - { - warning (_("\ -offsetof (struct sigcontext, sc_sp) yields %d instead of %d.\n\ -Please report this to ."), - offset, SC_SP_OFFSET); - } - - SC_SP_OFFSET = offset; - - /* And the frame pointer. */ - offset = offsetof (struct sigcontext, sc_fp); - - if (SC_FP_OFFSET != offset) - { - warning (_("\ -offsetof (struct sigcontext, sc_fp) yields %d instead of %d.\n\ -Please report this to ."), - offset, SC_FP_OFFSET); - } - - SC_FP_OFFSET = offset; - -#endif /* SC_REG_OFFSET */ -} diff --git a/gdb/i386bsd-nat.h b/gdb/i386bsd-nat.h deleted file mode 100644 index 1b51d19c48d..00000000000 --- a/gdb/i386bsd-nat.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Native-dependent code for modern i386 BSD's. - - Copyright (C) 2004-2016 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 I386BSD_NAT_H -#define I386BSD_NAT_H - -/* Create a prototype *BSD/i386 target. The client can override it - with local methods. */ - -extern struct target_ops *i386bsd_target (void); - -#endif /* i386bsd-nat.h */ diff --git a/gdb/i386bsd-tdep.c b/gdb/i386bsd-tdep.c deleted file mode 100644 index 15809b3b9a6..00000000000 --- a/gdb/i386bsd-tdep.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Target-dependent code for i386 BSD's. - - Copyright (C) 2001-2016 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 "osabi.h" - -#include "i386-tdep.h" - -/* Support for signal handlers. */ - -/* Assuming THIS_FRAME is for a BSD sigtramp routine, return the - address of the associated sigcontext structure. */ - -static CORE_ADDR -i386bsd_sigcontext_addr (struct frame_info *this_frame) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[4]; - CORE_ADDR sp; - - get_frame_register (this_frame, I386_ESP_REGNUM, buf); - sp = extract_unsigned_integer (buf, 4, byte_order); - - return read_memory_unsigned_integer (sp + 8, 4, byte_order); -} - - -/* Support for shared libraries. */ - -/* Traditional BSD (4.3 BSD, still used for BSDI and 386BSD). */ - -/* From . */ -int i386bsd_sc_reg_offset[] = -{ - -1, /* %eax */ - -1, /* %ecx */ - -1, /* %edx */ - -1, /* %ebx */ - 8 + 0 * 4, /* %esp */ - 8 + 1 * 4, /* %ebp */ - -1, /* %esi */ - -1, /* %edi */ - 8 + 3 * 4, /* %eip */ - 8 + 4 * 4, /* %eflags */ - -1, /* %cs */ - -1, /* %ss */ - -1, /* %ds */ - -1, /* %es */ - -1, /* %fs */ - -1 /* %gs */ -}; - -void -i386bsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->jb_pc_offset = 0; - - tdep->sigtramp_start = 0xfdbfdfc0; - tdep->sigtramp_end = 0xfdbfe000; - tdep->sigcontext_addr = i386bsd_sigcontext_addr; - tdep->sc_reg_offset = i386bsd_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (i386bsd_sc_reg_offset); -} - - -static enum gdb_osabi -i386bsd_aout_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "a.out-i386-netbsd") == 0) - return GDB_OSABI_NETBSD_AOUT; - - if (strcmp (bfd_get_target (abfd), "a.out-i386-freebsd") == 0) - return GDB_OSABI_FREEBSD_AOUT; - - return GDB_OSABI_UNKNOWN; -} - -static enum gdb_osabi -i386bsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_NETBSD_AOUT; - - return GDB_OSABI_UNKNOWN; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_i386bsd_tdep (void); - -void -_initialize_i386bsd_tdep (void) -{ - gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_aout_flavour, - i386bsd_aout_osabi_sniffer); - - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_unknown_flavour, - i386bsd_core_osabi_sniffer); -} diff --git a/gdb/i386fbsd-nat.c b/gdb/i386fbsd-nat.c deleted file mode 100644 index 716b51364e5..00000000000 --- a/gdb/i386fbsd-nat.c +++ /dev/null @@ -1,197 +0,0 @@ -/* Native-dependent code for FreeBSD/i386. - - Copyright (C) 2001-2016 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 "target.h" - -#include -#include -#include -#include - -#include "fbsd-nat.h" -#include "i386-tdep.h" -#include "x86-nat.h" -#include "x86bsd-nat.h" -#include "i386bsd-nat.h" - -/* Resume execution of the inferior process. If STEP is nonzero, - single-step it. If SIGNAL is nonzero, give it that signal. */ - -static void -i386fbsd_resume (struct target_ops *ops, - ptid_t ptid, int step, enum gdb_signal signal) -{ - pid_t pid = ptid_get_pid (ptid); - int request = PT_STEP; - - if (pid == -1) - /* Resume all threads. This only gets used in the non-threaded - case, where "resume all threads" and "resume inferior_ptid" are - the same. */ - pid = ptid_get_pid (inferior_ptid); - - if (!step) - { - struct regcache *regcache = get_current_regcache (); - ULONGEST eflags; - - /* Workaround for a bug in FreeBSD. Make sure that the trace - flag is off when doing a continue. There is a code path - through the kernel which leaves the flag set when it should - have been cleared. If a process has a signal pending (such - as SIGALRM) and we do a PT_STEP, the process never really has - a chance to run because the kernel needs to notify the - debugger that a signal is being sent. Therefore, the process - never goes through the kernel's trap() function which would - normally clear it. */ - - regcache_cooked_read_unsigned (regcache, I386_EFLAGS_REGNUM, - &eflags); - if (eflags & 0x0100) - regcache_cooked_write_unsigned (regcache, I386_EFLAGS_REGNUM, - eflags & ~0x0100); - - request = PT_CONTINUE; - } - - /* An addres of (caddr_t) 1 tells ptrace to continue from where it - was. (If GDB wanted it to start some other way, we have already - written a new PC value to the child.) */ - if (ptrace (request, pid, (caddr_t) 1, - gdb_signal_to_host (signal)) == -1) - perror_with_name (("ptrace")); -} - - -/* Support for debugging kernel virtual memory images. */ - -#include - -#include "bsd-kvm.h" - -static int -i386fbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - /* The following is true for FreeBSD 4.7: - - The pcb contains %eip, %ebx, %esp, %ebp, %esi, %edi and %gs. - This accounts for all callee-saved registers specified by the - psABI and then some. Here %esp contains the stack pointer at the - point just after the call to cpu_switch(). 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_esp == 0) - return 0; - - pcb->pcb_esp += 4; - regcache_raw_supply (regcache, I386_EDI_REGNUM, &pcb->pcb_edi); - regcache_raw_supply (regcache, I386_ESI_REGNUM, &pcb->pcb_esi); - regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); - regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); - regcache_raw_supply (regcache, I386_EBX_REGNUM, &pcb->pcb_ebx); - regcache_raw_supply (regcache, I386_EIP_REGNUM, &pcb->pcb_eip); - regcache_raw_supply (regcache, I386_GS_REGNUM, &pcb->pcb_gs); - - return 1; -} - - -#ifdef PT_GETXSTATE_INFO -/* Implement the to_read_description method. */ - -static const struct target_desc * -i386fbsd_read_description (struct target_ops *ops) -{ - static int xsave_probed; - static uint64_t xcr0; - - if (!xsave_probed) - { - struct ptrace_xstate_info info; - - if (ptrace (PT_GETXSTATE_INFO, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &info, sizeof (info)) == 0) - { - x86bsd_xsave_len = info.xsave_len; - xcr0 = info.xsave_mask; - } - xsave_probed = 1; - } - - if (x86bsd_xsave_len != 0) - { - return i386_target_description (xcr0); - } - else - return tdesc_i386; -} -#endif - -/* Prevent warning from -Wmissing-prototypes. */ -void _initialize_i386fbsd_nat (void); - -void -_initialize_i386fbsd_nat (void) -{ - struct target_ops *t; - - /* Add some extra features to the common *BSD/i386 target. */ - t = i386bsd_target (); - -#ifdef PT_GETXSTATE_INFO - t->to_read_description = i386fbsd_read_description; -#endif - - t->to_resume = i386fbsd_resume; - fbsd_nat_add_target (t); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (i386fbsd_supply_pcb); - -#ifdef KERN_PROC_SIGTRAMP - /* Normally signal frames are detected via i386fbsd_sigtramp_p. - However, FreeBSD 9.2 through 10.1 do not include the page holding - the signal code in core dumps. These releases do provide a - kern.proc.sigtramp. sysctl that returns the location of the - signal trampoline for a running process. We fetch the location - of the current (gdb) process and use this to identify signal - frames in core dumps from these releases. */ - { - int mib[4]; - struct kinfo_sigtramp kst; - size_t len; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_SIGTRAMP; - mib[3] = getpid (); - len = sizeof (kst); - if (sysctl (mib, 4, &kst, &len, NULL, 0) == 0) - { - i386fbsd_sigtramp_start_addr = (uintptr_t) kst.ksigtramp_start; - i386fbsd_sigtramp_end_addr = (uintptr_t) kst.ksigtramp_end; - } - } -#endif -} diff --git a/gdb/i386fbsd-tdep.c b/gdb/i386fbsd-tdep.c deleted file mode 100644 index fbff37c715d..00000000000 --- a/gdb/i386fbsd-tdep.c +++ /dev/null @@ -1,498 +0,0 @@ -/* Target-dependent code for FreeBSD/i386. - - Copyright (C) 2003-2016 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 "gdbcore.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "i386fbsd-tdep.h" -#include "x86-xstate.h" - -#include "i386-tdep.h" -#include "i387-tdep.h" -#include "bsd-uthread.h" -#include "fbsd-tdep.h" -#include "solib-svr4.h" - -/* Support for signal handlers. */ - -/* Return whether THIS_FRAME corresponds to a FreeBSD sigtramp - routine. */ - -/* FreeBSD/i386 supports three different signal trampolines, one for - versions before 4.0, a second for 4.x, and a third for 5.0 and - later. To complicate matters, FreeBSD/i386 binaries running under - an amd64 kernel use a different set of trampolines. These - trampolines differ from the i386 kernel trampolines in that they - omit a middle section that conditionally restores %gs. */ - -static const gdb_byte i386fbsd_sigtramp_start[] = -{ - 0x8d, 0x44, 0x24, 0x20, /* lea SIGF_UC(%esp),%eax */ - 0x50 /* pushl %eax */ -}; - -static const gdb_byte i386fbsd_sigtramp_middle[] = -{ - 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00, - /* testl $PSL_VM,UC_EFLAGS(%eax) */ - 0x75, 0x03, /* jne +3 */ - 0x8e, 0x68, 0x14 /* mov UC_GS(%eax),%gs */ -}; - -static const gdb_byte i386fbsd_sigtramp_end[] = -{ - 0xb8, 0xa1, 0x01, 0x00, 0x00, /* movl $SYS_sigreturn,%eax */ - 0x50, /* pushl %eax */ - 0xcd, 0x80 /* int $0x80 */ -}; - -static const gdb_byte i386fbsd_freebsd4_sigtramp_start[] = -{ - 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC4(%esp),%eax */ - 0x50 /* pushl %eax */ -}; - -static const gdb_byte i386fbsd_freebsd4_sigtramp_middle[] = -{ - 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x00, - /* testl $PSL_VM,UC4_EFLAGS(%eax) */ - 0x75, 0x03, /* jne +3 */ - 0x8e, 0x68, 0x14 /* mov UC4_GS(%eax),%gs */ -}; - -static const gdb_byte i386fbsd_freebsd4_sigtramp_end[] = -{ - 0xb8, 0x58, 0x01, 0x00, 0x00, /* movl $344,%eax */ - 0x50, /* pushl %eax */ - 0xcd, 0x80 /* int $0x80 */ -}; - -static const gdb_byte i386fbsd_osigtramp_start[] = -{ - 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_SC(%esp),%eax */ - 0x50 /* pushl %eax */ -}; - -static const gdb_byte i386fbsd_osigtramp_middle[] = -{ - 0xf7, 0x40, 0x18, 0x00, 0x00, 0x02, 0x00, - /* testl $PSL_VM,SC_PS(%eax) */ - 0x75, 0x03, /* jne +3 */ - 0x8e, 0x68, 0x44 /* mov SC_GS(%eax),%gs */ -}; - -static const gdb_byte i386fbsd_osigtramp_end[] = -{ - 0xb8, 0x67, 0x00, 0x00, 0x00, /* movl $103,%eax */ - 0x50, /* pushl %eax */ - 0xcd, 0x80 /* int $0x80 */ -}; - -/* The three different trampolines are all the same size. */ -gdb_static_assert (sizeof i386fbsd_sigtramp_start - == sizeof i386fbsd_freebsd4_sigtramp_start); -gdb_static_assert (sizeof i386fbsd_sigtramp_start - == sizeof i386fbsd_osigtramp_start); -gdb_static_assert (sizeof i386fbsd_sigtramp_middle - == sizeof i386fbsd_freebsd4_sigtramp_middle); -gdb_static_assert (sizeof i386fbsd_sigtramp_middle - == sizeof i386fbsd_osigtramp_middle); -gdb_static_assert (sizeof i386fbsd_sigtramp_end - == sizeof i386fbsd_freebsd4_sigtramp_end); -gdb_static_assert (sizeof i386fbsd_sigtramp_end - == sizeof i386fbsd_osigtramp_end); - -/* We assume that the middle is the largest chunk below. */ -gdb_static_assert (sizeof i386fbsd_sigtramp_middle - > sizeof i386fbsd_sigtramp_start); -gdb_static_assert (sizeof i386fbsd_sigtramp_middle - > sizeof i386fbsd_sigtramp_end); - -static int -i386fbsd_sigtramp_p (struct frame_info *this_frame) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - gdb_byte buf[sizeof i386fbsd_sigtramp_middle]; - const gdb_byte *middle, *end; - - /* Look for a matching start. */ - if (!safe_frame_unwind_memory (this_frame, pc, buf, - sizeof i386fbsd_sigtramp_start)) - return 0; - if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start) - == 0) - { - middle = i386fbsd_sigtramp_middle; - end = i386fbsd_sigtramp_end; - } - else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start, - sizeof i386fbsd_freebsd4_sigtramp_start) == 0) - { - middle = i386fbsd_freebsd4_sigtramp_middle; - end = i386fbsd_freebsd4_sigtramp_end; - } - else if (memcmp (buf, i386fbsd_osigtramp_start, - sizeof i386fbsd_osigtramp_start) == 0) - { - middle = i386fbsd_osigtramp_middle; - end = i386fbsd_osigtramp_end; - } - else - return 0; - - /* Since the end is shorter than the middle, check for a matching end - next. */ - pc += sizeof i386fbsd_sigtramp_start; - if (!safe_frame_unwind_memory (this_frame, pc, buf, - sizeof i386fbsd_sigtramp_end)) - return 0; - if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) == 0) - return 1; - - /* If the end didn't match, check for a matching middle. */ - if (!safe_frame_unwind_memory (this_frame, pc, buf, - sizeof i386fbsd_sigtramp_middle)) - return 0; - if (memcmp (buf, middle, sizeof i386fbsd_sigtramp_middle) != 0) - return 0; - - /* The middle matched, check for a matching end. */ - pc += sizeof i386fbsd_sigtramp_middle; - if (!safe_frame_unwind_memory (this_frame, pc, buf, - sizeof i386fbsd_sigtramp_end)) - return 0; - if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) != 0) - return 0; - - return 1; -} - -/* FreeBSD 3.0-RELEASE or later. */ - -/* From . */ -static int i386fbsd_r_reg_offset[] = -{ - 9 * 4, 8 * 4, 7 * 4, 6 * 4, /* %eax, %ecx, %edx, %ebx */ - 15 * 4, 4 * 4, /* %esp, %ebp */ - 3 * 4, 2 * 4, /* %esi, %edi */ - 12 * 4, 14 * 4, /* %eip, %eflags */ - 13 * 4, 16 * 4, /* %cs, %ss */ - 1 * 4, 0 * 4, -1, -1 /* %ds, %es, %fs, %gs */ -}; - -/* Sigtramp routine location. */ -CORE_ADDR i386fbsd_sigtramp_start_addr; -CORE_ADDR i386fbsd_sigtramp_end_addr; - -/* From . */ -int i386fbsd_sc_reg_offset[] = -{ - 8 + 14 * 4, /* %eax */ - 8 + 13 * 4, /* %ecx */ - 8 + 12 * 4, /* %edx */ - 8 + 11 * 4, /* %ebx */ - 8 + 0 * 4, /* %esp */ - 8 + 1 * 4, /* %ebp */ - 8 + 10 * 4, /* %esi */ - 8 + 9 * 4, /* %edi */ - 8 + 3 * 4, /* %eip */ - 8 + 4 * 4, /* %eflags */ - 8 + 7 * 4, /* %cs */ - 8 + 8 * 4, /* %ss */ - 8 + 6 * 4, /* %ds */ - 8 + 5 * 4, /* %es */ - 8 + 15 * 4, /* %fs */ - 8 + 16 * 4 /* %gs */ -}; - -/* From /usr/src/lib/libc/i386/gen/_setjmp.S. */ -static int i386fbsd_jmp_buf_reg_offset[] = -{ - -1, /* %eax */ - -1, /* %ecx */ - -1, /* %edx */ - 1 * 4, /* %ebx */ - 2 * 4, /* %esp */ - 3 * 4, /* %ebp */ - 4 * 4, /* %esi */ - 5 * 4, /* %edi */ - 0 * 4 /* %eip */ -}; - -/* Get XSAVE extended state xcr0 from core dump. */ - -uint64_t -i386fbsd_core_read_xcr0 (bfd *abfd) -{ - asection *xstate = bfd_get_section_by_name (abfd, ".reg-xstate"); - uint64_t xcr0; - - if (xstate) - { - size_t size = bfd_section_size (abfd, xstate); - - /* Check extended state size. */ - if (size < X86_XSTATE_AVX_SIZE) - xcr0 = X86_XSTATE_SSE_MASK; - else - { - char contents[8]; - - if (! bfd_get_section_contents (abfd, xstate, contents, - I386_FBSD_XSAVE_XCR0_OFFSET, - 8)) - { - warning (_("Couldn't read `xcr0' bytes from " - "`.reg-xstate' section in core file.")); - return 0; - } - - xcr0 = bfd_get_64 (abfd, contents); - } - } - else - xcr0 = 0; - - return xcr0; -} - -/* Implement the core_read_description gdbarch method. */ - -static const struct target_desc * -i386fbsd_core_read_description (struct gdbarch *gdbarch, - struct target_ops *target, - bfd *abfd) -{ - return i386_target_description (i386fbsd_core_read_xcr0 (abfd)); -} - -/* Similar to i386_supply_fpregset, but use XSAVE extended state. */ - -static void -i386fbsd_supply_xstateregset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *xstateregs, size_t len) -{ - i387_supply_xsave (regcache, regnum, xstateregs); -} - -/* Similar to i386_collect_fpregset, but use XSAVE extended state. */ - -static void -i386fbsd_collect_xstateregset (const struct regset *regset, - const struct regcache *regcache, - int regnum, void *xstateregs, size_t len) -{ - i387_collect_xsave (regcache, regnum, xstateregs, 1); -} - -/* Register set definitions. */ - -static const struct regset i386fbsd_xstateregset = - { - NULL, - i386fbsd_supply_xstateregset, - i386fbsd_collect_xstateregset - }; - -/* Iterate over core file register note sections. */ - -static void -i386fbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - cb (".reg", tdep->sizeof_gregset, &i386_gregset, NULL, cb_data); - cb (".reg2", tdep->sizeof_fpregset, &i386_fpregset, NULL, cb_data); - - if (tdep->xcr0 & X86_XSTATE_AVX) - cb (".reg-xstate", X86_XSTATE_SIZE(tdep->xcr0), - &i386fbsd_xstateregset, "XSAVE extended state", cb_data); -} - -static void -i386fbsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[4]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++) - { - if (i386fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - read_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4); - regcache_raw_supply (regcache, i, buf); - } - } -} - -static void -i386fbsd_collect_uthread (const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - gdb_byte buf[4]; - int i; - - gdb_assert (regnum >= -1); - - for (i = 0; i < ARRAY_SIZE (i386fbsd_jmp_buf_reg_offset); i++) - { - if (i386fbsd_jmp_buf_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - regcache_raw_collect (regcache, i, buf); - write_memory (addr + i386fbsd_jmp_buf_reg_offset[i], buf, 4); - } - } -} - -static void -i386fbsdaout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Obviously FreeBSD is BSD-based. */ - i386bsd_init_abi (info, gdbarch); - - /* FreeBSD has a different `struct reg', and reserves some space for - its FPU emulator in `struct fpreg'. */ - tdep->gregset_reg_offset = i386fbsd_r_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd_r_reg_offset); - tdep->sizeof_gregset = 18 * 4; - tdep->sizeof_fpregset = 176; - - /* FreeBSD uses -freg-struct-return by default. */ - tdep->struct_return = reg_struct_return; - - tdep->sigtramp_p = i386fbsd_sigtramp_p; - - /* FreeBSD uses a different memory layout. */ - tdep->sigtramp_start = i386fbsd_sigtramp_start_addr; - tdep->sigtramp_end = i386fbsd_sigtramp_end_addr; - - /* FreeBSD has a more complete `struct sigcontext'. */ - tdep->sc_reg_offset = i386fbsd_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (i386fbsd_sc_reg_offset); - - /* FreeBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, i386fbsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, i386fbsd_collect_uthread); -} - -static void -i386fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* It's almost identical to FreeBSD a.out. */ - i386fbsdaout_init_abi (info, gdbarch); - - /* Except that it uses ELF. */ - i386_elf_init_abi (info, gdbarch); - - /* FreeBSD ELF uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - -/* FreeBSD 4.0-RELEASE or later. */ - -/* From . */ -static int i386fbsd4_r_reg_offset[] = -{ - 10 * 4, 9 * 4, 8 * 4, 7 * 4, /* %eax, %ecx, %edx, %ebx */ - 16 * 4, 5 * 4, /* %esp, %ebp */ - 4 * 4, 3 * 4, /* %esi, %edi */ - 13 * 4, 15 * 4, /* %eip, %eflags */ - 14 * 4, 17 * 4, /* %cs, %ss */ - 2 * 4, 1 * 4, 0 * 4, 18 * 4 /* %ds, %es, %fs, %gs */ -}; - -/* From . */ -int i386fbsd4_sc_reg_offset[] = -{ - 20 + 11 * 4, /* %eax */ - 20 + 10 * 4, /* %ecx */ - 20 + 9 * 4, /* %edx */ - 20 + 8 * 4, /* %ebx */ - 20 + 17 * 4, /* %esp */ - 20 + 6 * 4, /* %ebp */ - 20 + 5 * 4, /* %esi */ - 20 + 4 * 4, /* %edi */ - 20 + 14 * 4, /* %eip */ - 20 + 16 * 4, /* %eflags */ - 20 + 15 * 4, /* %cs */ - 20 + 18 * 4, /* %ss */ - 20 + 3 * 4, /* %ds */ - 20 + 2 * 4, /* %es */ - 20 + 1 * 4, /* %fs */ - 20 + 0 * 4 /* %gs */ -}; - -static void -i386fbsd4_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Generic FreeBSD support. */ - fbsd_init_abi (info, gdbarch); - - /* Inherit stuff from older releases. We assume that FreeBSD - 4.0-RELEASE always uses ELF. */ - i386fbsd_init_abi (info, gdbarch); - - /* FreeBSD 4.0 introduced a new `struct reg'. */ - tdep->gregset_reg_offset = i386fbsd4_r_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (i386fbsd4_r_reg_offset); - tdep->sizeof_gregset = 19 * 4; - - /* FreeBSD 4.0 introduced a new `struct sigcontext'. */ - tdep->sc_reg_offset = i386fbsd4_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (i386fbsd4_sc_reg_offset); - - tdep->xsave_xcr0_offset = I386_FBSD_XSAVE_XCR0_OFFSET; - - /* Iterate over core file register note sections. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, i386fbsd_iterate_over_regset_sections); - - set_gdbarch_core_read_description (gdbarch, - i386fbsd_core_read_description); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_i386fbsd_tdep (void); - -void -_initialize_i386fbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_AOUT, - i386fbsdaout_init_abi); - gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_FREEBSD_ELF, - i386fbsd4_init_abi); -} diff --git a/gdb/i386fbsd-tdep.h b/gdb/i386fbsd-tdep.h deleted file mode 100644 index c8ed1c17d7d..00000000000 --- a/gdb/i386fbsd-tdep.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Target-dependent code for FreeBSD x86. - - Copyright (C) 2015-2016 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 I386FBSD_TDEP_H -#define I386FBSD_TDEP_H - -/* Get XSAVE extended state xcr0 from core dump. */ -extern uint64_t i386fbsd_core_read_xcr0 (bfd *abfd); - -/* The format of the XSAVE extended area is determined by hardware. - Cores store the XSAVE extended area in a NT_X86_XSTATE note that - matches the layout on Linux. */ -#define I386_FBSD_XSAVE_XCR0_OFFSET 464 - -#endif /* i386fbsd-tdep.h */ diff --git a/gdb/i386gnu-nat.c b/gdb/i386gnu-nat.c deleted file mode 100644 index e14a181564f..00000000000 --- a/gdb/i386gnu-nat.c +++ /dev/null @@ -1,436 +0,0 @@ -/* Low level interface to i386 running the GNU Hurd. - - Copyright (C) 1992-2016 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 "x86-nat.h" -#include "inferior.h" -#include "floatformat.h" -#include "regcache.h" - -#include -#include -#include -#include - -#include "i386-tdep.h" - -#include "gnu-nat.h" -#include "inf-child.h" -#include "i387-tdep.h" - -/* Offset to the thread_state_t location where REG is stored. */ -#define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg) - -/* At REG_OFFSET[N] is the offset to the thread_state_t location where - the GDB register N is stored. */ -static int reg_offset[] = -{ - REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx), - REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi), - REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss), - REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs) -}; - -#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum]) - - -/* Get the whole floating-point state of THREAD and record the values - of the corresponding (pseudo) registers. */ - -static void -fetch_fpregs (struct regcache *regcache, struct proc *thread) -{ - mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; - struct i386_float_state state; - error_t err; - - err = thread_get_state (thread->port, i386_FLOAT_STATE, - (thread_state_t) &state, &count); - if (err) - { - warning (_("Couldn't fetch floating-point state from %s"), - proc_string (thread)); - return; - } - - if (!state.initialized) - { - /* The floating-point state isn't initialized. */ - i387_supply_fsave (regcache, -1, NULL); - } - else - { - /* Supply the floating-point registers. */ - i387_supply_fsave (regcache, -1, state.hw_state); - } -} - -/* Fetch register REGNO, or all regs if REGNO is -1. */ -static void -gnu_fetch_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - struct proc *thread; - - /* Make sure we know about new threads. */ - inf_update_procs (gnu_current_inf); - - thread = inf_tid_to_thread (gnu_current_inf, - ptid_get_lwp (inferior_ptid)); - if (!thread) - error (_("Can't fetch registers from thread %s: No such thread"), - target_pid_to_str (inferior_ptid)); - - if (regno < I386_NUM_GREGS || regno == -1) - { - thread_state_t state; - - /* This does the dirty work for us. */ - state = proc_get_state (thread, 0); - if (!state) - { - warning (_("Couldn't fetch registers from %s"), - proc_string (thread)); - return; - } - - if (regno == -1) - { - int i; - - proc_debug (thread, "fetching all register"); - - for (i = 0; i < I386_NUM_GREGS; i++) - regcache_raw_supply (regcache, i, REG_ADDR (state, i)); - thread->fetched_regs = ~0; - } - else - { - proc_debug (thread, "fetching register %s", - gdbarch_register_name (get_regcache_arch (regcache), - regno)); - - regcache_raw_supply (regcache, regno, - REG_ADDR (state, regno)); - thread->fetched_regs |= (1 << regno); - } - } - - if (regno >= I386_NUM_GREGS || regno == -1) - { - proc_debug (thread, "fetching floating-point registers"); - - fetch_fpregs (regcache, thread); - } -} - - -/* Store the whole floating-point state into THREAD using information - from the corresponding (pseudo) registers. */ -static void -store_fpregs (const struct regcache *regcache, struct proc *thread, int regno) -{ - mach_msg_type_number_t count = i386_FLOAT_STATE_COUNT; - struct i386_float_state state; - error_t err; - - err = thread_get_state (thread->port, i386_FLOAT_STATE, - (thread_state_t) &state, &count); - if (err) - { - warning (_("Couldn't fetch floating-point state from %s"), - proc_string (thread)); - return; - } - - /* FIXME: kettenis/2001-07-15: Is this right? Should we somehow - take into account DEPRECATED_REGISTER_VALID like the old code did? */ - i387_collect_fsave (regcache, regno, state.hw_state); - - err = thread_set_state (thread->port, i386_FLOAT_STATE, - (thread_state_t) &state, i386_FLOAT_STATE_COUNT); - if (err) - { - warning (_("Couldn't store floating-point state into %s"), - proc_string (thread)); - return; - } -} - -/* Store at least register REGNO, or all regs if REGNO == -1. */ -static void -gnu_store_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - struct proc *thread; - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - /* Make sure we know about new threads. */ - inf_update_procs (gnu_current_inf); - - thread = inf_tid_to_thread (gnu_current_inf, - ptid_get_lwp (inferior_ptid)); - if (!thread) - error (_("Couldn't store registers into thread %s: No such thread"), - target_pid_to_str (inferior_ptid)); - - if (regno < I386_NUM_GREGS || regno == -1) - { - thread_state_t state; - thread_state_data_t old_state; - int was_aborted = thread->aborted; - int was_valid = thread->state_valid; - int trace; - - if (!was_aborted && was_valid) - memcpy (&old_state, &thread->state, sizeof (old_state)); - - state = proc_get_state (thread, 1); - if (!state) - { - warning (_("Couldn't store registers into %s"), - proc_string (thread)); - return; - } - - /* Save the T bit. We might try to restore the %eflags register - below, but changing the T bit would seriously confuse GDB. */ - trace = ((struct i386_thread_state *)state)->efl & 0x100; - - if (!was_aborted && was_valid) - /* See which registers have changed after aborting the thread. */ - { - int check_regno; - - for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++) - if ((thread->fetched_regs & (1 << check_regno)) - && memcpy (REG_ADDR (&old_state, check_regno), - REG_ADDR (state, check_regno), - register_size (gdbarch, check_regno))) - /* Register CHECK_REGNO has changed! Ack! */ - { - warning (_("Register %s changed after the thread was aborted"), - gdbarch_register_name (gdbarch, check_regno)); - if (regno >= 0 && regno != check_regno) - /* Update GDB's copy of the register. */ - regcache_raw_supply (regcache, check_regno, - REG_ADDR (state, check_regno)); - else - warning (_("... also writing this register! " - "Suspicious...")); - } - } - - if (regno == -1) - { - int i; - - proc_debug (thread, "storing all registers"); - - for (i = 0; i < I386_NUM_GREGS; i++) - if (REG_VALID == regcache_register_status (regcache, i)) - regcache_raw_collect (regcache, i, REG_ADDR (state, i)); - } - else - { - proc_debug (thread, "storing register %s", - gdbarch_register_name (gdbarch, regno)); - - gdb_assert (REG_VALID == regcache_register_status (regcache, regno)); - regcache_raw_collect (regcache, regno, REG_ADDR (state, regno)); - } - - /* Restore the T bit. */ - ((struct i386_thread_state *)state)->efl &= ~0x100; - ((struct i386_thread_state *)state)->efl |= trace; - } - - if (regno >= I386_NUM_GREGS || regno == -1) - { - proc_debug (thread, "storing floating-point registers"); - - store_fpregs (regcache, thread, regno); - } -} - - -/* Support for debug registers. */ - -#ifdef i386_DEBUG_STATE -/* Get debug registers for thread THREAD. */ - -static void -i386_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread) -{ - mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT; - error_t err; - - err = thread_get_state (thread->port, i386_DEBUG_STATE, - (thread_state_t) regs, &count); - if (err != 0 || count != i386_DEBUG_STATE_COUNT) - warning (_("Couldn't fetch debug state from %s"), - proc_string (thread)); -} - -/* Set debug registers for thread THREAD. */ - -static void -i386_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread) -{ - error_t err; - - err = thread_set_state (thread->port, i386_DEBUG_STATE, - (thread_state_t) regs, i386_DEBUG_STATE_COUNT); - if (err != 0) - warning (_("Couldn't store debug state into %s"), - proc_string (thread)); -} - -/* Set DR_CONTROL in THREAD. */ - -static void -i386_gnu_dr_set_control_one (struct proc *thread, void *arg) -{ - unsigned long *control = arg; - struct i386_debug_state regs; - - i386_gnu_dr_get (®s, thread); - regs.dr[DR_CONTROL] = *control; - i386_gnu_dr_set (®s, thread); -} - -/* Set DR_CONTROL to CONTROL in all threads. */ - -static void -i386_gnu_dr_set_control (unsigned long control) -{ - inf_update_procs (gnu_current_inf); - inf_threads (gnu_current_inf, i386_gnu_dr_set_control_one, &control); -} - -/* Parameters to set a debugging address. */ - -struct reg_addr -{ - int regnum; /* Register number (zero based). */ - CORE_ADDR addr; /* Address. */ -}; - -/* Set address REGNUM (zero based) to ADDR in THREAD. */ - -static void -i386_gnu_dr_set_addr_one (struct proc *thread, void *arg) -{ - struct reg_addr *reg_addr = arg; - struct i386_debug_state regs; - - i386_gnu_dr_get (®s, thread); - regs.dr[reg_addr->regnum] = reg_addr->addr; - i386_gnu_dr_set (®s, thread); -} - -/* Set address REGNUM (zero based) to ADDR in all threads. */ - -static void -i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr) -{ - struct reg_addr reg_addr; - - gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); - - reg_addr.regnum = regnum; - reg_addr.addr = addr; - - inf_update_procs (gnu_current_inf); - inf_threads (gnu_current_inf, i386_gnu_dr_set_addr_one, ®_addr); -} - -/* Get debug register REGNUM value from only the one LWP of PTID. */ - -static unsigned long -i386_gnu_dr_get_reg (ptid_t ptid, int regnum) -{ - struct i386_debug_state regs; - struct proc *thread; - - /* Make sure we know about new threads. */ - inf_update_procs (gnu_current_inf); - - thread = inf_tid_to_thread (gnu_current_inf, ptid_get_lwp (ptid)); - i386_gnu_dr_get (®s, thread); - - return regs.dr[regnum]; -} - -/* Return the inferior's debug register REGNUM. */ - -static CORE_ADDR -i386_gnu_dr_get_addr (int regnum) -{ - gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR); - - return i386_gnu_dr_get_reg (inferior_ptid, regnum); -} - -/* Get DR_STATUS from only the one thread of INFERIOR_PTID. */ - -static unsigned long -i386_gnu_dr_get_status (void) -{ - return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS); -} - -/* Return the inferior's DR7 debug control register. */ - -static unsigned long -i386_gnu_dr_get_control (void) -{ - return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL); -} -#endif /* i386_DEBUG_STATE */ - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_i386gnu_nat; - -void -_initialize_i386gnu_nat (void) -{ - struct target_ops *t; - - /* Fill in the generic GNU/Hurd methods. */ - t = gnu_target (); - -#ifdef i386_DEBUG_STATE - x86_use_watchpoints (t); - - x86_dr_low.set_control = i386_gnu_dr_set_control; - gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT); - x86_dr_low.set_addr = i386_gnu_dr_set_addr; - x86_dr_low.get_addr = i386_gnu_dr_get_addr; - x86_dr_low.get_status = i386_gnu_dr_get_status; - x86_dr_low.get_control = i386_gnu_dr_get_control; - x86_set_debug_register_length (4); -#endif /* i386_DEBUG_STATE */ - - t->to_fetch_registers = gnu_fetch_registers; - t->to_store_registers = gnu_store_registers; - - /* Register the target. */ - add_target (t); -} diff --git a/gdb/i386gnu-tdep.c b/gdb/i386gnu-tdep.c deleted file mode 100644 index acf772fb85b..00000000000 --- a/gdb/i386gnu-tdep.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Target-dependent code for the GNU Hurd. - Copyright (C) 2002-2016 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 "solib-svr4.h" - -#include "i386-tdep.h" - -/* From . */ -static int i386gnu_gregset_reg_offset[] = -{ - 11 * 4, /* %eax */ - 10 * 4, /* %ecx */ - 9 * 4, /* %edx */ - 8 * 4, /* %ebx */ - 17 * 4, /* %uesp */ - 6 * 4, /* %ebp */ - 5 * 4, /* %esi */ - 4 * 4, /* %edi */ - 14 * 4, /* %eip */ - 16 * 4, /* %efl */ - 15 * 4, /* %cs */ - 18 * 4, /* %ss */ - 3 * 4, /* %ds */ - 2 * 4, /* %es */ - 1 * 4, /* %fs */ - 0 * 4, /* %gs */ -}; - -static void -i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* GNU uses ELF. */ - i386_elf_init_abi (info, gdbarch); - - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); - - tdep->gregset_reg_offset = i386gnu_gregset_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (i386gnu_gregset_reg_offset); - tdep->sizeof_gregset = 19 * 4; - - tdep->jb_pc_offset = 20; /* From . */ -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern void _initialize_i386gnu_tdep (void); - -void -_initialize_i386gnu_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_HURD, i386gnu_init_abi); -} diff --git a/gdb/i386nbsd-nat.c b/gdb/i386nbsd-nat.c deleted file mode 100644 index 6ace1d496d6..00000000000 --- a/gdb/i386nbsd-nat.c +++ /dev/null @@ -1,90 +0,0 @@ -/* Native-dependent code for NetBSD/i386. - - Copyright (C) 2004-2016 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 "i386bsd-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 (regcache, I386_EDI_REGNUM, &sf.sf_edi); - regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi); - regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); - regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); - regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx); - regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_i386nbsd_nat (void); - -void -_initialize_i386nbsd_nat (void) -{ - struct target_ops *t; - - /* Add some extra features to the common *BSD/i386 target. */ - t = i386bsd_target (); - t->to_pid_to_exec_file = nbsd_pid_to_exec_file; - add_target (t); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (i386nbsd_supply_pcb); -} diff --git a/gdb/i386nbsd-tdep.c b/gdb/i386nbsd-tdep.c deleted file mode 100644 index f73e5c10274..00000000000 --- a/gdb/i386nbsd-tdep.c +++ /dev/null @@ -1,327 +0,0 @@ -/* Target-dependent code for NetBSD/i386. - - Copyright (C) 1988-2016 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 . */ -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, - { - { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x10, -1 }, - /* leal 0x10(%esp), %eax */ - { 0x50, -1 }, /* pushl %eax */ - { 0x50, -1 }, /* pushl %eax */ - { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, - /* movl $0x127, %eax # __sigreturn14 */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, - /* movl $0x1, %eax # exit */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { TRAMP_SENTINEL_INSN, -1 } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_sc2 = -{ - SIGTRAMP_FRAME, - 1, - { - { 0x8d, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x0c, -1 }, - /* leal 0x0c(%esp), %eax */ - { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - /* movl %eax, 0x4(%esp) */ - { 0xb8, -1 }, { 0x27, -1 }, {0x01, -1 }, {0x00, -1 }, {0x00, -1 }, - /* movl $0x127, %eax # __sigreturn14 */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - /* movl %eax, 0x4(%esp) */ - { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, - /* movl $0x1, %eax */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { TRAMP_SENTINEL_INSN, -1 } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_si2 = -{ - SIGTRAMP_FRAME, - 1, - { - { 0x8b, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x08, -1 }, - /* movl 8(%esp),%eax */ - { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - /* movl %eax, 0x4(%esp) */ - { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, - /* movl $0x134, %eax # setcontext */ - { 0xcd, -1 }, { 0x80, -1 }, - /* int $0x80 */ - { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - /* movl %eax, 0x4(%esp) */ - { 0xb8, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, - /* movl $0x1, %eax */ - { 0xcd, -1 }, { 0x80, -1 }, - /* int $0x80 */ - { TRAMP_SENTINEL_INSN, -1 } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_si31 = -{ - SIGTRAMP_FRAME, - 1, - { - { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, - { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, - /* leal 0x8c(%esp), %eax */ - { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - /* movl %eax, 0x4(%esp) */ - { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, - /* movl $0x134, %eax # setcontext */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - /* movl %eax, 0x4(%esp) */ - { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, - /* movl $0x1, %eax */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { TRAMP_SENTINEL_INSN, -1 } - }, - i386nbsd_sigtramp_cache_init -}; - -static const struct tramp_frame i386nbsd_sigtramp_si4 = -{ - SIGTRAMP_FRAME, - 1, - { - { 0x8d, -1 }, { 0x84, -1 }, { 0x24, -1 }, - { 0x8c, -1 }, { 0x00, -1 }, { 0x00, -1 }, { 0x00, -1 }, - /* leal 0x8c(%esp), %eax */ - { 0x89, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - /* movl %eax, 0x4(%esp) */ - { 0xb8, -1 }, { 0x34, -1 }, { 0x01, -1 }, { 0x00, -1 }, { 0x00, -1 }, - /* movl $0x134, %eax # setcontext */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { 0xc7, -1 }, { 0x44, -1 }, { 0x24, -1 }, { 0x04, -1 }, - { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, { 0xff, -1 }, - /* movl $0xffffffff,0x4(%esp) */ - { 0xb8, -1 }, { 0x01, -1 }, {0x00, -1 }, {0x00, -1 }, {0x00, -1 }, - /* movl $0x1, %eax */ - { 0xcd, -1 }, { 0x80, -1}, - /* int $0x80 */ - { TRAMP_SENTINEL_INSN, -1 } - }, - 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); - - /* 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; -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_i386nbsd_tdep; - -void -_initialize_i386nbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_NETBSD_ELF, - i386nbsdelf_init_abi); -} diff --git a/gdb/i386obsd-nat.c b/gdb/i386obsd-nat.c deleted file mode 100644 index eeeee9aa127..00000000000 --- a/gdb/i386obsd-nat.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Native-dependent code for OpenBSD/i386. - - Copyright (C) 2002-2016 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 -#include -#include - -#include "i386-tdep.h" -#include "i386bsd-nat.h" -#include "obsd-nat.h" -#include "bsd-kvm.h" - -static int -i386obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct switchframe sf; - - /* The following is true for OpenBSD 3.6: - - 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 OpenBSD 3.6 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 the stack frame, and check its validity. We do this by - checking if the saved interrupt priority level in the stack frame - looks reasonable.. */ -#ifdef PCB_SAVECTX - if ((pcb->pcb_flags & PCB_SAVECTX) == 0) - { - /* Yes, we have a frame that matches cpu_switch(). */ - read_memory (pcb->pcb_esp, (gdb_byte *) &sf, sizeof sf); - pcb->pcb_esp += sizeof (struct switchframe); - regcache_raw_supply (regcache, I386_EDI_REGNUM, &sf.sf_edi); - regcache_raw_supply (regcache, I386_ESI_REGNUM, &sf.sf_esi); - regcache_raw_supply (regcache, I386_EBX_REGNUM, &sf.sf_ebx); - regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); - } - else -#endif - { - /* No, the pcb must have been last updated by savectx(). */ - pcb->pcb_esp = pcb->pcb_ebp; - pcb->pcb_ebp = read_memory_integer(pcb->pcb_esp, 4, byte_order); - sf.sf_eip = read_memory_integer(pcb->pcb_esp + 4, 4, byte_order); - regcache_raw_supply (regcache, I386_EIP_REGNUM, &sf.sf_eip); - } - - regcache_raw_supply (regcache, I386_EBP_REGNUM, &pcb->pcb_ebp); - regcache_raw_supply (regcache, I386_ESP_REGNUM, &pcb->pcb_esp); - - return 1; -} - - -/* Prevent warning from -Wmissing-prototypes. */ -void _initialize_i386obsd_nat (void); - -void -_initialize_i386obsd_nat (void) -{ - /* Add some extra features to the common *BSD/i386 target. */ - obsd_add_target (i386bsd_target ()); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (i386obsd_supply_pcb); - - /* OpenBSD provides a vm.psstrings sysctl that we can use to locate - the sigtramp. That way we can still recognize a sigtramp if its - location is changed in a new kernel. This is especially - important for OpenBSD, since it uses a different memory layout - than NetBSD, yet we cannot distinguish between the two. - - Of course this is still based on the assumption that the sigtramp - is placed directly under the location where the program arguments - and environment can be found. */ -#ifdef VM_PSSTRINGS - { - struct _ps_strings _ps; - int mib[2]; - size_t len; - - mib[0] = CTL_VM; - mib[1] = VM_PSSTRINGS; - len = sizeof (_ps); - if (sysctl (mib, 2, &_ps, &len, NULL, 0) == 0) - { - i386obsd_sigtramp_start_addr = (u_long) _ps.val - 128; - i386obsd_sigtramp_end_addr = (u_long) _ps.val; - } - } -#endif -} diff --git a/gdb/i386obsd-tdep.c b/gdb/i386obsd-tdep.c deleted file mode 100644 index 08becfa8296..00000000000 --- a/gdb/i386obsd-tdep.c +++ /dev/null @@ -1,520 +0,0 @@ -/* Target-dependent code for OpenBSD/i386. - - Copyright (C) 1988-2016 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 "frame-unwind.h" -#include "gdbcore.h" -#include "regcache.h" -#include "regset.h" -#include "symtab.h" -#include "objfiles.h" -#include "osabi.h" -#include "target.h" -#include "trad-frame.h" - -#include "obsd-tdep.h" -#include "i386-tdep.h" -#include "i387-tdep.h" -#include "solib-svr4.h" -#include "bsd-uthread.h" - -/* Support for signal handlers. */ - -/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page - in virtual memory. The randomness makes it somewhat tricky to - detect it, but fortunately we can rely on the fact that the start - of the sigtramp routine is page-aligned. We recognize the - trampoline by looking for the code that invokes the sigreturn - system call. The offset where we can find that code varies from - release to release. - - By the way, the mapping mentioned above is read-only, so you cannot - place a breakpoint in the signal trampoline. */ - -/* Default page size. */ -static const int i386obsd_page_size = 4096; - -/* Offset for sigreturn(2). */ -static const int i386obsd_sigreturn_offset[] = { - 0x0a, /* OpenBSD 3.2 */ - 0x14, /* OpenBSD 3.6 */ - 0x3a, /* OpenBSD 3.8 */ - -1 -}; - -/* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp - routine. */ - -static int -i386obsd_sigtramp_p (struct frame_info *this_frame) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1)); - /* The call sequence invoking sigreturn(2). */ - const gdb_byte sigreturn[] = - { - 0xb8, - 0x67, 0x00, 0x00, 0x00, /* movl $SYS_sigreturn, %eax */ - 0xcd, 0x80 /* int $0x80 */ - }; - size_t buflen = sizeof sigreturn; - const int *offset; - gdb_byte *buf; - const char *name; - - /* If the function has a valid symbol name, it isn't a - trampoline. */ - find_pc_partial_function (pc, &name, NULL, NULL); - if (name != NULL) - return 0; - - /* If the function lives in a valid section (even without a starting - point) it isn't a trampoline. */ - if (find_pc_section (pc) != NULL) - return 0; - - /* Allocate buffer. */ - buf = (gdb_byte *) alloca (buflen); - - /* Loop over all offsets. */ - for (offset = i386obsd_sigreturn_offset; *offset != -1; offset++) - { - /* If we can't read the instructions, return zero. */ - if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, - buf, buflen)) - return 0; - - /* Check for sigreturn(2). */ - if (memcmp (buf, sigreturn, buflen) == 0) - return 1; - } - - return 0; -} - -/* Mapping between the general-purpose registers in `struct reg' - format and GDB's register cache layout. */ - -/* From . */ -static int i386obsd_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 */ -}; - -static void -i386obsd_aout_supply_regset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *regs, size_t len) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const gdb_byte *gregs = (const gdb_byte *) regs; - - gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE); - - i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset); - i387_supply_fsave (regcache, regnum, gregs + tdep->sizeof_gregset); -} - -static const struct regset i386obsd_aout_gregset = - { - NULL, i386obsd_aout_supply_regset, NULL - }; - -static void -i386obsd_aout_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* OpenBSD a.out core dumps don't use seperate register sets for the - general-purpose and floating-point registers. */ - - cb (".reg", tdep->sizeof_gregset + I387_SIZEOF_FSAVE, - &i386obsd_aout_gregset, NULL, cb_data); -} - - -/* Sigtramp routine location for OpenBSD 3.1 and earlier releases. */ -CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20; -CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0; - -/* From . */ -int i386obsd_sc_reg_offset[I386_NUM_GREGS] = -{ - 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 /usr/src/lib/libpthread/arch/i386/uthread_machdep.c. */ -static int i386obsd_uthread_reg_offset[] = -{ - 11 * 4, /* %eax */ - 10 * 4, /* %ecx */ - 9 * 4, /* %edx */ - 8 * 4, /* %ebx */ - -1, /* %esp */ - 6 * 4, /* %ebp */ - 5 * 4, /* %esi */ - 4 * 4, /* %edi */ - 12 * 4, /* %eip */ - -1, /* %eflags */ - 13 * 4, /* %cs */ - -1, /* %ss */ - 3 * 4, /* %ds */ - 2 * 4, /* %es */ - 1 * 4, /* %fs */ - 0 * 4 /* %gs */ -}; - -/* Offset within the thread structure where we can find the saved - stack pointer (%esp). */ -#define I386OBSD_UTHREAD_ESP_OFFSET 176 - -static void -i386obsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET; - CORE_ADDR sp = 0; - gdb_byte buf[4]; - int i; - - gdb_assert (regnum >= -1); - - if (regnum == -1 || regnum == I386_ESP_REGNUM) - { - int offset; - - /* Fetch stack pointer from thread structure. */ - sp = read_memory_unsigned_integer (sp_addr, 4, byte_order); - - /* Adjust the stack pointer such that it looks as if we just - returned from _thread_machdep_switch. */ - offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4; - store_unsigned_integer (buf, 4, byte_order, sp + offset); - regcache_raw_supply (regcache, I386_ESP_REGNUM, buf); - } - - for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++) - { - if (i386obsd_uthread_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - /* Fetch stack pointer from thread structure (if we didn't - do so already). */ - if (sp == 0) - sp = read_memory_unsigned_integer (sp_addr, 4, byte_order); - - /* Read the saved register from the stack frame. */ - read_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4); - regcache_raw_supply (regcache, i, buf); - } - } -} - -static void -i386obsd_collect_uthread (const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET; - CORE_ADDR sp = 0; - gdb_byte buf[4]; - int i; - - gdb_assert (regnum >= -1); - - if (regnum == -1 || regnum == I386_ESP_REGNUM) - { - int offset; - - /* Calculate the stack pointer (frame pointer) that will be - stored into the thread structure. */ - offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4; - regcache_raw_collect (regcache, I386_ESP_REGNUM, buf); - sp = extract_unsigned_integer (buf, 4, byte_order) - offset; - - /* Store the stack pointer. */ - write_memory_unsigned_integer (sp_addr, 4, byte_order, sp); - - /* The stack pointer was (potentially) modified. Make sure we - build a proper stack frame. */ - regnum = -1; - } - - for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++) - { - if (i386obsd_uthread_reg_offset[i] != -1 - && (regnum == -1 || regnum == i)) - { - /* Fetch stack pointer from thread structure (if we didn't - calculate it already). */ - if (sp == 0) - sp = read_memory_unsigned_integer (sp_addr, 4, byte_order); - - /* Write the register into the stack frame. */ - regcache_raw_collect (regcache, i, buf); - write_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4); - } - } -} - -/* Kernel debugging support. */ - -/* From . Note that %esp and %ess are only saved in - a trap frame when entering the kernel from user space. */ -static int i386obsd_tf_reg_offset[] = -{ - 10 * 4, /* %eax */ - 9 * 4, /* %ecx */ - 8 * 4, /* %edx */ - 7 * 4, /* %ebx */ - -1, /* %esp */ - 6 * 4, /* %ebp */ - 5 * 4, /* %esi */ - 4 * 4, /* %edi */ - 13 * 4, /* %eip */ - 15 * 4, /* %eflags */ - 14 * 4, /* %cs */ - -1, /* %ss */ - 3 * 4, /* %ds */ - 2 * 4, /* %es */ - 0 * 4, /* %fs */ - 1 * 4 /* %gs */ -}; - -static struct trad_frame_cache * -i386obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct trad_frame_cache *cache; - CORE_ADDR func, sp, addr; - ULONGEST cs; - const char *name; - int i; - - if (*this_cache) - return (struct trad_frame_cache *) *this_cache; - - cache = trad_frame_cache_zalloc (this_frame); - *this_cache = cache; - - func = get_frame_func (this_frame); - sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM); - - find_pc_partial_function (func, &name, NULL, NULL); - if (name && startswith (name, "Xintr")) - addr = sp + 8; /* It's an interrupt frame. */ - else - addr = sp; - - for (i = 0; i < ARRAY_SIZE (i386obsd_tf_reg_offset); i++) - if (i386obsd_tf_reg_offset[i] != -1) - trad_frame_set_reg_addr (cache, i, addr + i386obsd_tf_reg_offset[i]); - - /* Read %cs from trap frame. */ - addr += i386obsd_tf_reg_offset[I386_CS_REGNUM]; - cs = read_memory_unsigned_integer (addr, 4, byte_order); - if ((cs & I386_SEL_RPL) == I386_SEL_UPL) - { - /* Trap from user space; terminate backtrace. */ - trad_frame_set_id (cache, outer_frame_id); - } - else - { - /* Construct the frame ID using the function start. */ - trad_frame_set_id (cache, frame_id_build (sp + 8, func)); - } - - return cache; -} - -static void -i386obsd_trapframe_this_id (struct frame_info *this_frame, - void **this_cache, struct frame_id *this_id) -{ - struct trad_frame_cache *cache = - i386obsd_trapframe_cache (this_frame, this_cache); - - trad_frame_get_id (cache, this_id); -} - -static struct value * -i386obsd_trapframe_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct trad_frame_cache *cache = - i386obsd_trapframe_cache (this_frame, this_cache); - - return trad_frame_get_register (cache, this_frame, regnum); -} - -static int -i386obsd_trapframe_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_prologue_cache) -{ - ULONGEST cs; - const char *name; - - /* Check Current Privilege Level and bail out if we're not executing - in kernel space. */ - cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM); - if ((cs & I386_SEL_RPL) == I386_SEL_UPL) - return 0; - - find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL); - return (name && (strcmp (name, "calltrap") == 0 - || strcmp (name, "syscall1") == 0 - || startswith (name, "Xintr") - || startswith (name, "Xsoft"))); -} - -static const struct frame_unwind i386obsd_trapframe_unwind = { - /* FIXME: kettenis/20051219: This really is more like an interrupt - frame, but SIGTRAMP_FRAME would print , - which really is not what we want here. */ - NORMAL_FRAME, - default_frame_unwind_stop_reason, - i386obsd_trapframe_this_id, - i386obsd_trapframe_prev_register, - NULL, - i386obsd_trapframe_sniffer -}; - - -static void -i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Obviously OpenBSD is BSD-based. */ - i386bsd_init_abi (info, gdbarch); - obsd_init_abi (info, gdbarch); - - /* OpenBSD has a different `struct reg'. */ - tdep->gregset_reg_offset = i386obsd_r_reg_offset; - tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset); - tdep->sizeof_gregset = 16 * 4; - - /* OpenBSD uses -freg-struct-return by default. */ - tdep->struct_return = reg_struct_return; - - /* OpenBSD uses a different memory layout. */ - tdep->sigtramp_start = i386obsd_sigtramp_start_addr; - tdep->sigtramp_end = i386obsd_sigtramp_end_addr; - tdep->sigtramp_p = i386obsd_sigtramp_p; - - /* OpenBSD has a `struct sigcontext' that's different from the - original 4.3 BSD. */ - tdep->sc_reg_offset = i386obsd_sc_reg_offset; - tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset); - - /* OpenBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, i386obsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, i386obsd_collect_uthread); - - /* Unwind kernel trap frames correctly. */ - frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind); -} - -/* OpenBSD a.out. */ - -static void -i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - i386obsd_init_abi (info, gdbarch); - - /* OpenBSD a.out has a single register set. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, i386obsd_aout_iterate_over_regset_sections); -} - -/* OpenBSD ELF. */ - -static void -i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* It's still OpenBSD. */ - i386obsd_init_abi (info, gdbarch); - - /* But ELF-based. */ - i386_elf_init_abi (info, gdbarch); - - /* OpenBSD ELF uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_i386obsd_tdep (void); - -void -_initialize_i386obsd_tdep (void) -{ - /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are - indistingushable from NetBSD/i386 a.out binaries, building a GDB - that should support both these targets will probably not work as - expected. */ -#define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT - - gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT, - i386obsd_aout_init_abi); - gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF, - i386obsd_elf_init_abi); -} diff --git a/gdb/i386v4-nat.c b/gdb/i386v4-nat.c deleted file mode 100644 index 4d1020b8d63..00000000000 --- a/gdb/i386v4-nat.c +++ /dev/null @@ -1,163 +0,0 @@ -/* Native-dependent code for Unix SVR4 running on i386's. - - Copyright (C) 1988-2016 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 "value.h" -#include "inferior.h" -#include "regcache.h" - -#ifdef HAVE_SYS_REG_H -#include -#endif - -#include "i386-tdep.h" -#include "i387-tdep.h" - -#ifdef HAVE_SYS_PROCFS_H - -#include - -/* We must not compile this code for 64-bit Solaris x86. */ -#if !defined (PR_MODEL_NATIVE) || (PR_MODEL_NATIVE == PR_MODEL_ILP32) - -#include "gregset.h" - -/* The `/proc' interface divides the target machine's register set up - into two different sets, the general purpose register set (gregset) - and the floating-point register set (fpregset). For each set, - there is an ioctl to get the current register set and another ioctl - to set the current values. - - The actual structure passed through the ioctl interface is, of - course, naturally machine dependent, and is different for each set - of registers. For the i386 for example, the general-purpose - register set is typically defined by: - - typedef int gregset_t[19]; (in ) - - #define GS 0 (in ) - #define FS 1 - ... - #define UESP 17 - #define SS 18 - - and the floating-point set by: - - typedef struct fpregset { - union { - struct fpchip_state // fp extension state // - { - int state[27]; // 287/387 saved state // - int status; // status word saved at // - // exception // - } fpchip_state; - struct fp_emul_space // for emulators // - { - char fp_emul[246]; - char fp_epad[2]; - } fp_emul_space; - int f_fpregs[62]; // union of the above // - } fp_reg_set; - long f_wregs[33]; // saved weitek state // - } fpregset_t; - - Incidentally fpchip_state contains the FPU state in the same format - as used by the "fsave" instruction, and that's the only thing we - support here. I don't know how the emulator stores it state. The - Weitek stuff definitely isn't supported. - - The routines defined here, provide the packing and unpacking of - gregset_t and fpregset_t formatted data. */ - -#ifdef HAVE_GREGSET_T - -/* Mapping between the general-purpose registers in `/proc' - format and GDB's register array layout. */ -static int regmap[] = -{ - EAX, ECX, EDX, EBX, - UESP, EBP, ESI, EDI, - EIP, EFL, CS, SS, - DS, ES, FS, GS -}; - -/* Fill GDB's register array with the general-purpose register values - in *GREGSETP. */ - -void -supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) -{ - const greg_t *regp = (const greg_t *) gregsetp; - int regnum; - - for (regnum = 0; regnum < I386_NUM_GREGS; regnum++) - regcache_raw_supply (regcache, regnum, regp + regmap[regnum]); -} - -/* Fill register REGNUM (if it is a general-purpose register) in - *GREGSETPS with the value in GDB's register array. If REGNUM is -1, - do this for all registers. */ - -void -fill_gregset (const struct regcache *regcache, - gregset_t *gregsetp, int regnum) -{ - greg_t *regp = (greg_t *) gregsetp; - int i; - - for (i = 0; i < I386_NUM_GREGS; i++) - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, regp + regmap[i]); -} - -#endif /* HAVE_GREGSET_T */ - -#ifdef HAVE_FPREGSET_T - -/* Fill GDB's register array with the floating-point register values in - *FPREGSETP. */ - -void -supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) -{ - if (gdbarch_fp0_regnum (get_regcache_arch (regcache)) == 0) - return; - - i387_supply_fsave (regcache, -1, fpregsetp); -} - -/* Fill register REGNO (if it is a floating-point register) in - *FPREGSETP with the value in GDB's register array. If REGNO is -1, - do this for all registers. */ - -void -fill_fpregset (const struct regcache *regcache, - fpregset_t *fpregsetp, int regno) -{ - if (gdbarch_fp0_regnum (get_regcache_arch (regcache)) == 0) - return; - - i387_collect_fsave (regcache, regno, fpregsetp); -} - -#endif /* HAVE_FPREGSET_T */ - -#endif /* not 64-bit. */ - -#endif /* HAVE_SYS_PROCFS_H */ diff --git a/gdb/m68k-bsd-nat.c b/gdb/m68k-bsd-nat.c new file mode 100644 index 00000000000..b39847585eb --- /dev/null +++ b/gdb/m68k-bsd-nat.c @@ -0,0 +1,237 @@ +/* Native-dependent code for Motorola 68000 BSD's. + + Copyright (C) 2004-2016 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 "inferior.h" +#include "regcache.h" + +#include +#include +#include + +#include "m68k-tdep.h" +#include "inf-ptrace.h" + +static int +m68kbsd_gregset_supplies_p (int regnum) +{ + return (regnum >= M68K_D0_REGNUM && regnum <= M68K_PC_REGNUM); +} + +static int +m68kbsd_fpregset_supplies_p (int regnum) +{ + return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM); +} + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +m68kbsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + int regnum; + + for (regnum = M68K_D0_REGNUM; regnum <= M68K_PC_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); +} + +/* Supply the floating-point registers stored in FPREGS to REGCACHE. */ + +static void +m68kbsd_supply_fpregset (struct regcache *regcache, const void *fpregs) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + const char *regs = fpregs; + int regnum; + + for (regnum = M68K_FP0_REGNUM; regnum <= M68K_FPI_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, + regs + m68kbsd_fpreg_offset (gdbarch, regnum)); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +m68kbsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } +} + +/* Collect the floating-point registers from REGCACHE and store them + in FPREGS. */ + +static void +m68kbsd_collect_fpregset (struct regcache *regcache, + void *fpregs, int regnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + char *regs = fpregs; + int i; + + for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, + regs + m68kbsd_fpreg_offset (gdbarch, i)); + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers (including the floating-point registers). */ + +static void +m68kbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + m68kbsd_supply_gregset (regcache, ®s); + } + + if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + m68kbsd_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). */ + +static void +m68kbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + m68kbsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + m68kbsd_collect_fpregset (regcache, &fpregs, regnum); + + if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + + +/* Support for debugging kernel virtual memory images. */ + +#include + +#include "bsd-kvm.h" + +/* OpenBSD doesn't have these. */ +#ifndef PCB_REGS_FP +#define PCB_REGS_FP 10 +#endif +#ifndef PCB_REGS_SP +#define PCB_REGS_SP 11 +#endif + +static int +m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + int regnum, tmp; + int i = 0; + + /* The following is true for NetBSD 1.6.2: + + The pcb contains %d2...%d7, %a2...%a7 and %ps. This accounts for + all callee-saved registers. 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_regs[PCB_REGS_SP] == 0) + return 0; + + for (regnum = M68K_D2_REGNUM; regnum <= M68K_D7_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]); + for (regnum = M68K_A2_REGNUM; regnum <= M68K_SP_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]); + + tmp = pcb->pcb_ps & 0xffff; + regcache_raw_supply (regcache, M68K_PS_REGNUM, &tmp); + + read_memory (pcb->pcb_regs[PCB_REGS_FP] + 4, (char *) &tmp, sizeof tmp); + regcache_raw_supply (regcache, M68K_PC_REGNUM, &tmp); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_m68kbsd_nat (void); + +void +_initialize_m68kbsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = m68kbsd_fetch_inferior_registers; + t->to_store_registers = m68kbsd_store_inferior_registers; + add_target (t); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (m68kbsd_supply_pcb); +} diff --git a/gdb/m68k-bsd-tdep.c b/gdb/m68k-bsd-tdep.c new file mode 100644 index 00000000000..0d2a4e9577f --- /dev/null +++ b/gdb/m68k-bsd-tdep.c @@ -0,0 +1,270 @@ +/* Target-dependent code for Motorola 68000 BSD's. + + Copyright (C) 2004-2016 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 "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "trad-frame.h" +#include "tramp-frame.h" +#include "gdbtypes.h" + +#include "m68k-tdep.h" +#include "solib-svr4.h" + +/* Core file support. */ + +/* Sizeof `struct reg' in . */ +#define M68KBSD_SIZEOF_GREGS (18 * 4) + +/* Sizeof `struct fpreg' in = M68K_FPC_REGNUM) + return 8 * fp_len + (regnum - M68K_FPC_REGNUM) * 4; + + return (regnum - M68K_FP0_REGNUM) * fp_len; +} + +/* 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 +m68kbsd_supply_fpregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + const gdb_byte *regs = (const gdb_byte *) fpregs; + int i; + + gdb_assert (len >= M68KBSD_SIZEOF_FPREGS); + + for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, + regs + m68kbsd_fpreg_offset (gdbarch, i)); + } +} + +/* 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 +m68kbsd_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 >= M68KBSD_SIZEOF_GREGS); + + for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + i * 4); + } + + if (len >= M68KBSD_SIZEOF_GREGS + M68KBSD_SIZEOF_FPREGS) + { + regs += M68KBSD_SIZEOF_GREGS; + len -= M68KBSD_SIZEOF_GREGS; + m68kbsd_supply_fpregset (regset, regcache, regnum, regs, len); + } +} + +/* Motorola 68000 register sets. */ + +static const struct regset m68kbsd_gregset = +{ + NULL, + m68kbsd_supply_gregset, + NULL, + REGSET_VARIABLE_SIZE +}; + +static const struct regset m68kbsd_fpregset = +{ + NULL, + m68kbsd_supply_fpregset +}; + +/* Iterate over core file register note sections. */ + +static void +m68kbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", M68KBSD_SIZEOF_GREGS, &m68kbsd_gregset, NULL, cb_data); + cb (".reg2", M68KBSD_SIZEOF_FPREGS, &m68kbsd_fpregset, NULL, cb_data); +} + + +/* Signal trampolines. */ + +static void +m68kobsd_sigtramp_cache_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *this_cache, + CORE_ADDR func) +{ + CORE_ADDR addr, base, pc; + int regnum; + + base = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM); + + /* The 'addql #4,%sp' instruction at offset 8 adjusts the stack + pointer. Adjust the frame base accordingly. */ + pc = get_frame_register_unsigned (this_frame, M68K_PC_REGNUM); + if ((pc - func) > 8) + base -= 4; + + /* Get frame pointer, stack pointer, program counter and processor + state from `struct sigcontext'. */ + addr = get_frame_memory_unsigned (this_frame, base + 8, 4); + trad_frame_set_reg_addr (this_cache, M68K_FP_REGNUM, addr + 8); + trad_frame_set_reg_addr (this_cache, M68K_SP_REGNUM, addr + 12); + trad_frame_set_reg_addr (this_cache, M68K_PC_REGNUM, addr + 20); + trad_frame_set_reg_addr (this_cache, M68K_PS_REGNUM, addr + 24); + + /* The sc_ap member of `struct sigcontext' points to additional + hardware state. Here we find the missing registers. */ + addr = get_frame_memory_unsigned (this_frame, addr + 16, 4) + 4; + for (regnum = M68K_D0_REGNUM; regnum < M68K_FP_REGNUM; regnum++, addr += 4) + trad_frame_set_reg_addr (this_cache, regnum, addr); + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (this_cache, frame_id_build (base, func)); +} + +static const struct tramp_frame m68kobsd_sigtramp = { + SIGTRAMP_FRAME, + 2, + { + { 0x206f, -1 }, { 0x000c, -1}, /* moveal %sp@(12),%a0 */ + { 0x4e90, -1 }, /* jsr %a0@ */ + { 0x588f, -1 }, /* addql #4,%sp */ + { 0x4e41, -1 }, /* trap #1 */ + { 0x2f40, -1 }, { 0x0004, -1 }, /* moveal %d0,%sp@(4) */ + { 0x7001, -1 }, /* moveq #SYS_exit,%d0 */ + { 0x4e40, -1 }, /* trap #0 */ + { TRAMP_SENTINEL_INSN, -1 } + }, + m68kobsd_sigtramp_cache_init +}; + + +static void +m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + tdep->jb_pc = 5; + tdep->jb_elt_size = 4; + + set_gdbarch_decr_pc_after_break (gdbarch, 2); + + set_gdbarch_iterate_over_regset_sections + (gdbarch, m68kbsd_iterate_over_regset_sections); +} + +/* OpenBSD and NetBSD a.out. */ + +static void +m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + m68kbsd_init_abi (info, gdbarch); + + tdep->struct_return = reg_struct_return; + + tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp); +} + +/* NetBSD ELF. */ + +static void +m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + m68kbsd_init_abi (info, gdbarch); + + /* NetBSD ELF uses the SVR4 ABI. */ + m68k_svr4_init_abi (info, gdbarch); + tdep->struct_return = pcc_struct_return; + + /* NetBSD ELF uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + + +static enum gdb_osabi +m68kbsd_aout_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0 + || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0) + return GDB_OSABI_NETBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + +static enum gdb_osabi +m68kbsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_m68kbsd_tdep (void); + +void +_initialize_m68kbsd_tdep (void) +{ + gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour, + m68kbsd_aout_osabi_sniffer); + + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour, + m68kbsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT, + m68kbsd_aout_init_abi); + gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF, + m68kbsd_elf_init_abi); +} diff --git a/gdb/m68k-linux-nat.c b/gdb/m68k-linux-nat.c new file mode 100644 index 00000000000..5b8684b7197 --- /dev/null +++ b/gdb/m68k-linux-nat.c @@ -0,0 +1,542 @@ +/* Motorola m68k native support for GNU/Linux. + + Copyright (C) 1996-2016 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 "frame.h" +#include "inferior.h" +#include "language.h" +#include "gdbcore.h" +#include "regcache.h" +#include "target.h" +#include "linux-nat.h" + +#include "m68k-tdep.h" + +#include +#include +#include "nat/gdb_ptrace.h" +#include +#include +#include +#include + +#ifdef HAVE_SYS_REG_H +#include +#endif + +#include +#include + +#include "floatformat.h" + +/* Prototypes for supply_gregset etc. */ +#include "gregset.h" + +/* Defines ps_err_e, struct ps_prochandle. */ +#include "gdb_proc_service.h" + +#ifndef PTRACE_GET_THREAD_AREA +#define PTRACE_GET_THREAD_AREA 25 +#endif + +/* This table must line up with gdbarch_register_name in "m68k-tdep.c". */ +static const int regmap[] = +{ + PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7, + PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP, + PT_SR, PT_PC, + /* PT_FP0, ..., PT_FP7 */ + 21, 24, 27, 30, 33, 36, 39, 42, + /* PT_FPCR, PT_FPSR, PT_FPIAR */ + 45, 46, 47 +}; + +/* Which ptrace request retrieves which registers? + These apply to the corresponding SET requests as well. */ +#define NUM_GREGS (18) +#define MAX_NUM_REGS (NUM_GREGS + 11) + +static int +getregs_supplies (int regno) +{ + return 0 <= regno && regno < NUM_GREGS; +} + +static int +getfpregs_supplies (int regno) +{ + return M68K_FP0_REGNUM <= regno && regno <= M68K_FPI_REGNUM; +} + +/* Does the current host support the GETREGS request? */ +static int have_ptrace_getregs = +#ifdef HAVE_PTRACE_GETREGS + 1 +#else + 0 +#endif +; + + + +/* Fetching registers directly from the U area, one at a time. */ + +/* Fetch one register. */ + +static void +fetch_register (struct regcache *regcache, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + long regaddr, val; + int i; + gdb_byte buf[MAX_REGISTER_SIZE]; + int tid; + + /* Overload thread id onto process id. */ + tid = ptid_get_lwp (inferior_ptid); + if (tid == 0) + tid = ptid_get_pid (inferior_ptid); /* no thread id, just use + process id. */ + + regaddr = 4 * regmap[regno]; + for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long)) + { + errno = 0; + val = ptrace (PTRACE_PEEKUSER, tid, regaddr, 0); + memcpy (&buf[i], &val, sizeof (long)); + regaddr += sizeof (long); + if (errno != 0) + error (_("Couldn't read register %s (#%d): %s."), + gdbarch_register_name (gdbarch, regno), + regno, safe_strerror (errno)); + } + regcache_raw_supply (regcache, regno, buf); +} + +/* Fetch register values from the inferior. + If REGNO is negative, do this for all registers. + Otherwise, REGNO specifies which register (so we can save time). */ + +static void +old_fetch_inferior_registers (struct regcache *regcache, int regno) +{ + if (regno >= 0) + { + fetch_register (regcache, regno); + } + else + { + for (regno = 0; + regno < gdbarch_num_regs (get_regcache_arch (regcache)); + regno++) + { + fetch_register (regcache, regno); + } + } +} + +/* Store one register. */ + +static void +store_register (const struct regcache *regcache, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + long regaddr, val; + int i; + int tid; + gdb_byte buf[MAX_REGISTER_SIZE]; + + /* Overload thread id onto process id. */ + tid = ptid_get_lwp (inferior_ptid); + if (tid == 0) + tid = ptid_get_pid (inferior_ptid); /* no thread id, just use + process id. */ + + regaddr = 4 * regmap[regno]; + + /* Put the contents of regno into a local buffer. */ + regcache_raw_collect (regcache, regno, buf); + + /* Store the local buffer into the inferior a chunk at the time. */ + for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long)) + { + errno = 0; + memcpy (&val, &buf[i], sizeof (long)); + ptrace (PTRACE_POKEUSER, tid, regaddr, val); + regaddr += sizeof (long); + if (errno != 0) + error (_("Couldn't write register %s (#%d): %s."), + gdbarch_register_name (gdbarch, regno), + regno, safe_strerror (errno)); + } +} + +/* Store our register values back into the inferior. + If REGNO is negative, do this for all registers. + Otherwise, REGNO specifies which register (so we can save time). */ + +static void +old_store_inferior_registers (const struct regcache *regcache, int regno) +{ + if (regno >= 0) + { + store_register (regcache, regno); + } + else + { + for (regno = 0; + regno < gdbarch_num_regs (get_regcache_arch (regcache)); + regno++) + { + store_register (regcache, regno); + } + } +} + +/* Given a pointer to a general register set in /proc format + (elf_gregset_t *), unpack the register contents and supply + them as gdb's idea of the current register values. */ + +void +supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + const elf_greg_t *regp = (const elf_greg_t *) gregsetp; + int regi; + + for (regi = M68K_D0_REGNUM; + regi <= gdbarch_sp_regnum (gdbarch); + regi++) + regcache_raw_supply (regcache, regi, ®p[regmap[regi]]); + regcache_raw_supply (regcache, gdbarch_ps_regnum (gdbarch), + ®p[PT_SR]); + regcache_raw_supply (regcache, + gdbarch_pc_regnum (gdbarch), ®p[PT_PC]); +} + +/* Fill register REGNO (if it is a general-purpose register) in + *GREGSETPS with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ +void +fill_gregset (const struct regcache *regcache, + elf_gregset_t *gregsetp, int regno) +{ + elf_greg_t *regp = (elf_greg_t *) gregsetp; + int i; + + for (i = 0; i < NUM_GREGS; i++) + if (regno == -1 || regno == i) + regcache_raw_collect (regcache, i, regp + regmap[i]); +} + +#ifdef HAVE_PTRACE_GETREGS + +/* Fetch all general-purpose registers from process/thread TID and + store their values in GDB's register array. */ + +static void +fetch_regs (struct regcache *regcache, int tid) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + { + if (errno == EIO) + { + /* The kernel we're running on doesn't support the GETREGS + request. Reset `have_ptrace_getregs'. */ + have_ptrace_getregs = 0; + return; + } + + perror_with_name (_("Couldn't get registers")); + } + + supply_gregset (regcache, (const elf_gregset_t *) ®s); +} + +/* Store all valid general-purpose registers in GDB's register array + into the process/thread specified by TID. */ + +static void +store_regs (const struct regcache *regcache, int tid, int regno) +{ + elf_gregset_t regs; + + if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) + perror_with_name (_("Couldn't get registers")); + + fill_gregset (regcache, ®s, regno); + + if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) + perror_with_name (_("Couldn't write registers")); +} + +#else + +static void fetch_regs (struct regcache *regcache, int tid) +{ +} + +static void store_regs (const struct regcache *regcache, int tid, int regno) +{ +} + +#endif + + +/* Transfering floating-point registers between GDB, inferiors and cores. */ + +/* What is the address of fpN within the floating-point register set F? */ +#define FPREG_ADDR(f, n) (&(f)->fpregs[(n) * 3]) + +/* Fill GDB's register array with the floating-point register values in + *FPREGSETP. */ + +void +supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int regi; + + for (regi = gdbarch_fp0_regnum (gdbarch); + regi < gdbarch_fp0_regnum (gdbarch) + 8; regi++) + regcache_raw_supply (regcache, regi, + FPREG_ADDR (fpregsetp, + regi - gdbarch_fp0_regnum (gdbarch))); + regcache_raw_supply (regcache, M68K_FPC_REGNUM, &fpregsetp->fpcntl[0]); + regcache_raw_supply (regcache, M68K_FPS_REGNUM, &fpregsetp->fpcntl[1]); + regcache_raw_supply (regcache, M68K_FPI_REGNUM, &fpregsetp->fpcntl[2]); +} + +/* Fill register REGNO (if it is a floating-point register) in + *FPREGSETP with the value in GDB's register array. If REGNO is -1, + do this for all registers. */ + +void +fill_fpregset (const struct regcache *regcache, + elf_fpregset_t *fpregsetp, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + int i; + + /* Fill in the floating-point registers. */ + for (i = gdbarch_fp0_regnum (gdbarch); + i < gdbarch_fp0_regnum (gdbarch) + 8; i++) + if (regno == -1 || regno == i) + regcache_raw_collect (regcache, i, + FPREG_ADDR (fpregsetp, + i - gdbarch_fp0_regnum (gdbarch))); + + /* Fill in the floating-point control registers. */ + for (i = M68K_FPC_REGNUM; i <= M68K_FPI_REGNUM; i++) + if (regno == -1 || regno == i) + regcache_raw_collect (regcache, i, + &fpregsetp->fpcntl[i - M68K_FPC_REGNUM]); +} + +#ifdef HAVE_PTRACE_GETREGS + +/* Fetch all floating-point registers from process/thread TID and store + thier values in GDB's register array. */ + +static void +fetch_fpregs (struct regcache *regcache, int tid) +{ + elf_fpregset_t fpregs; + + if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) + perror_with_name (_("Couldn't get floating point status")); + + supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs); +} + +/* Store all valid floating-point registers in GDB's register array + into the process/thread specified by TID. */ + +static void +store_fpregs (const struct regcache *regcache, int tid, int regno) +{ + elf_fpregset_t fpregs; + + if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) + perror_with_name (_("Couldn't get floating point status")); + + fill_fpregset (regcache, &fpregs, regno); + + if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0) + perror_with_name (_("Couldn't write floating point status")); +} + +#else + +static void fetch_fpregs (struct regcache *regcache, int tid) +{ +} + +static void store_fpregs (const struct regcache *regcache, int tid, int regno) +{ +} + +#endif + +/* Transferring arbitrary registers between GDB and inferior. */ + +/* Fetch register REGNO from the child process. If REGNO is -1, do + this for all registers (including the floating point and SSE + registers). */ + +static void +m68k_linux_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + int tid; + + /* Use the old method of peeking around in `struct user' if the + GETREGS request isn't available. */ + if (! have_ptrace_getregs) + { + old_fetch_inferior_registers (regcache, regno); + return; + } + + /* GNU/Linux LWP ID's are process ID's. */ + tid = ptid_get_lwp (inferior_ptid); + if (tid == 0) + tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_GETFPXREGS request whenever possible, since it + transfers more registers in one system call, and we'll cache the + results. But remember that fetch_fpxregs can fail, and return + zero. */ + if (regno == -1) + { + fetch_regs (regcache, tid); + + /* The call above might reset `have_ptrace_getregs'. */ + if (! have_ptrace_getregs) + { + old_fetch_inferior_registers (regcache, -1); + return; + } + + fetch_fpregs (regcache, tid); + return; + } + + if (getregs_supplies (regno)) + { + fetch_regs (regcache, tid); + return; + } + + if (getfpregs_supplies (regno)) + { + fetch_fpregs (regcache, tid); + return; + } + + internal_error (__FILE__, __LINE__, + _("Got request for bad register number %d."), regno); +} + +/* Store register REGNO back into the child process. If REGNO is -1, + do this for all registers (including the floating point and SSE + registers). */ +static void +m68k_linux_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + int tid; + + /* Use the old method of poking around in `struct user' if the + SETREGS request isn't available. */ + if (! have_ptrace_getregs) + { + old_store_inferior_registers (regcache, regno); + return; + } + + /* GNU/Linux LWP ID's are process ID's. */ + tid = ptid_get_lwp (inferior_ptid); + if (tid == 0) + tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */ + + /* Use the PTRACE_SETFPREGS requests whenever possible, since it + transfers more registers in one system call. But remember that + store_fpregs can fail, and return zero. */ + if (regno == -1) + { + store_regs (regcache, tid, regno); + store_fpregs (regcache, tid, regno); + return; + } + + if (getregs_supplies (regno)) + { + store_regs (regcache, tid, regno); + return; + } + + if (getfpregs_supplies (regno)) + { + store_fpregs (regcache, tid, regno); + return; + } + + internal_error (__FILE__, __LINE__, + _("Got request to store bad register number %d."), regno); +} + + +/* Fetch the thread-local storage pointer for libthread_db. */ + +ps_err_e +ps_get_thread_area (struct ps_prochandle *ph, + lwpid_t lwpid, int idx, void **base) +{ + if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) < 0) + return PS_ERR; + + /* IDX is the bias from the thread pointer to the beginning of the + thread descriptor. It has to be subtracted due to implementation + quirks in libthread_db. */ + *base = (char *) *base - idx; + + return PS_OK; +} + + +void _initialize_m68k_linux_nat (void); + +void +_initialize_m68k_linux_nat (void) +{ + struct target_ops *t; + + /* Fill in the generic GNU/Linux methods. */ + t = linux_target (); + + /* Add our register access methods. */ + t->to_fetch_registers = m68k_linux_fetch_inferior_registers; + t->to_store_registers = m68k_linux_store_inferior_registers; + + /* Register the target. */ + linux_nat_add_target (t); +} diff --git a/gdb/m68k-linux-tdep.c b/gdb/m68k-linux-tdep.c new file mode 100644 index 00000000000..94fb953edf0 --- /dev/null +++ b/gdb/m68k-linux-tdep.c @@ -0,0 +1,435 @@ +/* Motorola m68k target-dependent support for GNU/Linux. + + Copyright (C) 1996-2016 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 "doublest.h" +#include "floatformat.h" +#include "frame.h" +#include "target.h" +#include "gdbtypes.h" +#include "osabi.h" +#include "regcache.h" +#include "objfiles.h" +#include "symtab.h" +#include "m68k-tdep.h" +#include "trad-frame.h" +#include "frame-unwind.h" +#include "glibc-tdep.h" +#include "solib-svr4.h" +#include "auxv.h" +#include "observer.h" +#include "elf/common.h" +#include "linux-tdep.h" +#include "regset.h" + +/* Offsets (in target ints) into jmp_buf. */ + +#define M68K_LINUX_JB_ELEMENT_SIZE 4 +#define M68K_LINUX_JB_PC 7 + +/* Check whether insn1 and insn2 are parts of a signal trampoline. */ + +#define IS_SIGTRAMP(insn1, insn2) \ + (/* addaw #20,sp; moveq #119,d0; trap #0 */ \ + (insn1 == 0xdefc0014 && insn2 == 0x70774e40) \ + /* moveq #119,d0; trap #0 */ \ + || insn1 == 0x70774e40) + +#define IS_RT_SIGTRAMP(insn1, insn2) \ + (/* movel #173,d0; trap #0 */ \ + (insn1 == 0x203c0000 && insn2 == 0x00ad4e40) \ + /* moveq #82,d0; notb d0; trap #0 */ \ + || (insn1 == 0x70524600 && (insn2 >> 16) == 0x4e40)) + +/* Return non-zero if THIS_FRAME corresponds to a signal trampoline. For + the sake of m68k_linux_get_sigtramp_info we also distinguish between + non-RT and RT signal trampolines. */ + +static int +m68k_linux_pc_in_sigtramp (struct frame_info *this_frame) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + gdb_byte buf[12]; + unsigned long insn0, insn1, insn2; + CORE_ADDR pc = get_frame_pc (this_frame); + + if (!safe_frame_unwind_memory (this_frame, pc - 4, buf, sizeof (buf))) + return 0; + insn1 = extract_unsigned_integer (buf + 4, 4, byte_order); + insn2 = extract_unsigned_integer (buf + 8, 4, byte_order); + if (IS_SIGTRAMP (insn1, insn2)) + return 1; + if (IS_RT_SIGTRAMP (insn1, insn2)) + return 2; + + insn0 = extract_unsigned_integer (buf, 4, byte_order); + if (IS_SIGTRAMP (insn0, insn1)) + return 1; + if (IS_RT_SIGTRAMP (insn0, insn1)) + return 2; + + insn0 = ((insn0 << 16) & 0xffffffff) | (insn1 >> 16); + insn1 = ((insn1 << 16) & 0xffffffff) | (insn2 >> 16); + if (IS_SIGTRAMP (insn0, insn1)) + return 1; + if (IS_RT_SIGTRAMP (insn0, insn1)) + return 2; + + return 0; +} + +/* From . */ +static int m68k_linux_sigcontext_reg_offset[M68K_NUM_REGS] = +{ + 2 * 4, /* %d0 */ + 3 * 4, /* %d1 */ + -1, /* %d2 */ + -1, /* %d3 */ + -1, /* %d4 */ + -1, /* %d5 */ + -1, /* %d6 */ + -1, /* %d7 */ + 4 * 4, /* %a0 */ + 5 * 4, /* %a1 */ + -1, /* %a2 */ + -1, /* %a3 */ + -1, /* %a4 */ + -1, /* %a5 */ + -1, /* %fp */ + 1 * 4, /* %sp */ + 6 * 4, /* %sr */ + 6 * 4 + 2, /* %pc */ + 8 * 4, /* %fp0 */ + 11 * 4, /* %fp1 */ + -1, /* %fp2 */ + -1, /* %fp3 */ + -1, /* %fp4 */ + -1, /* %fp5 */ + -1, /* %fp6 */ + -1, /* %fp7 */ + 14 * 4, /* %fpcr */ + 15 * 4, /* %fpsr */ + 16 * 4 /* %fpiaddr */ +}; + +static int m68k_uclinux_sigcontext_reg_offset[M68K_NUM_REGS] = +{ + 2 * 4, /* %d0 */ + 3 * 4, /* %d1 */ + -1, /* %d2 */ + -1, /* %d3 */ + -1, /* %d4 */ + -1, /* %d5 */ + -1, /* %d6 */ + -1, /* %d7 */ + 4 * 4, /* %a0 */ + 5 * 4, /* %a1 */ + -1, /* %a2 */ + -1, /* %a3 */ + -1, /* %a4 */ + 6 * 4, /* %a5 */ + -1, /* %fp */ + 1 * 4, /* %sp */ + 7 * 4, /* %sr */ + 7 * 4 + 2, /* %pc */ + -1, /* %fp0 */ + -1, /* %fp1 */ + -1, /* %fp2 */ + -1, /* %fp3 */ + -1, /* %fp4 */ + -1, /* %fp5 */ + -1, /* %fp6 */ + -1, /* %fp7 */ + -1, /* %fpcr */ + -1, /* %fpsr */ + -1 /* %fpiaddr */ +}; + +/* From . */ +static int m68k_linux_ucontext_reg_offset[M68K_NUM_REGS] = +{ + 6 * 4, /* %d0 */ + 7 * 4, /* %d1 */ + 8 * 4, /* %d2 */ + 9 * 4, /* %d3 */ + 10 * 4, /* %d4 */ + 11 * 4, /* %d5 */ + 12 * 4, /* %d6 */ + 13 * 4, /* %d7 */ + 14 * 4, /* %a0 */ + 15 * 4, /* %a1 */ + 16 * 4, /* %a2 */ + 17 * 4, /* %a3 */ + 18 * 4, /* %a4 */ + 19 * 4, /* %a5 */ + 20 * 4, /* %fp */ + 21 * 4, /* %sp */ + 23 * 4, /* %sr */ + 22 * 4, /* %pc */ + 27 * 4, /* %fp0 */ + 30 * 4, /* %fp1 */ + 33 * 4, /* %fp2 */ + 36 * 4, /* %fp3 */ + 39 * 4, /* %fp4 */ + 42 * 4, /* %fp5 */ + 45 * 4, /* %fp6 */ + 48 * 4, /* %fp7 */ + 24 * 4, /* %fpcr */ + 25 * 4, /* %fpsr */ + 26 * 4 /* %fpiaddr */ +}; + + +/* Get info about saved registers in sigtramp. */ + +struct m68k_linux_sigtramp_info +{ + /* Address of sigcontext. */ + CORE_ADDR sigcontext_addr; + + /* Offset of registers in `struct sigcontext'. */ + int *sc_reg_offset; +}; + +/* Nonzero if running on uClinux. */ +static int target_is_uclinux; + +static void +m68k_linux_inferior_created (struct target_ops *objfile, int from_tty) +{ + /* Record that we will need to re-evaluate whether we are running on a + uClinux or normal GNU/Linux target (see m68k_linux_get_sigtramp_info). */ + target_is_uclinux = -1; +} + +static struct m68k_linux_sigtramp_info +m68k_linux_get_sigtramp_info (struct frame_info *this_frame) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp; + struct m68k_linux_sigtramp_info info; + + /* Determine whether we are running on a uClinux or normal GNU/Linux + target so we can use the correct sigcontext layouts. */ + if (target_is_uclinux == -1) + target_is_uclinux = linux_is_uclinux (); + + sp = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM); + + /* Get sigcontext address, it is the third parameter on the stack. */ + info.sigcontext_addr = read_memory_unsigned_integer (sp + 8, 4, byte_order); + + if (m68k_linux_pc_in_sigtramp (this_frame) == 2) + info.sc_reg_offset = m68k_linux_ucontext_reg_offset; + else + info.sc_reg_offset = (target_is_uclinux + ? m68k_uclinux_sigcontext_reg_offset + : m68k_linux_sigcontext_reg_offset); + return info; +} + +/* Signal trampolines. */ + +static struct trad_frame_cache * +m68k_linux_sigtramp_frame_cache (struct frame_info *this_frame, + void **this_cache) +{ + struct frame_id this_id; + struct trad_frame_cache *cache; + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct m68k_linux_sigtramp_info info; + gdb_byte buf[4]; + int i; + + if (*this_cache) + return (struct trad_frame_cache *) *this_cache; + + cache = trad_frame_cache_zalloc (this_frame); + + /* FIXME: cagney/2004-05-01: This is is long standing broken code. + The frame ID's code address should be the start-address of the + signal trampoline and not the current PC within that + trampoline. */ + get_frame_register (this_frame, M68K_SP_REGNUM, buf); + /* See the end of m68k_push_dummy_call. */ + this_id = frame_id_build (extract_unsigned_integer (buf, 4, byte_order) + - 4 + 8, get_frame_pc (this_frame)); + trad_frame_set_id (cache, this_id); + + info = m68k_linux_get_sigtramp_info (this_frame); + + for (i = 0; i < M68K_NUM_REGS; i++) + if (info.sc_reg_offset[i] != -1) + trad_frame_set_reg_addr (cache, i, + info.sigcontext_addr + info.sc_reg_offset[i]); + + *this_cache = cache; + return cache; +} + +static void +m68k_linux_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct trad_frame_cache *cache = + m68k_linux_sigtramp_frame_cache (this_frame, this_cache); + trad_frame_get_id (cache, this_id); +} + +static struct value * +m68k_linux_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, + int regnum) +{ + /* Make sure we've initialized the cache. */ + struct trad_frame_cache *cache = + m68k_linux_sigtramp_frame_cache (this_frame, this_cache); + return trad_frame_get_register (cache, this_frame, regnum); +} + +static int +m68k_linux_sigtramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + return m68k_linux_pc_in_sigtramp (this_frame); +} + +static const struct frame_unwind m68k_linux_sigtramp_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + m68k_linux_sigtramp_frame_this_id, + m68k_linux_sigtramp_frame_prev_register, + NULL, + m68k_linux_sigtramp_frame_sniffer +}; + +/* Register maps for supply/collect regset functions. */ + +static const struct regcache_map_entry m68k_linux_gregmap[] = + { + { 7, M68K_D1_REGNUM, 4 }, /* d1 ... d7 */ + { 7, M68K_A0_REGNUM, 4 }, /* a0 ... a6 */ + { 1, M68K_D0_REGNUM, 4 }, + { 1, M68K_SP_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 4 }, /* orig_d0 (skip) */ + { 1, M68K_PS_REGNUM, 4 }, + { 1, M68K_PC_REGNUM, 4 }, + /* Ignore 16-bit fields 'fmtvec' and '__fill'. */ + { 0 } + }; + +#define M68K_LINUX_GREGS_SIZE (20 * 4) + +static const struct regcache_map_entry m68k_linux_fpregmap[] = + { + { 8, M68K_FP0_REGNUM, 12 }, /* fp0 ... fp7 */ + { 1, M68K_FPC_REGNUM, 4 }, + { 1, M68K_FPS_REGNUM, 4 }, + { 1, M68K_FPI_REGNUM, 4 }, + { 0 } + }; + +#define M68K_LINUX_FPREGS_SIZE (27 * 4) + +/* Register sets. */ + +static const struct regset m68k_linux_gregset = + { + m68k_linux_gregmap, + regcache_supply_regset, regcache_collect_regset + }; + +static const struct regset m68k_linux_fpregset = + { + m68k_linux_fpregmap, + regcache_supply_regset, regcache_collect_regset + }; + +/* Iterate over core file register note sections. */ + +static void +m68k_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", M68K_LINUX_GREGS_SIZE, &m68k_linux_gregset, NULL, cb_data); + cb (".reg2", M68K_LINUX_FPREGS_SIZE, &m68k_linux_fpregset, NULL, cb_data); +} + +static void +m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + linux_init_abi (info, gdbarch); + + tdep->jb_pc = M68K_LINUX_JB_PC; + tdep->jb_elt_size = M68K_LINUX_JB_ELEMENT_SIZE; + + /* GNU/Linux uses a calling convention that's similar to SVR4. It + returns integer values in %d0/%d1, pointer values in %a0 and + floating values in %fp0, just like SVR4, but uses %a1 to pass the + address to store a structure value. It also returns small + structures in registers instead of memory. */ + m68k_svr4_init_abi (info, gdbarch); + tdep->struct_value_regnum = M68K_A1_REGNUM; + tdep->struct_return = reg_struct_return; + + set_gdbarch_decr_pc_after_break (gdbarch, 2); + + frame_unwind_append_unwinder (gdbarch, &m68k_linux_sigtramp_frame_unwind); + + /* Shared library handling. */ + + /* GNU/Linux uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets (gdbarch, + svr4_ilp32_fetch_link_map_offsets); + + /* GNU/Linux uses the dynamic linker included in the GNU C Library. */ + set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); + + set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); + + /* Core file support. */ + set_gdbarch_iterate_over_regset_sections + (gdbarch, m68k_linux_iterate_over_regset_sections); + + /* Enable TLS support. */ + set_gdbarch_fetch_tls_load_module_address (gdbarch, + svr4_fetch_objfile_link_map); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_m68k_linux_tdep; + +void +_initialize_m68k_linux_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_LINUX, + m68k_linux_init_abi); + observer_attach_inferior_created (m68k_linux_inferior_created); +} diff --git a/gdb/m68k-tdep.h b/gdb/m68k-tdep.h index db03192523e..a3433e1a0e8 100644 --- a/gdb/m68k-tdep.h +++ b/gdb/m68k-tdep.h @@ -101,7 +101,7 @@ struct gdbarch_tdep extern void m68k_svr4_init_abi (struct gdbarch_info, struct gdbarch *); -/* Functions exported from m68kbsd-tdep.c. */ +/* Functions exported from m68k-bsd-tdep.c. */ extern int m68kbsd_fpreg_offset (struct gdbarch *gdbarch, int regnum); diff --git a/gdb/m68kbsd-nat.c b/gdb/m68kbsd-nat.c deleted file mode 100644 index b39847585eb..00000000000 --- a/gdb/m68kbsd-nat.c +++ /dev/null @@ -1,237 +0,0 @@ -/* Native-dependent code for Motorola 68000 BSD's. - - Copyright (C) 2004-2016 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 "inferior.h" -#include "regcache.h" - -#include -#include -#include - -#include "m68k-tdep.h" -#include "inf-ptrace.h" - -static int -m68kbsd_gregset_supplies_p (int regnum) -{ - return (regnum >= M68K_D0_REGNUM && regnum <= M68K_PC_REGNUM); -} - -static int -m68kbsd_fpregset_supplies_p (int regnum) -{ - return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM); -} - -/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ - -static void -m68kbsd_supply_gregset (struct regcache *regcache, const void *gregs) -{ - const char *regs = gregs; - int regnum; - - for (regnum = M68K_D0_REGNUM; regnum <= M68K_PC_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, regs + regnum * 4); -} - -/* Supply the floating-point registers stored in FPREGS to REGCACHE. */ - -static void -m68kbsd_supply_fpregset (struct regcache *regcache, const void *fpregs) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - const char *regs = fpregs; - int regnum; - - for (regnum = M68K_FP0_REGNUM; regnum <= M68K_FPI_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, - regs + m68kbsd_fpreg_offset (gdbarch, regnum)); -} - -/* Collect the general-purpose registers from REGCACHE and store them - in GREGS. */ - -static void -m68kbsd_collect_gregset (const struct regcache *regcache, - void *gregs, int regnum) -{ - char *regs = gregs; - int i; - - for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) - { - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, regs + i * 4); - } -} - -/* Collect the floating-point registers from REGCACHE and store them - in FPREGS. */ - -static void -m68kbsd_collect_fpregset (struct regcache *regcache, - void *fpregs, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - char *regs = fpregs; - int i; - - for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++) - { - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, - regs + m68kbsd_fpreg_offset (gdbarch, i)); - } -} - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers (including the floating-point registers). */ - -static void -m68kbsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - m68kbsd_supply_gregset (regcache, ®s); - } - - if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - m68kbsd_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). */ - -static void -m68kbsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - m68kbsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - } - - if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - m68kbsd_collect_fpregset (regcache, &fpregs, regnum); - - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - - -/* Support for debugging kernel virtual memory images. */ - -#include - -#include "bsd-kvm.h" - -/* OpenBSD doesn't have these. */ -#ifndef PCB_REGS_FP -#define PCB_REGS_FP 10 -#endif -#ifndef PCB_REGS_SP -#define PCB_REGS_SP 11 -#endif - -static int -m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - int regnum, tmp; - int i = 0; - - /* The following is true for NetBSD 1.6.2: - - The pcb contains %d2...%d7, %a2...%a7 and %ps. This accounts for - all callee-saved registers. 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_regs[PCB_REGS_SP] == 0) - return 0; - - for (regnum = M68K_D2_REGNUM; regnum <= M68K_D7_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]); - for (regnum = M68K_A2_REGNUM; regnum <= M68K_SP_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, &pcb->pcb_regs[i++]); - - tmp = pcb->pcb_ps & 0xffff; - regcache_raw_supply (regcache, M68K_PS_REGNUM, &tmp); - - read_memory (pcb->pcb_regs[PCB_REGS_FP] + 4, (char *) &tmp, sizeof tmp); - regcache_raw_supply (regcache, M68K_PC_REGNUM, &tmp); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_m68kbsd_nat (void); - -void -_initialize_m68kbsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = m68kbsd_fetch_inferior_registers; - t->to_store_registers = m68kbsd_store_inferior_registers; - add_target (t); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (m68kbsd_supply_pcb); -} diff --git a/gdb/m68kbsd-tdep.c b/gdb/m68kbsd-tdep.c deleted file mode 100644 index 0d2a4e9577f..00000000000 --- a/gdb/m68kbsd-tdep.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Target-dependent code for Motorola 68000 BSD's. - - Copyright (C) 2004-2016 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 "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "trad-frame.h" -#include "tramp-frame.h" -#include "gdbtypes.h" - -#include "m68k-tdep.h" -#include "solib-svr4.h" - -/* Core file support. */ - -/* Sizeof `struct reg' in . */ -#define M68KBSD_SIZEOF_GREGS (18 * 4) - -/* Sizeof `struct fpreg' in = M68K_FPC_REGNUM) - return 8 * fp_len + (regnum - M68K_FPC_REGNUM) * 4; - - return (regnum - M68K_FP0_REGNUM) * fp_len; -} - -/* 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 -m68kbsd_supply_fpregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *fpregs, size_t len) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - const gdb_byte *regs = (const gdb_byte *) fpregs; - int i; - - gdb_assert (len >= M68KBSD_SIZEOF_FPREGS); - - for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, - regs + m68kbsd_fpreg_offset (gdbarch, i)); - } -} - -/* 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 -m68kbsd_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 >= M68KBSD_SIZEOF_GREGS); - - for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + i * 4); - } - - if (len >= M68KBSD_SIZEOF_GREGS + M68KBSD_SIZEOF_FPREGS) - { - regs += M68KBSD_SIZEOF_GREGS; - len -= M68KBSD_SIZEOF_GREGS; - m68kbsd_supply_fpregset (regset, regcache, regnum, regs, len); - } -} - -/* Motorola 68000 register sets. */ - -static const struct regset m68kbsd_gregset = -{ - NULL, - m68kbsd_supply_gregset, - NULL, - REGSET_VARIABLE_SIZE -}; - -static const struct regset m68kbsd_fpregset = -{ - NULL, - m68kbsd_supply_fpregset -}; - -/* Iterate over core file register note sections. */ - -static void -m68kbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", M68KBSD_SIZEOF_GREGS, &m68kbsd_gregset, NULL, cb_data); - cb (".reg2", M68KBSD_SIZEOF_FPREGS, &m68kbsd_fpregset, NULL, cb_data); -} - - -/* Signal trampolines. */ - -static void -m68kobsd_sigtramp_cache_init (const struct tramp_frame *self, - struct frame_info *this_frame, - struct trad_frame_cache *this_cache, - CORE_ADDR func) -{ - CORE_ADDR addr, base, pc; - int regnum; - - base = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM); - - /* The 'addql #4,%sp' instruction at offset 8 adjusts the stack - pointer. Adjust the frame base accordingly. */ - pc = get_frame_register_unsigned (this_frame, M68K_PC_REGNUM); - if ((pc - func) > 8) - base -= 4; - - /* Get frame pointer, stack pointer, program counter and processor - state from `struct sigcontext'. */ - addr = get_frame_memory_unsigned (this_frame, base + 8, 4); - trad_frame_set_reg_addr (this_cache, M68K_FP_REGNUM, addr + 8); - trad_frame_set_reg_addr (this_cache, M68K_SP_REGNUM, addr + 12); - trad_frame_set_reg_addr (this_cache, M68K_PC_REGNUM, addr + 20); - trad_frame_set_reg_addr (this_cache, M68K_PS_REGNUM, addr + 24); - - /* The sc_ap member of `struct sigcontext' points to additional - hardware state. Here we find the missing registers. */ - addr = get_frame_memory_unsigned (this_frame, addr + 16, 4) + 4; - for (regnum = M68K_D0_REGNUM; regnum < M68K_FP_REGNUM; regnum++, addr += 4) - trad_frame_set_reg_addr (this_cache, regnum, addr); - - /* Construct the frame ID using the function start. */ - trad_frame_set_id (this_cache, frame_id_build (base, func)); -} - -static const struct tramp_frame m68kobsd_sigtramp = { - SIGTRAMP_FRAME, - 2, - { - { 0x206f, -1 }, { 0x000c, -1}, /* moveal %sp@(12),%a0 */ - { 0x4e90, -1 }, /* jsr %a0@ */ - { 0x588f, -1 }, /* addql #4,%sp */ - { 0x4e41, -1 }, /* trap #1 */ - { 0x2f40, -1 }, { 0x0004, -1 }, /* moveal %d0,%sp@(4) */ - { 0x7001, -1 }, /* moveq #SYS_exit,%d0 */ - { 0x4e40, -1 }, /* trap #0 */ - { TRAMP_SENTINEL_INSN, -1 } - }, - m68kobsd_sigtramp_cache_init -}; - - -static void -m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->jb_pc = 5; - tdep->jb_elt_size = 4; - - set_gdbarch_decr_pc_after_break (gdbarch, 2); - - set_gdbarch_iterate_over_regset_sections - (gdbarch, m68kbsd_iterate_over_regset_sections); -} - -/* OpenBSD and NetBSD a.out. */ - -static void -m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - m68kbsd_init_abi (info, gdbarch); - - tdep->struct_return = reg_struct_return; - - tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp); -} - -/* NetBSD ELF. */ - -static void -m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - m68kbsd_init_abi (info, gdbarch); - - /* NetBSD ELF uses the SVR4 ABI. */ - m68k_svr4_init_abi (info, gdbarch); - tdep->struct_return = pcc_struct_return; - - /* NetBSD ELF uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - - -static enum gdb_osabi -m68kbsd_aout_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0 - || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0) - return GDB_OSABI_NETBSD_AOUT; - - return GDB_OSABI_UNKNOWN; -} - -static enum gdb_osabi -m68kbsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_NETBSD_AOUT; - - return GDB_OSABI_UNKNOWN; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_m68kbsd_tdep (void); - -void -_initialize_m68kbsd_tdep (void) -{ - gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour, - m68kbsd_aout_osabi_sniffer); - - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour, - m68kbsd_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT, - m68kbsd_aout_init_abi); - gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF, - m68kbsd_elf_init_abi); -} diff --git a/gdb/m68klinux-nat.c b/gdb/m68klinux-nat.c deleted file mode 100644 index 5b8684b7197..00000000000 --- a/gdb/m68klinux-nat.c +++ /dev/null @@ -1,542 +0,0 @@ -/* Motorola m68k native support for GNU/Linux. - - Copyright (C) 1996-2016 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 "frame.h" -#include "inferior.h" -#include "language.h" -#include "gdbcore.h" -#include "regcache.h" -#include "target.h" -#include "linux-nat.h" - -#include "m68k-tdep.h" - -#include -#include -#include "nat/gdb_ptrace.h" -#include -#include -#include -#include - -#ifdef HAVE_SYS_REG_H -#include -#endif - -#include -#include - -#include "floatformat.h" - -/* Prototypes for supply_gregset etc. */ -#include "gregset.h" - -/* Defines ps_err_e, struct ps_prochandle. */ -#include "gdb_proc_service.h" - -#ifndef PTRACE_GET_THREAD_AREA -#define PTRACE_GET_THREAD_AREA 25 -#endif - -/* This table must line up with gdbarch_register_name in "m68k-tdep.c". */ -static const int regmap[] = -{ - PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7, - PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP, - PT_SR, PT_PC, - /* PT_FP0, ..., PT_FP7 */ - 21, 24, 27, 30, 33, 36, 39, 42, - /* PT_FPCR, PT_FPSR, PT_FPIAR */ - 45, 46, 47 -}; - -/* Which ptrace request retrieves which registers? - These apply to the corresponding SET requests as well. */ -#define NUM_GREGS (18) -#define MAX_NUM_REGS (NUM_GREGS + 11) - -static int -getregs_supplies (int regno) -{ - return 0 <= regno && regno < NUM_GREGS; -} - -static int -getfpregs_supplies (int regno) -{ - return M68K_FP0_REGNUM <= regno && regno <= M68K_FPI_REGNUM; -} - -/* Does the current host support the GETREGS request? */ -static int have_ptrace_getregs = -#ifdef HAVE_PTRACE_GETREGS - 1 -#else - 0 -#endif -; - - - -/* Fetching registers directly from the U area, one at a time. */ - -/* Fetch one register. */ - -static void -fetch_register (struct regcache *regcache, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - long regaddr, val; - int i; - gdb_byte buf[MAX_REGISTER_SIZE]; - int tid; - - /* Overload thread id onto process id. */ - tid = ptid_get_lwp (inferior_ptid); - if (tid == 0) - tid = ptid_get_pid (inferior_ptid); /* no thread id, just use - process id. */ - - regaddr = 4 * regmap[regno]; - for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long)) - { - errno = 0; - val = ptrace (PTRACE_PEEKUSER, tid, regaddr, 0); - memcpy (&buf[i], &val, sizeof (long)); - regaddr += sizeof (long); - if (errno != 0) - error (_("Couldn't read register %s (#%d): %s."), - gdbarch_register_name (gdbarch, regno), - regno, safe_strerror (errno)); - } - regcache_raw_supply (regcache, regno, buf); -} - -/* Fetch register values from the inferior. - If REGNO is negative, do this for all registers. - Otherwise, REGNO specifies which register (so we can save time). */ - -static void -old_fetch_inferior_registers (struct regcache *regcache, int regno) -{ - if (regno >= 0) - { - fetch_register (regcache, regno); - } - else - { - for (regno = 0; - regno < gdbarch_num_regs (get_regcache_arch (regcache)); - regno++) - { - fetch_register (regcache, regno); - } - } -} - -/* Store one register. */ - -static void -store_register (const struct regcache *regcache, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - long regaddr, val; - int i; - int tid; - gdb_byte buf[MAX_REGISTER_SIZE]; - - /* Overload thread id onto process id. */ - tid = ptid_get_lwp (inferior_ptid); - if (tid == 0) - tid = ptid_get_pid (inferior_ptid); /* no thread id, just use - process id. */ - - regaddr = 4 * regmap[regno]; - - /* Put the contents of regno into a local buffer. */ - regcache_raw_collect (regcache, regno, buf); - - /* Store the local buffer into the inferior a chunk at the time. */ - for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long)) - { - errno = 0; - memcpy (&val, &buf[i], sizeof (long)); - ptrace (PTRACE_POKEUSER, tid, regaddr, val); - regaddr += sizeof (long); - if (errno != 0) - error (_("Couldn't write register %s (#%d): %s."), - gdbarch_register_name (gdbarch, regno), - regno, safe_strerror (errno)); - } -} - -/* Store our register values back into the inferior. - If REGNO is negative, do this for all registers. - Otherwise, REGNO specifies which register (so we can save time). */ - -static void -old_store_inferior_registers (const struct regcache *regcache, int regno) -{ - if (regno >= 0) - { - store_register (regcache, regno); - } - else - { - for (regno = 0; - regno < gdbarch_num_regs (get_regcache_arch (regcache)); - regno++) - { - store_register (regcache, regno); - } - } -} - -/* Given a pointer to a general register set in /proc format - (elf_gregset_t *), unpack the register contents and supply - them as gdb's idea of the current register values. */ - -void -supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - const elf_greg_t *regp = (const elf_greg_t *) gregsetp; - int regi; - - for (regi = M68K_D0_REGNUM; - regi <= gdbarch_sp_regnum (gdbarch); - regi++) - regcache_raw_supply (regcache, regi, ®p[regmap[regi]]); - regcache_raw_supply (regcache, gdbarch_ps_regnum (gdbarch), - ®p[PT_SR]); - regcache_raw_supply (regcache, - gdbarch_pc_regnum (gdbarch), ®p[PT_PC]); -} - -/* Fill register REGNO (if it is a general-purpose register) in - *GREGSETPS with the value in GDB's register array. If REGNO is -1, - do this for all registers. */ -void -fill_gregset (const struct regcache *regcache, - elf_gregset_t *gregsetp, int regno) -{ - elf_greg_t *regp = (elf_greg_t *) gregsetp; - int i; - - for (i = 0; i < NUM_GREGS; i++) - if (regno == -1 || regno == i) - regcache_raw_collect (regcache, i, regp + regmap[i]); -} - -#ifdef HAVE_PTRACE_GETREGS - -/* Fetch all general-purpose registers from process/thread TID and - store their values in GDB's register array. */ - -static void -fetch_regs (struct regcache *regcache, int tid) -{ - elf_gregset_t regs; - - if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) - { - if (errno == EIO) - { - /* The kernel we're running on doesn't support the GETREGS - request. Reset `have_ptrace_getregs'. */ - have_ptrace_getregs = 0; - return; - } - - perror_with_name (_("Couldn't get registers")); - } - - supply_gregset (regcache, (const elf_gregset_t *) ®s); -} - -/* Store all valid general-purpose registers in GDB's register array - into the process/thread specified by TID. */ - -static void -store_regs (const struct regcache *regcache, int tid, int regno) -{ - elf_gregset_t regs; - - if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) - perror_with_name (_("Couldn't get registers")); - - fill_gregset (regcache, ®s, regno); - - if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) - perror_with_name (_("Couldn't write registers")); -} - -#else - -static void fetch_regs (struct regcache *regcache, int tid) -{ -} - -static void store_regs (const struct regcache *regcache, int tid, int regno) -{ -} - -#endif - - -/* Transfering floating-point registers between GDB, inferiors and cores. */ - -/* What is the address of fpN within the floating-point register set F? */ -#define FPREG_ADDR(f, n) (&(f)->fpregs[(n) * 3]) - -/* Fill GDB's register array with the floating-point register values in - *FPREGSETP. */ - -void -supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - int regi; - - for (regi = gdbarch_fp0_regnum (gdbarch); - regi < gdbarch_fp0_regnum (gdbarch) + 8; regi++) - regcache_raw_supply (regcache, regi, - FPREG_ADDR (fpregsetp, - regi - gdbarch_fp0_regnum (gdbarch))); - regcache_raw_supply (regcache, M68K_FPC_REGNUM, &fpregsetp->fpcntl[0]); - regcache_raw_supply (regcache, M68K_FPS_REGNUM, &fpregsetp->fpcntl[1]); - regcache_raw_supply (regcache, M68K_FPI_REGNUM, &fpregsetp->fpcntl[2]); -} - -/* Fill register REGNO (if it is a floating-point register) in - *FPREGSETP with the value in GDB's register array. If REGNO is -1, - do this for all registers. */ - -void -fill_fpregset (const struct regcache *regcache, - elf_fpregset_t *fpregsetp, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - int i; - - /* Fill in the floating-point registers. */ - for (i = gdbarch_fp0_regnum (gdbarch); - i < gdbarch_fp0_regnum (gdbarch) + 8; i++) - if (regno == -1 || regno == i) - regcache_raw_collect (regcache, i, - FPREG_ADDR (fpregsetp, - i - gdbarch_fp0_regnum (gdbarch))); - - /* Fill in the floating-point control registers. */ - for (i = M68K_FPC_REGNUM; i <= M68K_FPI_REGNUM; i++) - if (regno == -1 || regno == i) - regcache_raw_collect (regcache, i, - &fpregsetp->fpcntl[i - M68K_FPC_REGNUM]); -} - -#ifdef HAVE_PTRACE_GETREGS - -/* Fetch all floating-point registers from process/thread TID and store - thier values in GDB's register array. */ - -static void -fetch_fpregs (struct regcache *regcache, int tid) -{ - elf_fpregset_t fpregs; - - if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) - perror_with_name (_("Couldn't get floating point status")); - - supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs); -} - -/* Store all valid floating-point registers in GDB's register array - into the process/thread specified by TID. */ - -static void -store_fpregs (const struct regcache *regcache, int tid, int regno) -{ - elf_fpregset_t fpregs; - - if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) - perror_with_name (_("Couldn't get floating point status")); - - fill_fpregset (regcache, &fpregs, regno); - - if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0) - perror_with_name (_("Couldn't write floating point status")); -} - -#else - -static void fetch_fpregs (struct regcache *regcache, int tid) -{ -} - -static void store_fpregs (const struct regcache *regcache, int tid, int regno) -{ -} - -#endif - -/* Transferring arbitrary registers between GDB and inferior. */ - -/* Fetch register REGNO from the child process. If REGNO is -1, do - this for all registers (including the floating point and SSE - registers). */ - -static void -m68k_linux_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - int tid; - - /* Use the old method of peeking around in `struct user' if the - GETREGS request isn't available. */ - if (! have_ptrace_getregs) - { - old_fetch_inferior_registers (regcache, regno); - return; - } - - /* GNU/Linux LWP ID's are process ID's. */ - tid = ptid_get_lwp (inferior_ptid); - if (tid == 0) - tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */ - - /* Use the PTRACE_GETFPXREGS request whenever possible, since it - transfers more registers in one system call, and we'll cache the - results. But remember that fetch_fpxregs can fail, and return - zero. */ - if (regno == -1) - { - fetch_regs (regcache, tid); - - /* The call above might reset `have_ptrace_getregs'. */ - if (! have_ptrace_getregs) - { - old_fetch_inferior_registers (regcache, -1); - return; - } - - fetch_fpregs (regcache, tid); - return; - } - - if (getregs_supplies (regno)) - { - fetch_regs (regcache, tid); - return; - } - - if (getfpregs_supplies (regno)) - { - fetch_fpregs (regcache, tid); - return; - } - - internal_error (__FILE__, __LINE__, - _("Got request for bad register number %d."), regno); -} - -/* Store register REGNO back into the child process. If REGNO is -1, - do this for all registers (including the floating point and SSE - registers). */ -static void -m68k_linux_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - int tid; - - /* Use the old method of poking around in `struct user' if the - SETREGS request isn't available. */ - if (! have_ptrace_getregs) - { - old_store_inferior_registers (regcache, regno); - return; - } - - /* GNU/Linux LWP ID's are process ID's. */ - tid = ptid_get_lwp (inferior_ptid); - if (tid == 0) - tid = ptid_get_pid (inferior_ptid); /* Not a threaded program. */ - - /* Use the PTRACE_SETFPREGS requests whenever possible, since it - transfers more registers in one system call. But remember that - store_fpregs can fail, and return zero. */ - if (regno == -1) - { - store_regs (regcache, tid, regno); - store_fpregs (regcache, tid, regno); - return; - } - - if (getregs_supplies (regno)) - { - store_regs (regcache, tid, regno); - return; - } - - if (getfpregs_supplies (regno)) - { - store_fpregs (regcache, tid, regno); - return; - } - - internal_error (__FILE__, __LINE__, - _("Got request to store bad register number %d."), regno); -} - - -/* Fetch the thread-local storage pointer for libthread_db. */ - -ps_err_e -ps_get_thread_area (struct ps_prochandle *ph, - lwpid_t lwpid, int idx, void **base) -{ - if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) < 0) - return PS_ERR; - - /* IDX is the bias from the thread pointer to the beginning of the - thread descriptor. It has to be subtracted due to implementation - quirks in libthread_db. */ - *base = (char *) *base - idx; - - return PS_OK; -} - - -void _initialize_m68k_linux_nat (void); - -void -_initialize_m68k_linux_nat (void) -{ - struct target_ops *t; - - /* Fill in the generic GNU/Linux methods. */ - t = linux_target (); - - /* Add our register access methods. */ - t->to_fetch_registers = m68k_linux_fetch_inferior_registers; - t->to_store_registers = m68k_linux_store_inferior_registers; - - /* Register the target. */ - linux_nat_add_target (t); -} diff --git a/gdb/m68klinux-tdep.c b/gdb/m68klinux-tdep.c deleted file mode 100644 index 94fb953edf0..00000000000 --- a/gdb/m68klinux-tdep.c +++ /dev/null @@ -1,435 +0,0 @@ -/* Motorola m68k target-dependent support for GNU/Linux. - - Copyright (C) 1996-2016 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 "doublest.h" -#include "floatformat.h" -#include "frame.h" -#include "target.h" -#include "gdbtypes.h" -#include "osabi.h" -#include "regcache.h" -#include "objfiles.h" -#include "symtab.h" -#include "m68k-tdep.h" -#include "trad-frame.h" -#include "frame-unwind.h" -#include "glibc-tdep.h" -#include "solib-svr4.h" -#include "auxv.h" -#include "observer.h" -#include "elf/common.h" -#include "linux-tdep.h" -#include "regset.h" - -/* Offsets (in target ints) into jmp_buf. */ - -#define M68K_LINUX_JB_ELEMENT_SIZE 4 -#define M68K_LINUX_JB_PC 7 - -/* Check whether insn1 and insn2 are parts of a signal trampoline. */ - -#define IS_SIGTRAMP(insn1, insn2) \ - (/* addaw #20,sp; moveq #119,d0; trap #0 */ \ - (insn1 == 0xdefc0014 && insn2 == 0x70774e40) \ - /* moveq #119,d0; trap #0 */ \ - || insn1 == 0x70774e40) - -#define IS_RT_SIGTRAMP(insn1, insn2) \ - (/* movel #173,d0; trap #0 */ \ - (insn1 == 0x203c0000 && insn2 == 0x00ad4e40) \ - /* moveq #82,d0; notb d0; trap #0 */ \ - || (insn1 == 0x70524600 && (insn2 >> 16) == 0x4e40)) - -/* Return non-zero if THIS_FRAME corresponds to a signal trampoline. For - the sake of m68k_linux_get_sigtramp_info we also distinguish between - non-RT and RT signal trampolines. */ - -static int -m68k_linux_pc_in_sigtramp (struct frame_info *this_frame) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[12]; - unsigned long insn0, insn1, insn2; - CORE_ADDR pc = get_frame_pc (this_frame); - - if (!safe_frame_unwind_memory (this_frame, pc - 4, buf, sizeof (buf))) - return 0; - insn1 = extract_unsigned_integer (buf + 4, 4, byte_order); - insn2 = extract_unsigned_integer (buf + 8, 4, byte_order); - if (IS_SIGTRAMP (insn1, insn2)) - return 1; - if (IS_RT_SIGTRAMP (insn1, insn2)) - return 2; - - insn0 = extract_unsigned_integer (buf, 4, byte_order); - if (IS_SIGTRAMP (insn0, insn1)) - return 1; - if (IS_RT_SIGTRAMP (insn0, insn1)) - return 2; - - insn0 = ((insn0 << 16) & 0xffffffff) | (insn1 >> 16); - insn1 = ((insn1 << 16) & 0xffffffff) | (insn2 >> 16); - if (IS_SIGTRAMP (insn0, insn1)) - return 1; - if (IS_RT_SIGTRAMP (insn0, insn1)) - return 2; - - return 0; -} - -/* From . */ -static int m68k_linux_sigcontext_reg_offset[M68K_NUM_REGS] = -{ - 2 * 4, /* %d0 */ - 3 * 4, /* %d1 */ - -1, /* %d2 */ - -1, /* %d3 */ - -1, /* %d4 */ - -1, /* %d5 */ - -1, /* %d6 */ - -1, /* %d7 */ - 4 * 4, /* %a0 */ - 5 * 4, /* %a1 */ - -1, /* %a2 */ - -1, /* %a3 */ - -1, /* %a4 */ - -1, /* %a5 */ - -1, /* %fp */ - 1 * 4, /* %sp */ - 6 * 4, /* %sr */ - 6 * 4 + 2, /* %pc */ - 8 * 4, /* %fp0 */ - 11 * 4, /* %fp1 */ - -1, /* %fp2 */ - -1, /* %fp3 */ - -1, /* %fp4 */ - -1, /* %fp5 */ - -1, /* %fp6 */ - -1, /* %fp7 */ - 14 * 4, /* %fpcr */ - 15 * 4, /* %fpsr */ - 16 * 4 /* %fpiaddr */ -}; - -static int m68k_uclinux_sigcontext_reg_offset[M68K_NUM_REGS] = -{ - 2 * 4, /* %d0 */ - 3 * 4, /* %d1 */ - -1, /* %d2 */ - -1, /* %d3 */ - -1, /* %d4 */ - -1, /* %d5 */ - -1, /* %d6 */ - -1, /* %d7 */ - 4 * 4, /* %a0 */ - 5 * 4, /* %a1 */ - -1, /* %a2 */ - -1, /* %a3 */ - -1, /* %a4 */ - 6 * 4, /* %a5 */ - -1, /* %fp */ - 1 * 4, /* %sp */ - 7 * 4, /* %sr */ - 7 * 4 + 2, /* %pc */ - -1, /* %fp0 */ - -1, /* %fp1 */ - -1, /* %fp2 */ - -1, /* %fp3 */ - -1, /* %fp4 */ - -1, /* %fp5 */ - -1, /* %fp6 */ - -1, /* %fp7 */ - -1, /* %fpcr */ - -1, /* %fpsr */ - -1 /* %fpiaddr */ -}; - -/* From . */ -static int m68k_linux_ucontext_reg_offset[M68K_NUM_REGS] = -{ - 6 * 4, /* %d0 */ - 7 * 4, /* %d1 */ - 8 * 4, /* %d2 */ - 9 * 4, /* %d3 */ - 10 * 4, /* %d4 */ - 11 * 4, /* %d5 */ - 12 * 4, /* %d6 */ - 13 * 4, /* %d7 */ - 14 * 4, /* %a0 */ - 15 * 4, /* %a1 */ - 16 * 4, /* %a2 */ - 17 * 4, /* %a3 */ - 18 * 4, /* %a4 */ - 19 * 4, /* %a5 */ - 20 * 4, /* %fp */ - 21 * 4, /* %sp */ - 23 * 4, /* %sr */ - 22 * 4, /* %pc */ - 27 * 4, /* %fp0 */ - 30 * 4, /* %fp1 */ - 33 * 4, /* %fp2 */ - 36 * 4, /* %fp3 */ - 39 * 4, /* %fp4 */ - 42 * 4, /* %fp5 */ - 45 * 4, /* %fp6 */ - 48 * 4, /* %fp7 */ - 24 * 4, /* %fpcr */ - 25 * 4, /* %fpsr */ - 26 * 4 /* %fpiaddr */ -}; - - -/* Get info about saved registers in sigtramp. */ - -struct m68k_linux_sigtramp_info -{ - /* Address of sigcontext. */ - CORE_ADDR sigcontext_addr; - - /* Offset of registers in `struct sigcontext'. */ - int *sc_reg_offset; -}; - -/* Nonzero if running on uClinux. */ -static int target_is_uclinux; - -static void -m68k_linux_inferior_created (struct target_ops *objfile, int from_tty) -{ - /* Record that we will need to re-evaluate whether we are running on a - uClinux or normal GNU/Linux target (see m68k_linux_get_sigtramp_info). */ - target_is_uclinux = -1; -} - -static struct m68k_linux_sigtramp_info -m68k_linux_get_sigtramp_info (struct frame_info *this_frame) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp; - struct m68k_linux_sigtramp_info info; - - /* Determine whether we are running on a uClinux or normal GNU/Linux - target so we can use the correct sigcontext layouts. */ - if (target_is_uclinux == -1) - target_is_uclinux = linux_is_uclinux (); - - sp = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM); - - /* Get sigcontext address, it is the third parameter on the stack. */ - info.sigcontext_addr = read_memory_unsigned_integer (sp + 8, 4, byte_order); - - if (m68k_linux_pc_in_sigtramp (this_frame) == 2) - info.sc_reg_offset = m68k_linux_ucontext_reg_offset; - else - info.sc_reg_offset = (target_is_uclinux - ? m68k_uclinux_sigcontext_reg_offset - : m68k_linux_sigcontext_reg_offset); - return info; -} - -/* Signal trampolines. */ - -static struct trad_frame_cache * -m68k_linux_sigtramp_frame_cache (struct frame_info *this_frame, - void **this_cache) -{ - struct frame_id this_id; - struct trad_frame_cache *cache; - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct m68k_linux_sigtramp_info info; - gdb_byte buf[4]; - int i; - - if (*this_cache) - return (struct trad_frame_cache *) *this_cache; - - cache = trad_frame_cache_zalloc (this_frame); - - /* FIXME: cagney/2004-05-01: This is is long standing broken code. - The frame ID's code address should be the start-address of the - signal trampoline and not the current PC within that - trampoline. */ - get_frame_register (this_frame, M68K_SP_REGNUM, buf); - /* See the end of m68k_push_dummy_call. */ - this_id = frame_id_build (extract_unsigned_integer (buf, 4, byte_order) - - 4 + 8, get_frame_pc (this_frame)); - trad_frame_set_id (cache, this_id); - - info = m68k_linux_get_sigtramp_info (this_frame); - - for (i = 0; i < M68K_NUM_REGS; i++) - if (info.sc_reg_offset[i] != -1) - trad_frame_set_reg_addr (cache, i, - info.sigcontext_addr + info.sc_reg_offset[i]); - - *this_cache = cache; - return cache; -} - -static void -m68k_linux_sigtramp_frame_this_id (struct frame_info *this_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct trad_frame_cache *cache = - m68k_linux_sigtramp_frame_cache (this_frame, this_cache); - trad_frame_get_id (cache, this_id); -} - -static struct value * -m68k_linux_sigtramp_frame_prev_register (struct frame_info *this_frame, - void **this_cache, - int regnum) -{ - /* Make sure we've initialized the cache. */ - struct trad_frame_cache *cache = - m68k_linux_sigtramp_frame_cache (this_frame, this_cache); - return trad_frame_get_register (cache, this_frame, regnum); -} - -static int -m68k_linux_sigtramp_frame_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_prologue_cache) -{ - return m68k_linux_pc_in_sigtramp (this_frame); -} - -static const struct frame_unwind m68k_linux_sigtramp_frame_unwind = -{ - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - m68k_linux_sigtramp_frame_this_id, - m68k_linux_sigtramp_frame_prev_register, - NULL, - m68k_linux_sigtramp_frame_sniffer -}; - -/* Register maps for supply/collect regset functions. */ - -static const struct regcache_map_entry m68k_linux_gregmap[] = - { - { 7, M68K_D1_REGNUM, 4 }, /* d1 ... d7 */ - { 7, M68K_A0_REGNUM, 4 }, /* a0 ... a6 */ - { 1, M68K_D0_REGNUM, 4 }, - { 1, M68K_SP_REGNUM, 4 }, - { 1, REGCACHE_MAP_SKIP, 4 }, /* orig_d0 (skip) */ - { 1, M68K_PS_REGNUM, 4 }, - { 1, M68K_PC_REGNUM, 4 }, - /* Ignore 16-bit fields 'fmtvec' and '__fill'. */ - { 0 } - }; - -#define M68K_LINUX_GREGS_SIZE (20 * 4) - -static const struct regcache_map_entry m68k_linux_fpregmap[] = - { - { 8, M68K_FP0_REGNUM, 12 }, /* fp0 ... fp7 */ - { 1, M68K_FPC_REGNUM, 4 }, - { 1, M68K_FPS_REGNUM, 4 }, - { 1, M68K_FPI_REGNUM, 4 }, - { 0 } - }; - -#define M68K_LINUX_FPREGS_SIZE (27 * 4) - -/* Register sets. */ - -static const struct regset m68k_linux_gregset = - { - m68k_linux_gregmap, - regcache_supply_regset, regcache_collect_regset - }; - -static const struct regset m68k_linux_fpregset = - { - m68k_linux_fpregmap, - regcache_supply_regset, regcache_collect_regset - }; - -/* Iterate over core file register note sections. */ - -static void -m68k_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", M68K_LINUX_GREGS_SIZE, &m68k_linux_gregset, NULL, cb_data); - cb (".reg2", M68K_LINUX_FPREGS_SIZE, &m68k_linux_fpregset, NULL, cb_data); -} - -static void -m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - linux_init_abi (info, gdbarch); - - tdep->jb_pc = M68K_LINUX_JB_PC; - tdep->jb_elt_size = M68K_LINUX_JB_ELEMENT_SIZE; - - /* GNU/Linux uses a calling convention that's similar to SVR4. It - returns integer values in %d0/%d1, pointer values in %a0 and - floating values in %fp0, just like SVR4, but uses %a1 to pass the - address to store a structure value. It also returns small - structures in registers instead of memory. */ - m68k_svr4_init_abi (info, gdbarch); - tdep->struct_value_regnum = M68K_A1_REGNUM; - tdep->struct_return = reg_struct_return; - - set_gdbarch_decr_pc_after_break (gdbarch, 2); - - frame_unwind_append_unwinder (gdbarch, &m68k_linux_sigtramp_frame_unwind); - - /* Shared library handling. */ - - /* GNU/Linux uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets (gdbarch, - svr4_ilp32_fetch_link_map_offsets); - - /* GNU/Linux uses the dynamic linker included in the GNU C Library. */ - set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); - - set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); - - /* Core file support. */ - set_gdbarch_iterate_over_regset_sections - (gdbarch, m68k_linux_iterate_over_regset_sections); - - /* Enable TLS support. */ - set_gdbarch_fetch_tls_load_module_address (gdbarch, - svr4_fetch_objfile_link_map); -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_m68k_linux_tdep; - -void -_initialize_m68k_linux_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_LINUX, - m68k_linux_init_abi); - observer_attach_inferior_created (m68k_linux_inferior_created); -} diff --git a/gdb/m88k-bsd-nat.c b/gdb/m88k-bsd-nat.c new file mode 100644 index 00000000000..16c03df1acb --- /dev/null +++ b/gdb/m88k-bsd-nat.c @@ -0,0 +1,111 @@ +/* Native-dependent code for Motorola 88000 BSD's. + + Copyright (C) 2004-2016 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 "target.h" + +#include +#include +#include + +#include "m88k-tdep.h" +#include "inf-ptrace.h" + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +m88kbsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + int regnum; + + for (regnum = 0; regnum < M88K_NUM_REGS; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +m88kbsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = 0; i < M88K_NUM_REGS; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +static void +m88kbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + m88kbsd_supply_gregset (regcache, ®s); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +static void +m88kbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + m88kbsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_m88kbsd_nat (void); + +void +_initialize_m88kbsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = m88kbsd_fetch_inferior_registers; + t->to_store_registers = m88kbsd_store_inferior_registers; + add_target (t); +} diff --git a/gdb/m88kbsd-nat.c b/gdb/m88kbsd-nat.c deleted file mode 100644 index 16c03df1acb..00000000000 --- a/gdb/m88kbsd-nat.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Native-dependent code for Motorola 88000 BSD's. - - Copyright (C) 2004-2016 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 "target.h" - -#include -#include -#include - -#include "m88k-tdep.h" -#include "inf-ptrace.h" - -/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ - -static void -m88kbsd_supply_gregset (struct regcache *regcache, const void *gregs) -{ - const char *regs = gregs; - int regnum; - - for (regnum = 0; regnum < M88K_NUM_REGS; regnum++) - regcache_raw_supply (regcache, regnum, regs + regnum * 4); -} - -/* Collect the general-purpose registers from REGCACHE and store them - in GREGS. */ - -static void -m88kbsd_collect_gregset (const struct regcache *regcache, - void *gregs, int regnum) -{ - char *regs = gregs; - int i; - - for (i = 0; i < M88K_NUM_REGS; i++) - { - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, regs + i * 4); - } -} - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers. */ - -static void -m88kbsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - m88kbsd_supply_gregset (regcache, ®s); -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers. */ - -static void -m88kbsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - m88kbsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_m88kbsd_nat (void); - -void -_initialize_m88kbsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = m88kbsd_fetch_inferior_registers; - t->to_store_registers = m88kbsd_store_inferior_registers; - add_target (t); -} diff --git a/gdb/mips-nbsd-nat.c b/gdb/mips-nbsd-nat.c new file mode 100644 index 00000000000..ebbe84ed85b --- /dev/null +++ b/gdb/mips-nbsd-nat.c @@ -0,0 +1,125 @@ +/* Native-dependent code for MIPS systems running NetBSD. + + Copyright (C) 2000-2016 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 "target.h" + +#include +#include +#include + +#include "mips-tdep.h" +#include "mips-nbsd-tdep.h" +#include "inf-ptrace.h" + +/* 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)); +} + +static void +mipsnbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + if (regno == -1 || getregs_supplies (gdbarch, regno)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (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 (get_regcache_arch (regcache))) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + mipsnbsd_supply_fpreg (regcache, (char *) &fpregs, regno); + } +} + +static void +mipsnbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + if (regno == -1 || getregs_supplies (gdbarch, regno)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + mipsnbsd_fill_reg (regcache, (char *) ®s, regno); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + + if (regno != -1) + return; + } + + if (regno == -1 + || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (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, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_mipsnbsd_nat (void); + +void +_initialize_mipsnbsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = mipsnbsd_fetch_inferior_registers; + t->to_store_registers = mipsnbsd_store_inferior_registers; + add_target (t); +} diff --git a/gdb/mips-nbsd-tdep.c b/gdb/mips-nbsd-tdep.c new file mode 100644 index 00000000000..2d7cd821f3e --- /dev/null +++ b/gdb/mips-nbsd-tdep.c @@ -0,0 +1,385 @@ +/* Target-dependent code for NetBSD/mips. + + Copyright (C) 2002-2016 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 (get_regcache_arch (regcache)); + 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 (regcache, 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 (get_regcache_arch (regcache)); + 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 (regcache, 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_gregset, + NULL, cb_data); + cb (".reg2", 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 = get_regcache_arch (regcache); + 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 (regcache, i, NULL); + else + regcache_raw_supply (regcache, i, + regs + (i * mips_isa_regsize (gdbarch))); + } + } +} + +void +mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + 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 (regcache, i, + regs + (i * mips_isa_regsize (gdbarch))); +} + +void +mipsnbsd_supply_fpreg (struct regcache *regcache, + const char *fpregs, int regno) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + 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 (regcache, i, NULL); + else + regcache_raw_supply (regcache, 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 = get_regcache_arch (regcache); + 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 (regcache, 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) +{ + 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)); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_mipsnbsd_tdep; + +void +_initialize_mipsnbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF, + mipsnbsd_init_abi); +} diff --git a/gdb/mips-nbsd-tdep.h b/gdb/mips-nbsd-tdep.h new file mode 100644 index 00000000000..caec0e1b019 --- /dev/null +++ b/gdb/mips-nbsd-tdep.h @@ -0,0 +1,29 @@ +/* Common target dependent code for GDB on MIPS systems running NetBSD. + + Copyright (C) 2002-2016 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/mips64-obsd-nat.c b/gdb/mips64-obsd-nat.c new file mode 100644 index 00000000000..48464642363 --- /dev/null +++ b/gdb/mips64-obsd-nat.c @@ -0,0 +1,126 @@ +/* Native-dependent code for OpenBSD/mips64. + + Copyright (C) 2004-2016 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 "target.h" + +#include +#include +#include + +#include "mips-tdep.h" +#include "inf-ptrace.h" +#include "obsd-nat.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 + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +mips64obsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const char *regs = gregs; + int regnum; + + for (regnum = MIPS_ZERO_REGNUM; regnum <= MIPS_PC_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 8); + + for (regnum = MIPS_FP0_REGNUM; regnum <= MIPS_FSR_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, regs + (regnum + 2) * 8); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +mips64obsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + char *regs = gregs; + int i; + + for (i = MIPS_ZERO_REGNUM; i <= MIPS_PC_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 8); + } + + for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + (i + 2) * 8); + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +static void +mips64obsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + mips64obsd_supply_gregset (regcache, ®s); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +static void +mips64obsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + mips64obsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_mips64obsd_nat (void); + +void +_initialize_mips64obsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = mips64obsd_fetch_inferior_registers; + t->to_store_registers = mips64obsd_store_inferior_registers; + obsd_add_target (t); +} diff --git a/gdb/mips64-obsd-tdep.c b/gdb/mips64-obsd-tdep.c new file mode 100644 index 00000000000..df8ec0f8dd8 --- /dev/null +++ b/gdb/mips64-obsd-tdep.c @@ -0,0 +1,170 @@ +/* Target-dependent code for OpenBSD/mips64. + + Copyright (C) 2004-2016 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 "gdbtypes.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "trad-frame.h" +#include "tramp-frame.h" + +#include "obsd-tdep.h" +#include "mips-tdep.h" +#include "solib-svr4.h" + +/* The MIPS64 Floating-Point Quad-Precision format is similar to + big-endian IA-64 Quad-Precision format. */ +#define floatformats_mips64_quad floatformats_ia64_quad + +#define MIPS64OBSD_NUM_REGS 73 + +/* Core file support. */ + +/* 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 +mips64obsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t len) +{ + const char *regs = (const char *) gregs; + int i; + + for (i = 0; i < MIPS64OBSD_NUM_REGS; i++) + { + if (regnum == i || regnum == -1) + regcache_raw_supply (regcache, i, regs + i * 8); + } +} + +/* OpenBSD/mips64 register set. */ + +static const struct regset mips64obsd_gregset = +{ + NULL, + mips64obsd_supply_gregset +}; + +/* Iterate over core file register note sections. */ + +static void +mips64obsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", MIPS64OBSD_NUM_REGS * 8, &mips64obsd_gregset, NULL, cb_data); +} + + +/* Signal trampolines. */ + +static void +mips64obsd_sigframe_init (const struct tramp_frame *self, + struct frame_info *this_frame, + struct trad_frame_cache *cache, + CORE_ADDR func) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + CORE_ADDR sp, sigcontext_addr, addr; + int regnum; + + /* We find the appropriate instance of `struct sigcontext' at a + fixed offset in the signal frame. */ + sp = get_frame_register_signed (this_frame, + MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch)); + sigcontext_addr = sp + 32; + + /* PC. */ + regnum = mips_regnum (gdbarch)->pc; + trad_frame_set_reg_addr (cache, + regnum + gdbarch_num_regs (gdbarch), + sigcontext_addr + 16); + + /* GPRs. */ + for (regnum = MIPS_AT_REGNUM, addr = sigcontext_addr + 32; + regnum <= MIPS_RA_REGNUM; regnum++, addr += 8) + trad_frame_set_reg_addr (cache, + regnum + gdbarch_num_regs (gdbarch), + addr); + + /* HI and LO. */ + regnum = mips_regnum (gdbarch)->lo; + trad_frame_set_reg_addr (cache, + regnum + gdbarch_num_regs (gdbarch), + sigcontext_addr + 280); + regnum = mips_regnum (gdbarch)->hi; + trad_frame_set_reg_addr (cache, + regnum + gdbarch_num_regs (gdbarch), + sigcontext_addr + 288); + + /* TODO: Handle the floating-point registers. */ + + trad_frame_set_id (cache, frame_id_build (sp, func)); +} + +static const struct tramp_frame mips64obsd_sigframe = +{ + SIGTRAMP_FRAME, + MIPS_INSN32_SIZE, + { + { 0x67a40020, -1 }, /* daddiu a0,sp,32 */ + { 0x24020067, -1 }, /* li v0,103 */ + { 0x0000000c, -1 }, /* syscall */ + { 0x0000000d, -1 }, /* break */ + { TRAMP_SENTINEL_INSN, -1 } + }, + mips64obsd_sigframe_init +}; + + +static void +mips64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* OpenBSD/mips64 only supports the n64 ABI, but the braindamaged + way GDB works, forces us to pretend we can handle them all. */ + + set_gdbarch_iterate_over_regset_sections + (gdbarch, mips64obsd_iterate_over_regset_sections); + + tramp_frame_prepend_unwinder (gdbarch, &mips64obsd_sigframe); + + set_gdbarch_long_double_bit (gdbarch, 128); + set_gdbarch_long_double_format (gdbarch, floatformats_mips64_quad); + + obsd_init_abi(info, gdbarch); + + /* OpenBSD/mips64 has SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_mips64obsd_tdep (void); + +void +_initialize_mips64obsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_OPENBSD_ELF, + mips64obsd_init_abi); +} diff --git a/gdb/mips64obsd-nat.c b/gdb/mips64obsd-nat.c deleted file mode 100644 index 48464642363..00000000000 --- a/gdb/mips64obsd-nat.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Native-dependent code for OpenBSD/mips64. - - Copyright (C) 2004-2016 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 "target.h" - -#include -#include -#include - -#include "mips-tdep.h" -#include "inf-ptrace.h" -#include "obsd-nat.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 - -/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ - -static void -mips64obsd_supply_gregset (struct regcache *regcache, const void *gregs) -{ - const char *regs = gregs; - int regnum; - - for (regnum = MIPS_ZERO_REGNUM; regnum <= MIPS_PC_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, regs + regnum * 8); - - for (regnum = MIPS_FP0_REGNUM; regnum <= MIPS_FSR_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, regs + (regnum + 2) * 8); -} - -/* Collect the general-purpose registers from REGCACHE and store them - in GREGS. */ - -static void -mips64obsd_collect_gregset (const struct regcache *regcache, - void *gregs, int regnum) -{ - char *regs = gregs; - int i; - - for (i = MIPS_ZERO_REGNUM; i <= MIPS_PC_REGNUM; i++) - { - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, regs + i * 8); - } - - for (i = MIPS_FP0_REGNUM; i <= MIPS_FSR_REGNUM; i++) - { - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, regs + (i + 2) * 8); - } -} - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers. */ - -static void -mips64obsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - mips64obsd_supply_gregset (regcache, ®s); -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers. */ - -static void -mips64obsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - mips64obsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_mips64obsd_nat (void); - -void -_initialize_mips64obsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = mips64obsd_fetch_inferior_registers; - t->to_store_registers = mips64obsd_store_inferior_registers; - obsd_add_target (t); -} diff --git a/gdb/mips64obsd-tdep.c b/gdb/mips64obsd-tdep.c deleted file mode 100644 index df8ec0f8dd8..00000000000 --- a/gdb/mips64obsd-tdep.c +++ /dev/null @@ -1,170 +0,0 @@ -/* Target-dependent code for OpenBSD/mips64. - - Copyright (C) 2004-2016 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 "gdbtypes.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "trad-frame.h" -#include "tramp-frame.h" - -#include "obsd-tdep.h" -#include "mips-tdep.h" -#include "solib-svr4.h" - -/* The MIPS64 Floating-Point Quad-Precision format is similar to - big-endian IA-64 Quad-Precision format. */ -#define floatformats_mips64_quad floatformats_ia64_quad - -#define MIPS64OBSD_NUM_REGS 73 - -/* Core file support. */ - -/* 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 -mips64obsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *gregs, size_t len) -{ - const char *regs = (const char *) gregs; - int i; - - for (i = 0; i < MIPS64OBSD_NUM_REGS; i++) - { - if (regnum == i || regnum == -1) - regcache_raw_supply (regcache, i, regs + i * 8); - } -} - -/* OpenBSD/mips64 register set. */ - -static const struct regset mips64obsd_gregset = -{ - NULL, - mips64obsd_supply_gregset -}; - -/* Iterate over core file register note sections. */ - -static void -mips64obsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", MIPS64OBSD_NUM_REGS * 8, &mips64obsd_gregset, NULL, cb_data); -} - - -/* Signal trampolines. */ - -static void -mips64obsd_sigframe_init (const struct tramp_frame *self, - struct frame_info *this_frame, - struct trad_frame_cache *cache, - CORE_ADDR func) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - CORE_ADDR sp, sigcontext_addr, addr; - int regnum; - - /* We find the appropriate instance of `struct sigcontext' at a - fixed offset in the signal frame. */ - sp = get_frame_register_signed (this_frame, - MIPS_SP_REGNUM + gdbarch_num_regs (gdbarch)); - sigcontext_addr = sp + 32; - - /* PC. */ - regnum = mips_regnum (gdbarch)->pc; - trad_frame_set_reg_addr (cache, - regnum + gdbarch_num_regs (gdbarch), - sigcontext_addr + 16); - - /* GPRs. */ - for (regnum = MIPS_AT_REGNUM, addr = sigcontext_addr + 32; - regnum <= MIPS_RA_REGNUM; regnum++, addr += 8) - trad_frame_set_reg_addr (cache, - regnum + gdbarch_num_regs (gdbarch), - addr); - - /* HI and LO. */ - regnum = mips_regnum (gdbarch)->lo; - trad_frame_set_reg_addr (cache, - regnum + gdbarch_num_regs (gdbarch), - sigcontext_addr + 280); - regnum = mips_regnum (gdbarch)->hi; - trad_frame_set_reg_addr (cache, - regnum + gdbarch_num_regs (gdbarch), - sigcontext_addr + 288); - - /* TODO: Handle the floating-point registers. */ - - trad_frame_set_id (cache, frame_id_build (sp, func)); -} - -static const struct tramp_frame mips64obsd_sigframe = -{ - SIGTRAMP_FRAME, - MIPS_INSN32_SIZE, - { - { 0x67a40020, -1 }, /* daddiu a0,sp,32 */ - { 0x24020067, -1 }, /* li v0,103 */ - { 0x0000000c, -1 }, /* syscall */ - { 0x0000000d, -1 }, /* break */ - { TRAMP_SENTINEL_INSN, -1 } - }, - mips64obsd_sigframe_init -}; - - -static void -mips64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* OpenBSD/mips64 only supports the n64 ABI, but the braindamaged - way GDB works, forces us to pretend we can handle them all. */ - - set_gdbarch_iterate_over_regset_sections - (gdbarch, mips64obsd_iterate_over_regset_sections); - - tramp_frame_prepend_unwinder (gdbarch, &mips64obsd_sigframe); - - set_gdbarch_long_double_bit (gdbarch, 128); - set_gdbarch_long_double_format (gdbarch, floatformats_mips64_quad); - - obsd_init_abi(info, gdbarch); - - /* OpenBSD/mips64 has SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_mips64obsd_tdep (void); - -void -_initialize_mips64obsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_OPENBSD_ELF, - mips64obsd_init_abi); -} diff --git a/gdb/mipsnbsd-nat.c b/gdb/mipsnbsd-nat.c deleted file mode 100644 index fc71592e5c5..00000000000 --- a/gdb/mipsnbsd-nat.c +++ /dev/null @@ -1,125 +0,0 @@ -/* Native-dependent code for MIPS systems running NetBSD. - - Copyright (C) 2000-2016 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 "target.h" - -#include -#include -#include - -#include "mips-tdep.h" -#include "mipsnbsd-tdep.h" -#include "inf-ptrace.h" - -/* 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)); -} - -static void -mipsnbsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - if (regno == -1 || getregs_supplies (gdbarch, regno)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (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 (get_regcache_arch (regcache))) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - mipsnbsd_supply_fpreg (regcache, (char *) &fpregs, regno); - } -} - -static void -mipsnbsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - if (regno == -1 || getregs_supplies (gdbarch, regno)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - mipsnbsd_fill_reg (regcache, (char *) ®s, regno); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - - if (regno != -1) - return; - } - - if (regno == -1 - || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (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, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_mipsnbsd_nat (void); - -void -_initialize_mipsnbsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = mipsnbsd_fetch_inferior_registers; - t->to_store_registers = mipsnbsd_store_inferior_registers; - add_target (t); -} diff --git a/gdb/mipsnbsd-tdep.c b/gdb/mipsnbsd-tdep.c deleted file mode 100644 index 48349957fc6..00000000000 --- a/gdb/mipsnbsd-tdep.c +++ /dev/null @@ -1,385 +0,0 @@ -/* Target-dependent code for NetBSD/mips. - - Copyright (C) 2002-2016 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 "mipsnbsd-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 (get_regcache_arch (regcache)); - 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 (regcache, 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 (get_regcache_arch (regcache)); - 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 (regcache, 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_gregset, - NULL, cb_data); - cb (".reg2", 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 = get_regcache_arch (regcache); - 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 (regcache, i, NULL); - else - regcache_raw_supply (regcache, i, - regs + (i * mips_isa_regsize (gdbarch))); - } - } -} - -void -mipsnbsd_fill_reg (const struct regcache *regcache, char *regs, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - 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 (regcache, i, - regs + (i * mips_isa_regsize (gdbarch))); -} - -void -mipsnbsd_supply_fpreg (struct regcache *regcache, - const char *fpregs, int regno) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - 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 (regcache, i, NULL); - else - regcache_raw_supply (regcache, 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 = get_regcache_arch (regcache); - 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 (regcache, 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) -{ - 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)); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_mipsnbsd_tdep; - -void -_initialize_mipsnbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_NETBSD_ELF, - mipsnbsd_init_abi); -} diff --git a/gdb/mipsnbsd-tdep.h b/gdb/mipsnbsd-tdep.h deleted file mode 100644 index 26f801ca46b..00000000000 --- a/gdb/mipsnbsd-tdep.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Common target dependent code for GDB on MIPS systems running NetBSD. - - Copyright (C) 2002-2016 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 MIPSNBSD_TDEP_H -#define MIPSNBSD_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 /* MIPSNBSD_TDEP_H */ diff --git a/gdb/ppc-fbsd-nat.c b/gdb/ppc-fbsd-nat.c new file mode 100644 index 00000000000..6eed99869ff --- /dev/null +++ b/gdb/ppc-fbsd-nat.c @@ -0,0 +1,219 @@ +/* Native-dependent code for PowerPC's running FreeBSD, for GDB. + + Copyright (C) 2013-2016 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 "inferior.h" +#include "regcache.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "fbsd-nat.h" +#include "gregset.h" +#include "ppc-tdep.h" +#include "ppc-fbsd-tdep.h" +#include "inf-ptrace.h" +#include "bsd-kvm.h" + +/* Fill GDB's register array with the general-purpose register values + in *GREGSETP. */ + +void +supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) +{ + const struct regset *regset = ppc_fbsd_gregset (sizeof (long)); + + ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp)); +} + +/* Fill register REGNO (if a gpr) in *GREGSETP with the value in GDB's + register array. If REGNO is -1 do it for all registers. */ + +void +fill_gregset (const struct regcache *regcache, + gdb_gregset_t *gregsetp, int regno) +{ + const struct regset *regset = ppc_fbsd_gregset (sizeof (long)); + + if (regno == -1) + memset (gregsetp, 0, sizeof (*gregsetp)); + ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp)); +} + +/* Fill GDB's register array with the floating-point register values + in *FPREGSETP. */ + +void +supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp) +{ + const struct regset *regset = ppc_fbsd_fpregset (); + + ppc_supply_fpregset (regset, regcache, -1, + fpregsetp, sizeof (*fpregsetp)); +} + +/* Fill register REGNO in *FGREGSETP with the value in GDB's + register array. If REGNO is -1 do it for all registers. */ + +void +fill_fpregset (const struct regcache *regcache, + gdb_fpregset_t *fpregsetp, int regno) +{ + const struct regset *regset = ppc_fbsd_fpregset (); + + ppc_collect_fpregset (regset, regcache, regno, + fpregsetp, sizeof (*fpregsetp)); +} + +/* Returns true if PT_GETFPREGS fetches this register. */ + +static int +getfpregs_supplies (struct gdbarch *gdbarch, int regno) +{ + 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 ((regno >= tdep->ppc_fp0_regnum + && regno < tdep->ppc_fp0_regnum + ppc_num_fprs) + || regno == tdep->ppc_fpscr_regnum); +} + +/* Fetch register REGNO from the child process. If REGNO is -1, do it + for all registers. */ + +static void +ppcfbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + gdb_gregset_t regs; + + if (ptrace (PT_GETREGS, ptid_get_lwp (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + supply_gregset (regcache, ®s); + + if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno)) + { + const struct regset *fpregset = ppc_fbsd_fpregset (); + gdb_fpregset_t fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_lwp (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get FP registers")); + + ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof fpregs); + } +} + +/* Store register REGNO back into the child process. If REGNO is -1, + do this for all registers. */ + +static void +ppcfbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + gdb_gregset_t regs; + + if (ptrace (PT_GETREGS, ptid_get_lwp (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + fill_gregset (regcache, ®s, regno); + + if (ptrace (PT_SETREGS, ptid_get_lwp (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + + if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno)) + { + gdb_fpregset_t fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_lwp (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get FP registers")); + + fill_fpregset (regcache, &fpregs, regno); + + if (ptrace (PT_SETFPREGS, ptid_get_lwp (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't set FP registers")); + } +} + +/* Architecture specific function that reconstructs the + register state from PCB (Process Control Block) and supplies it + to REGCACHE. */ + +static int +ppcfbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int i, regnum; + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_sp == 0) + return 0; + + regcache_raw_supply (regcache, gdbarch_sp_regnum (gdbarch), &pcb->pcb_sp); + regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &pcb->pcb_cr); + regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &pcb->pcb_lr); + for (i = 0, regnum = tdep->ppc_gp0_regnum + 14; i < 20; i++, regnum++) + regcache_raw_supply (regcache, regnum, &pcb->pcb_context[i]); + + return 1; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ + +void _initialize_ppcfbsd_nat (void); + +void +_initialize_ppcfbsd_nat (void) +{ + struct target_ops *t; + + /* Add in local overrides. */ + t = inf_ptrace_target (); + t->to_fetch_registers = ppcfbsd_fetch_inferior_registers; + t->to_store_registers = ppcfbsd_store_inferior_registers; + fbsd_nat_add_target (t); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (ppcfbsd_supply_pcb); +} diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c new file mode 100644 index 00000000000..0e5ead6d3f8 --- /dev/null +++ b/gdb/ppc-fbsd-tdep.c @@ -0,0 +1,353 @@ +/* Target-dependent code for PowerPC systems running FreeBSD. + + Copyright (C) 2013-2016 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 "frame-unwind.h" +#include "gdbtypes.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "symtab.h" +#include "target.h" +#include "trad-frame.h" + +#include "ppc-tdep.h" +#include "ppc64-tdep.h" +#include "ppc-fbsd-tdep.h" +#include "fbsd-tdep.h" +#include "solib-svr4.h" + + +/* 32-bit regset descriptions. */ + +static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 4, + /* .xr_size = */ 4, + /* .pc_offset = */ 144, + /* .ps_offset = */ -1, + /* .cr_offset = */ 132, + /* .lr_offset = */ 128, + /* .ctr_offset = */ 140, + /* .xer_offset = */ 136, + /* .mq_offset = */ -1, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256, + /* .fpscr_size = */ 8, +#ifdef NOTYET + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vscr_offset = */ 512 + 12, + /* .vrsave_offset = */ 512 +#endif + }; + +/* 64-bit regset descriptions. */ + +static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets = + { + /* General-purpose registers. */ + /* .r0_offset = */ 0, + /* .gpr_size = */ 8, + /* .xr_size = */ 8, + /* .pc_offset = */ 288, + /* .ps_offset = */ -1, + /* .cr_offset = */ 264, + /* .lr_offset = */ 256, + /* .ctr_offset = */ 280, + /* .xer_offset = */ 272, + /* .mq_offset = */ -1, + + /* Floating-point registers. */ + /* .f0_offset = */ 0, + /* .fpscr_offset = */ 256, + /* .fpscr_size = */ 8, +#ifdef NOYET + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vscr_offset = */ 512 + 12, + /* .vrsave_offset = */ 528 +#endif + }; + +/* 32-bit general-purpose register set. */ + +static const struct regset ppc32_fbsd_gregset = { + &ppc32_fbsd_reg_offsets, + ppc_supply_gregset, + ppc_collect_gregset +}; + +/* 64-bit general-purpose register set. */ + +static const struct regset ppc64_fbsd_gregset = { + &ppc64_fbsd_reg_offsets, + ppc_supply_gregset, + ppc_collect_gregset +}; + +/* 32-/64-bit floating-point register set. */ + +static const struct regset ppc32_fbsd_fpregset = { + &ppc32_fbsd_reg_offsets, + ppc_supply_fpregset, + ppc_collect_fpregset +}; + +const struct regset * +ppc_fbsd_gregset (int wordsize) +{ + return wordsize == 8 ? &ppc64_fbsd_gregset : &ppc32_fbsd_gregset; +} + +const struct regset * +ppc_fbsd_fpregset (void) +{ + return &ppc32_fbsd_fpregset; +} + +/* Iterate over core file register note sections. */ + +static void +ppcfbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (tdep->wordsize == 4) + cb (".reg", 148, &ppc32_fbsd_gregset, NULL, cb_data); + else + cb (".reg", 296, &ppc64_fbsd_gregset, NULL, cb_data); + cb (".reg2", 264, &ppc32_fbsd_fpregset, NULL, cb_data); +} + +/* Default page size. */ + +static const int ppcfbsd_page_size = 4096; + +/* Offset for sigreturn(2). */ + +static const int ppcfbsd_sigreturn_offset[] = { + 0xc, /* FreeBSD 32-bit */ + -1 +}; + +/* Signal trampolines. */ + +static int +ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR pc = get_frame_pc (this_frame); + CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1)); + const int *offset; + const char *name; + + /* A stack trampoline is detected if no name is associated + to the current pc and if it points inside a trampoline + sequence. */ + + find_pc_partial_function (pc, &name, NULL, NULL); + + /* If we have a name, we have no trampoline, return. */ + if (name) + return 0; + + for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++) + { + gdb_byte buf[2 * PPC_INSN_SIZE]; + unsigned long insn; + + if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, + buf, sizeof buf)) + continue; + + /* Check for "li r0,SYS_sigreturn". */ + insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); + if (insn != 0x380001a1) + continue; + + /* Check for "sc". */ + insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, + PPC_INSN_SIZE, byte_order); + if (insn != 0x44000002) + continue; + + return 1; + } + + return 0; +} + +static struct trad_frame_cache * +ppcfbsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct trad_frame_cache *cache; + CORE_ADDR addr, base, func; + gdb_byte buf[PPC_INSN_SIZE]; + int i; + + if (*this_cache) + return (struct trad_frame_cache *) *this_cache; + + cache = trad_frame_cache_zalloc (this_frame); + *this_cache = cache; + + func = get_frame_pc (this_frame); + func &= ~(ppcfbsd_page_size - 1); + if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf)) + return cache; + + base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); + addr = base + 0x10 + 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 (cache, regnum, addr); + } + trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr); + /* SRR0? */ + addr += tdep->wordsize; + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (cache, frame_id_build (base, func)); + + return cache; +} + +static void +ppcfbsd_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + struct trad_frame_cache *cache = + ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); + + trad_frame_get_id (cache, this_id); +} + +static struct value * +ppcfbsd_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct trad_frame_cache *cache = + ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); + + return trad_frame_get_register (cache, this_frame, regnum); +} + +static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + ppcfbsd_sigtramp_frame_this_id, + ppcfbsd_sigtramp_frame_prev_register, + NULL, + ppcfbsd_sigtramp_frame_sniffer +}; + +static enum return_value_convention +ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ + return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, + regcache, readbuf, writebuf); +} + + +static void +ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Generic FreeBSD support. */ + fbsd_init_abi (info, gdbarch); + + /* FreeBSD 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); + + if (tdep->wordsize == 4) + { + set_gdbarch_return_value (gdbarch, ppcfbsd_return_value); + + set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); + set_solib_svr4_fetch_link_map_offsets (gdbarch, + svr4_ilp32_fetch_link_map_offsets); + + frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind); + set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc"); + } + + if (tdep->wordsize == 8) + { + set_gdbarch_convert_from_func_ptr_addr + (gdbarch, ppc64_convert_from_func_ptr_addr); + set_gdbarch_elf_make_msymbol_special (gdbarch, + ppc64_elf_make_msymbol_special); + + set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); + set_solib_svr4_fetch_link_map_offsets (gdbarch, + svr4_lp64_fetch_link_map_offsets); + set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); + } + + set_gdbarch_iterate_over_regset_sections + (gdbarch, ppcfbsd_iterate_over_regset_sections); + + set_gdbarch_fetch_tls_load_module_address (gdbarch, + svr4_fetch_objfile_link_map); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ + +void _initialize_ppcfbsd_tdep (void); + +void +_initialize_ppcfbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_FREEBSD_ELF, + ppcfbsd_init_abi); + gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64, + GDB_OSABI_FREEBSD_ELF, + ppcfbsd_init_abi); + gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD_ELF, + ppcfbsd_init_abi); +} diff --git a/gdb/ppc-fbsd-tdep.h b/gdb/ppc-fbsd-tdep.h new file mode 100644 index 00000000000..9e1468bc972 --- /dev/null +++ b/gdb/ppc-fbsd-tdep.h @@ -0,0 +1,29 @@ +/* Target-dependent code for GDB on PowerPC systems running FreeBSD. + + Copyright (C) 2013-2016 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_FBSD_TDEP_H +#define PPC_FBSD_TDEP_H + +struct regset; + +/* From ppc-fbsd-tdep.c ... */ +const struct regset *ppc_fbsd_gregset (int); +const struct regset *ppc_fbsd_fpregset (void); + +#endif /* PPC_FBSD_TDEP_H */ diff --git a/gdb/ppc-nbsd-nat.c b/gdb/ppc-nbsd-nat.c new file mode 100644 index 00000000000..5b1d141c13d --- /dev/null +++ b/gdb/ppc-nbsd-nat.c @@ -0,0 +1,197 @@ +/* Native-dependent code for NetBSD/powerpc. + + Copyright (C) 2002-2016 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 +#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" + +/* 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); +} + +static void +ppcnbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -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, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get FP registers")); + + ppc_supply_fpregset (&ppcnbsd_fpregset, regcache, + regnum, &fpregs, sizeof fpregs); + } +} + +static void +ppcnbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + + if (regnum == -1 || getregs_supplies (gdbarch, regnum)) + { + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + ppc_collect_gregset (&ppcnbsd_gregset, regcache, + regnum, ®s, sizeof regs); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + } + + if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get FP registers")); + + ppc_collect_fpregset (&ppcnbsd_fpregset, regcache, + regnum, &fpregs, sizeof fpregs); + + if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -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 = get_regcache_arch (regcache); + 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 (regcache, tdep->ppc_cr_regnum, &sf.cr); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2); + for (i = 0 ; i < 19 ; i++) + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 13 + i, + &sf.fixreg[i]); + + read_memory(sf.sp, (gdb_byte *)&cf, sizeof(cf)); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 1, &cf.sp); + + read_memory(cf.sp, (gdb_byte *)&cf, sizeof(cf)); + regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &cf.lr); + regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &cf.lr); + + return 1; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_ppcnbsd_nat (void); + +void +_initialize_ppcnbsd_nat (void) +{ + struct target_ops *t; + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (ppcnbsd_supply_pcb); + + /* Add in local overrides. */ + t = inf_ptrace_target (); + t->to_fetch_registers = ppcnbsd_fetch_inferior_registers; + t->to_store_registers = ppcnbsd_store_inferior_registers; + add_target (t); +} diff --git a/gdb/ppc-nbsd-tdep.c b/gdb/ppc-nbsd-tdep.c new file mode 100644 index 00000000000..a730ebdf6e6 --- /dev/null +++ b/gdb/ppc-nbsd-tdep.c @@ -0,0 +1,227 @@ +/* Target-dependent code for NetBSD/powerpc. + + Copyright (C) 2002-2016 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 "ppc-nbsd-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, &ppcnbsd_gregset, NULL, cb_data); + cb (".reg2", 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 ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION) + && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8) + && TYPE_VECTOR (valtype)) + && !(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, -1 }, /* add r1,r1,-16 */ + { 0x4e800021, -1 }, /* blrl */ + { 0x38610018, -1 }, /* addi r3,r1,24 */ + { 0x38000127, -1 }, /* li r0,295 */ + { 0x44000002, -1 }, /* sc */ + { 0x38000001, -1 }, /* li r0,1 */ + { 0x44000002, -1 }, /* sc */ + { TRAMP_SENTINEL_INSN, -1 } + }, + ppcnbsd_sigtramp_cache_init +}; + +/* NetBSD 2.0 introduced a slightly different signal trampoline. */ + +const struct tramp_frame ppcnbsd2_sigtramp = +{ + SIGTRAMP_FRAME, + 4, + { + { 0x3821fff0, -1 }, /* add r1,r1,-16 */ + { 0x4e800021, -1 }, /* blrl */ + { 0x38610010, -1 }, /* addi r3,r1,16 */ + { 0x38000127, -1 }, /* li r0,295 */ + { 0x44000002, -1 }, /* sc */ + { 0x38000001, -1 }, /* li r0,1 */ + { 0x44000002, -1 }, /* sc */ + { TRAMP_SENTINEL_INSN, -1 } + }, + ppcnbsd_sigtramp_cache_init +}; + + +static void +ppcnbsd_init_abi (struct gdbarch_info info, + struct gdbarch *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); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_ppcnbsd_tdep (void); + +void +_initialize_ppcnbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD_ELF, + 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; + + /* AltiVec registers. */ + ppcnbsd_reg_offsets.vr0_offset = 0; + ppcnbsd_reg_offsets.vrsave_offset = 512; + ppcnbsd_reg_offsets.vscr_offset = 524; + } +} diff --git a/gdb/ppc-nbsd-tdep.h b/gdb/ppc-nbsd-tdep.h new file mode 100644 index 00000000000..1e1f291f9eb --- /dev/null +++ b/gdb/ppc-nbsd-tdep.h @@ -0,0 +1,32 @@ +/* Target-dependent code for NetBSD/powerpc. + + Copyright (C) 2004-2016 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-obsd-nat.c b/gdb/ppc-obsd-nat.c new file mode 100644 index 00000000000..eb39e7ce26d --- /dev/null +++ b/gdb/ppc-obsd-nat.c @@ -0,0 +1,231 @@ +/* Native-dependent code for OpenBSD/powerpc. + + Copyright (C) 2004-2016 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 "inferior.h" +#include "regcache.h" + +#include +#include +#include +#include +#include +#include + +#include "ppc-tdep.h" +#include "ppc-obsd-tdep.h" +#include "inf-ptrace.h" +#include "obsd-nat.h" +#include "bsd-kvm.h" + +/* OpenBSD/powerpc didn't have PT_GETFPREGS/PT_SETFPREGS until release + 4.0. On older releases the floating-point registers are handled by + PT_GETREGS/PT_SETREGS, but fpscr wasn't available.. */ + +#ifdef PT_GETFPREGS + +/* Returns true if PT_GETFPREGS fetches this register. */ + +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); +} + +#endif /* PT_GETFPREGS */ + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +static void +ppcobsd_fetch_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + ppc_supply_gregset (&ppcobsd_gregset, regcache, -1, + ®s, sizeof regs); +#ifndef PT_GETFPREGS + ppc_supply_fpregset (&ppcobsd_gregset, regcache, -1, + ®s, sizeof regs); +#endif + +#ifdef PT_GETFPREGS + if (regnum == -1 + || getfpregs_supplies (get_regcache_arch (regcache), regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + ppc_supply_fpregset (&ppcobsd_fpregset, regcache, -1, + &fpregs, sizeof fpregs); + } +#endif +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +static void +ppcobsd_store_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + ppc_collect_gregset (&ppcobsd_gregset, regcache, + regnum, ®s, sizeof regs); +#ifndef PT_GETFPREGS + ppc_collect_fpregset (&ppcobsd_gregset, regcache, + regnum, ®s, sizeof regs); +#endif + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); + +#ifdef PT_GETFPREGS + if (regnum == -1 + || getfpregs_supplies (get_regcache_arch (regcache), regnum)) + { + struct fpreg fpregs; + + if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't get floating point status")); + + ppc_collect_fpregset (&ppcobsd_fpregset, regcache, + regnum, &fpregs, sizeof fpregs); + + if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) + perror_with_name (_("Couldn't write floating point status")); + } +#endif +} + + +static int +ppcobsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct switchframe sf; + struct callframe cf; + int i, regnum; + + /* The following is true for OpenBSD 3.7: + + The pcb contains %r1 (the stack pointer) at the point of the + context switch in cpu_switch(). At that point we have a stack + frame as described by `struct switchframe', and below that a call + frame as described by `struct callframe'. From this information + we reconstruct the register state as it would look when we are in + cpu_switch(). */ + + /* 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 (regcache, gdbarch_sp_regnum (gdbarch), &sf.sp); + regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &sf.cr); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2); + for (i = 0, regnum = tdep->ppc_gp0_regnum + 13; i < 19; i++, regnum++) + regcache_raw_supply (regcache, regnum, &sf.fixreg[i]); + + read_memory (sf.sp, (gdb_byte *)&cf, sizeof cf); + regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &cf.lr); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30); + regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_ppcobsd_nat (void); + +void +_initialize_ppcobsd_nat (void) +{ + struct target_ops *t; + + /* Add in local overrides. */ + t = inf_ptrace_target (); + t->to_fetch_registers = ppcobsd_fetch_registers; + t->to_store_registers = ppcobsd_store_registers; + obsd_add_target (t); + + /* General-purpose registers. */ + ppcobsd_reg_offsets.r0_offset = offsetof (struct reg, gpr); + ppcobsd_reg_offsets.gpr_size = 4; + ppcobsd_reg_offsets.xr_size = 4; + ppcobsd_reg_offsets.pc_offset = offsetof (struct reg, pc); + ppcobsd_reg_offsets.ps_offset = offsetof (struct reg, ps); + ppcobsd_reg_offsets.cr_offset = offsetof (struct reg, cnd); + ppcobsd_reg_offsets.lr_offset = offsetof (struct reg, lr); + ppcobsd_reg_offsets.ctr_offset = offsetof (struct reg, cnt); + ppcobsd_reg_offsets.xer_offset = offsetof (struct reg, xer); + ppcobsd_reg_offsets.mq_offset = offsetof (struct reg, mq); + + /* Floating-point registers. */ + ppcobsd_reg_offsets.f0_offset = offsetof (struct reg, fpr); + ppcobsd_reg_offsets.fpscr_offset = -1; +#ifdef PT_GETFPREGS + ppcobsd_fpreg_offsets.f0_offset = offsetof (struct fpreg, fpr); + ppcobsd_fpreg_offsets.fpscr_offset = offsetof (struct fpreg, fpscr); + ppcobsd_fpreg_offsets.fpscr_size = 4; +#endif + + /* AltiVec registers. */ + ppcobsd_reg_offsets.vr0_offset = offsetof (struct vreg, vreg); + ppcobsd_reg_offsets.vscr_offset = offsetof (struct vreg, vscr); + ppcobsd_reg_offsets.vrsave_offset = offsetof (struct vreg, vrsave); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (ppcobsd_supply_pcb); +} diff --git a/gdb/ppc-obsd-tdep.c b/gdb/ppc-obsd-tdep.c new file mode 100644 index 00000000000..f61dd24b961 --- /dev/null +++ b/gdb/ppc-obsd-tdep.c @@ -0,0 +1,327 @@ +/* Target-dependent code for OpenBSD/powerpc. + + Copyright (C) 2004-2016 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 "frame-unwind.h" +#include "gdbtypes.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "symtab.h" +#include "trad-frame.h" + +#include "ppc-tdep.h" +#include "ppc-obsd-tdep.h" +#include "solib-svr4.h" + +/* Register offsets from . */ +struct ppc_reg_offsets ppcobsd_reg_offsets; +struct ppc_reg_offsets ppcobsd_fpreg_offsets; + + +/* Core file support. */ + +/* Supply register REGNUM in the general-purpose register set REGSET + from the buffer specified by GREGS and LEN to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +void +ppcobsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t len) +{ + ppc_supply_gregset (regset, regcache, regnum, gregs, len); + ppc_supply_fpregset (regset, regcache, regnum, gregs, len); +} + +/* Collect register REGNUM in the general-purpose register set + REGSET, from register cache REGCACHE into the buffer specified by + GREGS and LEN. If REGNUM is -1, do this for all registers in + REGSET. */ + +void +ppcobsd_collect_gregset (const struct regset *regset, + const struct regcache *regcache, int regnum, + void *gregs, size_t len) +{ + ppc_collect_gregset (regset, regcache, regnum, gregs, len); + ppc_collect_fpregset (regset, regcache, regnum, gregs, len); +} + +/* OpenBSD/powerpc register set. */ + +const struct regset ppcobsd_gregset = +{ + &ppcobsd_reg_offsets, + ppcobsd_supply_gregset +}; + +const struct regset ppcobsd_fpregset = +{ + &ppcobsd_fpreg_offsets, + ppc_supply_fpregset +}; + +/* Iterate over core file register note sections. */ + +static void +ppcobsd_iterate_over_regset_sections (struct gdbarch *gdbarch, + iterate_over_regset_sections_cb *cb, + void *cb_data, + const struct regcache *regcache) +{ + cb (".reg", 412, &ppcobsd_gregset, NULL, cb_data); +} + + +/* Signal trampolines. */ + +/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page + in virtual memory. The randomness makes it somewhat tricky to + detect it, but fortunately we can rely on the fact that the start + of the sigtramp routine is page-aligned. We recognize the + trampoline by looking for the code that invokes the sigreturn + system call. The offset where we can find that code varies from + release to release. + + By the way, the mapping mentioned above is read-only, so you cannot + place a breakpoint in the signal trampoline. */ + +/* Default page size. */ +static const int ppcobsd_page_size = 4096; + +/* Offset for sigreturn(2). */ +static const int ppcobsd_sigreturn_offset[] = { + 0x98, /* OpenBSD 3.8 */ + 0x0c, /* OpenBSD 3.2 */ + -1 +}; + +static int +ppcobsd_sigtramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR pc = get_frame_pc (this_frame); + CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1)); + const int *offset; + const char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (name) + return 0; + + for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++) + { + gdb_byte buf[2 * PPC_INSN_SIZE]; + unsigned long insn; + + if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, + buf, sizeof buf)) + continue; + + /* Check for "li r0,SYS_sigreturn". */ + insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); + if (insn != 0x38000067) + continue; + + /* Check for "sc". */ + insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, + PPC_INSN_SIZE, byte_order); + if (insn != 0x44000002) + continue; + + return 1; + } + + return 0; +} + +static struct trad_frame_cache * +ppcobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + struct trad_frame_cache *cache; + CORE_ADDR addr, base, func; + gdb_byte buf[PPC_INSN_SIZE]; + unsigned long insn, sigcontext_offset; + int i; + + if (*this_cache) + return (struct trad_frame_cache *) *this_cache; + + cache = trad_frame_cache_zalloc (this_frame); + *this_cache = cache; + + func = get_frame_pc (this_frame); + func &= ~(ppcobsd_page_size - 1); + if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf)) + return cache; + + /* Calculate the offset where we can find `struct sigcontext'. We + base our calculation on the amount of stack space reserved by the + first instruction of the signal trampoline. */ + insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); + sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8; + + base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); + addr = base + sigcontext_offset + 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 (cache, regnum, addr); + } + trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr); + addr += tdep->wordsize; + trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr); + /* SRR0? */ + addr += tdep->wordsize; + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (cache, frame_id_build (base, func)); + + return cache; +} + +static void +ppcobsd_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + struct trad_frame_cache *cache = + ppcobsd_sigtramp_frame_cache (this_frame, this_cache); + + trad_frame_get_id (cache, this_id); +} + +static struct value * +ppcobsd_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct trad_frame_cache *cache = + ppcobsd_sigtramp_frame_cache (this_frame, this_cache); + + return trad_frame_get_register (cache, this_frame, regnum); +} + +static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + ppcobsd_sigtramp_frame_this_id, + ppcobsd_sigtramp_frame_prev_register, + NULL, + ppcobsd_sigtramp_frame_sniffer +}; + + +static void +ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* OpenBSD 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); + + /* OpenBSD currently uses a broken GCC. */ + set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value); + + /* OpenBSD 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, ppcobsd_iterate_over_regset_sections); + + frame_unwind_append_unwinder (gdbarch, &ppcobsd_sigtramp_frame_unwind); +} + + +/* OpenBSD uses uses the traditional NetBSD core file format, even for + ports that use ELF. */ +#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF + +static enum gdb_osabi +ppcobsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_CORE; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_ppcobsd_tdep (void); + +void +_initialize_ppcobsd_tdep (void) +{ + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour, + ppcobsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF, + ppcobsd_init_abi); + gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF, + ppcobsd_init_abi); + + /* Avoid initializing the register offsets again if they were + already initialized by ppcobsd-nat.c. */ + if (ppcobsd_reg_offsets.pc_offset == 0) + { + /* General-purpose registers. */ + ppcobsd_reg_offsets.r0_offset = 0; + ppcobsd_reg_offsets.gpr_size = 4; + ppcobsd_reg_offsets.xr_size = 4; + ppcobsd_reg_offsets.pc_offset = 384; + ppcobsd_reg_offsets.ps_offset = 388; + ppcobsd_reg_offsets.cr_offset = 392; + ppcobsd_reg_offsets.lr_offset = 396; + ppcobsd_reg_offsets.ctr_offset = 400; + ppcobsd_reg_offsets.xer_offset = 404; + ppcobsd_reg_offsets.mq_offset = 408; + + /* Floating-point registers. */ + ppcobsd_reg_offsets.f0_offset = 128; + ppcobsd_reg_offsets.fpscr_offset = -1; + + /* AltiVec registers. */ + ppcobsd_reg_offsets.vr0_offset = 0; + ppcobsd_reg_offsets.vscr_offset = 512; + ppcobsd_reg_offsets.vrsave_offset = 520; + } + + if (ppcobsd_fpreg_offsets.fpscr_offset == 0) + { + /* Floating-point registers. */ + ppcobsd_reg_offsets.f0_offset = 0; + ppcobsd_reg_offsets.fpscr_offset = 256; + ppcobsd_reg_offsets.fpscr_size = 4; + } +} diff --git a/gdb/ppc-obsd-tdep.h b/gdb/ppc-obsd-tdep.h new file mode 100644 index 00000000000..cca5a791c6d --- /dev/null +++ b/gdb/ppc-obsd-tdep.h @@ -0,0 +1,52 @@ +/* Target-dependent code for OpenBSD/powerpc. + + Copyright (C) 2004-2016 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_OBSD_TDEP_H +#define PPC_OBSD_TDEP_H + +struct regset; +struct regcache; + +/* Register offsets for OpenBSD/powerpc. */ +extern struct ppc_reg_offsets ppcobsd_reg_offsets; +extern struct ppc_reg_offsets ppcobsd_fpreg_offsets; + +/* Register sets for OpenBSD/powerpc. */ +extern const struct regset ppcobsd_gregset; +extern const struct regset ppcobsd_fpregset; + + +/* Supply register REGNUM in the general-purpose register set REGSET + from the buffer specified by GREGS and LEN to register cache + REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ + +extern void ppcobsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *gregs, size_t len); + +/* Collect register REGNUM in the general-purpose register set + REGSET, from register cache REGCACHE into the buffer specified by + GREGS and LEN. If REGNUM is -1, do this for all registers in + REGSET. */ + +extern void ppcobsd_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs, size_t len); + +#endif /* ppc-obsd-tdep.h */ diff --git a/gdb/ppcfbsd-nat.c b/gdb/ppcfbsd-nat.c deleted file mode 100644 index 999e383d44f..00000000000 --- a/gdb/ppcfbsd-nat.c +++ /dev/null @@ -1,219 +0,0 @@ -/* Native-dependent code for PowerPC's running FreeBSD, for GDB. - - Copyright (C) 2013-2016 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 "inferior.h" -#include "regcache.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "fbsd-nat.h" -#include "gregset.h" -#include "ppc-tdep.h" -#include "ppcfbsd-tdep.h" -#include "inf-ptrace.h" -#include "bsd-kvm.h" - -/* Fill GDB's register array with the general-purpose register values - in *GREGSETP. */ - -void -supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) -{ - const struct regset *regset = ppc_fbsd_gregset (sizeof (long)); - - ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp)); -} - -/* Fill register REGNO (if a gpr) in *GREGSETP with the value in GDB's - register array. If REGNO is -1 do it for all registers. */ - -void -fill_gregset (const struct regcache *regcache, - gdb_gregset_t *gregsetp, int regno) -{ - const struct regset *regset = ppc_fbsd_gregset (sizeof (long)); - - if (regno == -1) - memset (gregsetp, 0, sizeof (*gregsetp)); - ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp)); -} - -/* Fill GDB's register array with the floating-point register values - in *FPREGSETP. */ - -void -supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp) -{ - const struct regset *regset = ppc_fbsd_fpregset (); - - ppc_supply_fpregset (regset, regcache, -1, - fpregsetp, sizeof (*fpregsetp)); -} - -/* Fill register REGNO in *FGREGSETP with the value in GDB's - register array. If REGNO is -1 do it for all registers. */ - -void -fill_fpregset (const struct regcache *regcache, - gdb_fpregset_t *fpregsetp, int regno) -{ - const struct regset *regset = ppc_fbsd_fpregset (); - - ppc_collect_fpregset (regset, regcache, regno, - fpregsetp, sizeof (*fpregsetp)); -} - -/* Returns true if PT_GETFPREGS fetches this register. */ - -static int -getfpregs_supplies (struct gdbarch *gdbarch, int regno) -{ - 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 ((regno >= tdep->ppc_fp0_regnum - && regno < tdep->ppc_fp0_regnum + ppc_num_fprs) - || regno == tdep->ppc_fpscr_regnum); -} - -/* Fetch register REGNO from the child process. If REGNO is -1, do it - for all registers. */ - -static void -ppcfbsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - gdb_gregset_t regs; - - if (ptrace (PT_GETREGS, ptid_get_lwp (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - supply_gregset (regcache, ®s); - - if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno)) - { - const struct regset *fpregset = ppc_fbsd_fpregset (); - gdb_fpregset_t fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_lwp (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get FP registers")); - - ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof fpregs); - } -} - -/* Store register REGNO back into the child process. If REGNO is -1, - do this for all registers. */ - -static void -ppcfbsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - gdb_gregset_t regs; - - if (ptrace (PT_GETREGS, ptid_get_lwp (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - fill_gregset (regcache, ®s, regno); - - if (ptrace (PT_SETREGS, ptid_get_lwp (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - - if (regno == -1 || getfpregs_supplies (get_regcache_arch (regcache), regno)) - { - gdb_fpregset_t fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_lwp (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get FP registers")); - - fill_fpregset (regcache, &fpregs, regno); - - if (ptrace (PT_SETFPREGS, ptid_get_lwp (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't set FP registers")); - } -} - -/* Architecture specific function that reconstructs the - register state from PCB (Process Control Block) and supplies it - to REGCACHE. */ - -static int -ppcfbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - int i, regnum; - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_sp == 0) - return 0; - - regcache_raw_supply (regcache, gdbarch_sp_regnum (gdbarch), &pcb->pcb_sp); - regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &pcb->pcb_cr); - regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &pcb->pcb_lr); - for (i = 0, regnum = tdep->ppc_gp0_regnum + 14; i < 20; i++, regnum++) - regcache_raw_supply (regcache, regnum, &pcb->pcb_context[i]); - - return 1; -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ - -void _initialize_ppcfbsd_nat (void); - -void -_initialize_ppcfbsd_nat (void) -{ - struct target_ops *t; - - /* Add in local overrides. */ - t = inf_ptrace_target (); - t->to_fetch_registers = ppcfbsd_fetch_inferior_registers; - t->to_store_registers = ppcfbsd_store_inferior_registers; - fbsd_nat_add_target (t); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (ppcfbsd_supply_pcb); -} diff --git a/gdb/ppcfbsd-tdep.c b/gdb/ppcfbsd-tdep.c deleted file mode 100644 index 10b41b0fee8..00000000000 --- a/gdb/ppcfbsd-tdep.c +++ /dev/null @@ -1,353 +0,0 @@ -/* Target-dependent code for PowerPC systems running FreeBSD. - - Copyright (C) 2013-2016 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 "frame-unwind.h" -#include "gdbtypes.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "symtab.h" -#include "target.h" -#include "trad-frame.h" - -#include "ppc-tdep.h" -#include "ppc64-tdep.h" -#include "ppcfbsd-tdep.h" -#include "fbsd-tdep.h" -#include "solib-svr4.h" - - -/* 32-bit regset descriptions. */ - -static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets = - { - /* General-purpose registers. */ - /* .r0_offset = */ 0, - /* .gpr_size = */ 4, - /* .xr_size = */ 4, - /* .pc_offset = */ 144, - /* .ps_offset = */ -1, - /* .cr_offset = */ 132, - /* .lr_offset = */ 128, - /* .ctr_offset = */ 140, - /* .xer_offset = */ 136, - /* .mq_offset = */ -1, - - /* Floating-point registers. */ - /* .f0_offset = */ 0, - /* .fpscr_offset = */ 256, - /* .fpscr_size = */ 8, -#ifdef NOTYET - /* AltiVec registers. */ - /* .vr0_offset = */ 0, - /* .vscr_offset = */ 512 + 12, - /* .vrsave_offset = */ 512 -#endif - }; - -/* 64-bit regset descriptions. */ - -static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets = - { - /* General-purpose registers. */ - /* .r0_offset = */ 0, - /* .gpr_size = */ 8, - /* .xr_size = */ 8, - /* .pc_offset = */ 288, - /* .ps_offset = */ -1, - /* .cr_offset = */ 264, - /* .lr_offset = */ 256, - /* .ctr_offset = */ 280, - /* .xer_offset = */ 272, - /* .mq_offset = */ -1, - - /* Floating-point registers. */ - /* .f0_offset = */ 0, - /* .fpscr_offset = */ 256, - /* .fpscr_size = */ 8, -#ifdef NOYET - /* AltiVec registers. */ - /* .vr0_offset = */ 0, - /* .vscr_offset = */ 512 + 12, - /* .vrsave_offset = */ 528 -#endif - }; - -/* 32-bit general-purpose register set. */ - -static const struct regset ppc32_fbsd_gregset = { - &ppc32_fbsd_reg_offsets, - ppc_supply_gregset, - ppc_collect_gregset -}; - -/* 64-bit general-purpose register set. */ - -static const struct regset ppc64_fbsd_gregset = { - &ppc64_fbsd_reg_offsets, - ppc_supply_gregset, - ppc_collect_gregset -}; - -/* 32-/64-bit floating-point register set. */ - -static const struct regset ppc32_fbsd_fpregset = { - &ppc32_fbsd_reg_offsets, - ppc_supply_fpregset, - ppc_collect_fpregset -}; - -const struct regset * -ppc_fbsd_gregset (int wordsize) -{ - return wordsize == 8 ? &ppc64_fbsd_gregset : &ppc32_fbsd_gregset; -} - -const struct regset * -ppc_fbsd_fpregset (void) -{ - return &ppc32_fbsd_fpregset; -} - -/* Iterate over core file register note sections. */ - -static void -ppcfbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - if (tdep->wordsize == 4) - cb (".reg", 148, &ppc32_fbsd_gregset, NULL, cb_data); - else - cb (".reg", 296, &ppc64_fbsd_gregset, NULL, cb_data); - cb (".reg2", 264, &ppc32_fbsd_fpregset, NULL, cb_data); -} - -/* Default page size. */ - -static const int ppcfbsd_page_size = 4096; - -/* Offset for sigreturn(2). */ - -static const int ppcfbsd_sigreturn_offset[] = { - 0xc, /* FreeBSD 32-bit */ - -1 -}; - -/* Signal trampolines. */ - -static int -ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR pc = get_frame_pc (this_frame); - CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1)); - const int *offset; - const char *name; - - /* A stack trampoline is detected if no name is associated - to the current pc and if it points inside a trampoline - sequence. */ - - find_pc_partial_function (pc, &name, NULL, NULL); - - /* If we have a name, we have no trampoline, return. */ - if (name) - return 0; - - for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++) - { - gdb_byte buf[2 * PPC_INSN_SIZE]; - unsigned long insn; - - if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, - buf, sizeof buf)) - continue; - - /* Check for "li r0,SYS_sigreturn". */ - insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); - if (insn != 0x380001a1) - continue; - - /* Check for "sc". */ - insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, - PPC_INSN_SIZE, byte_order); - if (insn != 0x44000002) - continue; - - return 1; - } - - return 0; -} - -static struct trad_frame_cache * -ppcfbsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - struct trad_frame_cache *cache; - CORE_ADDR addr, base, func; - gdb_byte buf[PPC_INSN_SIZE]; - int i; - - if (*this_cache) - return (struct trad_frame_cache *) *this_cache; - - cache = trad_frame_cache_zalloc (this_frame); - *this_cache = cache; - - func = get_frame_pc (this_frame); - func &= ~(ppcfbsd_page_size - 1); - if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf)) - return cache; - - base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); - addr = base + 0x10 + 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 (cache, regnum, addr); - } - trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr); - /* SRR0? */ - addr += tdep->wordsize; - - /* Construct the frame ID using the function start. */ - trad_frame_set_id (cache, frame_id_build (base, func)); - - return cache; -} - -static void -ppcfbsd_sigtramp_frame_this_id (struct frame_info *this_frame, - void **this_cache, struct frame_id *this_id) -{ - struct trad_frame_cache *cache = - ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); - - trad_frame_get_id (cache, this_id); -} - -static struct value * -ppcfbsd_sigtramp_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct trad_frame_cache *cache = - ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); - - return trad_frame_get_register (cache, this_frame, regnum); -} - -static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = { - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - ppcfbsd_sigtramp_frame_this_id, - ppcfbsd_sigtramp_frame_prev_register, - NULL, - ppcfbsd_sigtramp_frame_sniffer -}; - -static enum return_value_convention -ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function, - struct type *valtype, struct regcache *regcache, - gdb_byte *readbuf, const gdb_byte *writebuf) -{ - return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, - regcache, readbuf, writebuf); -} - - -static void -ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Generic FreeBSD support. */ - fbsd_init_abi (info, gdbarch); - - /* FreeBSD 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); - - if (tdep->wordsize == 4) - { - set_gdbarch_return_value (gdbarch, ppcfbsd_return_value); - - set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); - set_solib_svr4_fetch_link_map_offsets (gdbarch, - svr4_ilp32_fetch_link_map_offsets); - - frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind); - set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc"); - } - - if (tdep->wordsize == 8) - { - set_gdbarch_convert_from_func_ptr_addr - (gdbarch, ppc64_convert_from_func_ptr_addr); - set_gdbarch_elf_make_msymbol_special (gdbarch, - ppc64_elf_make_msymbol_special); - - set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); - set_solib_svr4_fetch_link_map_offsets (gdbarch, - svr4_lp64_fetch_link_map_offsets); - set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); - } - - set_gdbarch_iterate_over_regset_sections - (gdbarch, ppcfbsd_iterate_over_regset_sections); - - set_gdbarch_fetch_tls_load_module_address (gdbarch, - svr4_fetch_objfile_link_map); -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ - -void _initialize_ppcfbsd_tdep (void); - -void -_initialize_ppcfbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_FREEBSD_ELF, - ppcfbsd_init_abi); - gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64, - GDB_OSABI_FREEBSD_ELF, - ppcfbsd_init_abi); - gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD_ELF, - ppcfbsd_init_abi); -} diff --git a/gdb/ppcfbsd-tdep.h b/gdb/ppcfbsd-tdep.h deleted file mode 100644 index a51e5b7f24f..00000000000 --- a/gdb/ppcfbsd-tdep.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Target-dependent code for GDB on PowerPC systems running FreeBSD. - - Copyright (C) 2013-2016 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 PPCFBSD_TDEP_H -#define PPCFBSD_TDEP_H - -struct regset; - -/* From ppcfbsd-tdep.c ... */ -const struct regset *ppc_fbsd_gregset (int); -const struct regset *ppc_fbsd_fpregset (void); - -#endif /* PPCFBSD_TDEP_H */ diff --git a/gdb/ppcnbsd-nat.c b/gdb/ppcnbsd-nat.c deleted file mode 100644 index cd0416f5561..00000000000 --- a/gdb/ppcnbsd-nat.c +++ /dev/null @@ -1,197 +0,0 @@ -/* Native-dependent code for NetBSD/powerpc. - - Copyright (C) 2002-2016 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 -#include -#include -#include -#include - -#include "gdbcore.h" -#include "inferior.h" -#include "regcache.h" - -#include "ppc-tdep.h" -#include "ppcnbsd-tdep.h" -#include "bsd-kvm.h" -#include "inf-ptrace.h" - -/* 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); -} - -static void -ppcnbsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - if (regnum == -1 || getregs_supplies (gdbarch, regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -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, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get FP registers")); - - ppc_supply_fpregset (&ppcnbsd_fpregset, regcache, - regnum, &fpregs, sizeof fpregs); - } -} - -static void -ppcnbsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - - if (regnum == -1 || getregs_supplies (gdbarch, regnum)) - { - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - ppc_collect_gregset (&ppcnbsd_gregset, regcache, - regnum, ®s, sizeof regs); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - } - - if (regnum == -1 || getfpregs_supplies (gdbarch, regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get FP registers")); - - ppc_collect_fpregset (&ppcnbsd_fpregset, regcache, - regnum, &fpregs, sizeof fpregs); - - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -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 = get_regcache_arch (regcache); - 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 (regcache, tdep->ppc_cr_regnum, &sf.cr); - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2); - for (i = 0 ; i < 19 ; i++) - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 13 + i, - &sf.fixreg[i]); - - read_memory(sf.sp, (gdb_byte *)&cf, sizeof(cf)); - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30); - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31); - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 1, &cf.sp); - - read_memory(cf.sp, (gdb_byte *)&cf, sizeof(cf)); - regcache_raw_supply (regcache, tdep->ppc_lr_regnum, &cf.lr); - regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &cf.lr); - - return 1; -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_ppcnbsd_nat (void); - -void -_initialize_ppcnbsd_nat (void) -{ - struct target_ops *t; - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (ppcnbsd_supply_pcb); - - /* Add in local overrides. */ - t = inf_ptrace_target (); - t->to_fetch_registers = ppcnbsd_fetch_inferior_registers; - t->to_store_registers = ppcnbsd_store_inferior_registers; - add_target (t); -} diff --git a/gdb/ppcnbsd-tdep.c b/gdb/ppcnbsd-tdep.c deleted file mode 100644 index be152e1e795..00000000000 --- a/gdb/ppcnbsd-tdep.c +++ /dev/null @@ -1,227 +0,0 @@ -/* Target-dependent code for NetBSD/powerpc. - - Copyright (C) 2002-2016 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 "ppcnbsd-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, &ppcnbsd_gregset, NULL, cb_data); - cb (".reg2", 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 ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT - || TYPE_CODE (valtype) == TYPE_CODE_UNION) - && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8) - && TYPE_VECTOR (valtype)) - && !(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, -1 }, /* add r1,r1,-16 */ - { 0x4e800021, -1 }, /* blrl */ - { 0x38610018, -1 }, /* addi r3,r1,24 */ - { 0x38000127, -1 }, /* li r0,295 */ - { 0x44000002, -1 }, /* sc */ - { 0x38000001, -1 }, /* li r0,1 */ - { 0x44000002, -1 }, /* sc */ - { TRAMP_SENTINEL_INSN, -1 } - }, - ppcnbsd_sigtramp_cache_init -}; - -/* NetBSD 2.0 introduced a slightly different signal trampoline. */ - -const struct tramp_frame ppcnbsd2_sigtramp = -{ - SIGTRAMP_FRAME, - 4, - { - { 0x3821fff0, -1 }, /* add r1,r1,-16 */ - { 0x4e800021, -1 }, /* blrl */ - { 0x38610010, -1 }, /* addi r3,r1,16 */ - { 0x38000127, -1 }, /* li r0,295 */ - { 0x44000002, -1 }, /* sc */ - { 0x38000001, -1 }, /* li r0,1 */ - { 0x44000002, -1 }, /* sc */ - { TRAMP_SENTINEL_INSN, -1 } - }, - ppcnbsd_sigtramp_cache_init -}; - - -static void -ppcnbsd_init_abi (struct gdbarch_info info, - struct gdbarch *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); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_ppcnbsd_tdep (void); - -void -_initialize_ppcnbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_NETBSD_ELF, - 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; - - /* AltiVec registers. */ - ppcnbsd_reg_offsets.vr0_offset = 0; - ppcnbsd_reg_offsets.vrsave_offset = 512; - ppcnbsd_reg_offsets.vscr_offset = 524; - } -} diff --git a/gdb/ppcnbsd-tdep.h b/gdb/ppcnbsd-tdep.h deleted file mode 100644 index 25258ef0a78..00000000000 --- a/gdb/ppcnbsd-tdep.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Target-dependent code for NetBSD/powerpc. - - Copyright (C) 2004-2016 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 PPCNBSD_TDEP_H -#define PPCNBSD_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 /* ppcnbsd-tdep.h */ diff --git a/gdb/ppcobsd-nat.c b/gdb/ppcobsd-nat.c deleted file mode 100644 index c8e82c38799..00000000000 --- a/gdb/ppcobsd-nat.c +++ /dev/null @@ -1,231 +0,0 @@ -/* Native-dependent code for OpenBSD/powerpc. - - Copyright (C) 2004-2016 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 "inferior.h" -#include "regcache.h" - -#include -#include -#include -#include -#include -#include - -#include "ppc-tdep.h" -#include "ppcobsd-tdep.h" -#include "inf-ptrace.h" -#include "obsd-nat.h" -#include "bsd-kvm.h" - -/* OpenBSD/powerpc didn't have PT_GETFPREGS/PT_SETFPREGS until release - 4.0. On older releases the floating-point registers are handled by - PT_GETREGS/PT_SETREGS, but fpscr wasn't available.. */ - -#ifdef PT_GETFPREGS - -/* Returns true if PT_GETFPREGS fetches this register. */ - -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); -} - -#endif /* PT_GETFPREGS */ - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers. */ - -static void -ppcobsd_fetch_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - ppc_supply_gregset (&ppcobsd_gregset, regcache, -1, - ®s, sizeof regs); -#ifndef PT_GETFPREGS - ppc_supply_fpregset (&ppcobsd_gregset, regcache, -1, - ®s, sizeof regs); -#endif - -#ifdef PT_GETFPREGS - if (regnum == -1 - || getfpregs_supplies (get_regcache_arch (regcache), regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - ppc_supply_fpregset (&ppcobsd_fpregset, regcache, -1, - &fpregs, sizeof fpregs); - } -#endif -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers. */ - -static void -ppcobsd_store_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - ppc_collect_gregset (&ppcobsd_gregset, regcache, - regnum, ®s, sizeof regs); -#ifndef PT_GETFPREGS - ppc_collect_fpregset (&ppcobsd_gregset, regcache, - regnum, ®s, sizeof regs); -#endif - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); - -#ifdef PT_GETFPREGS - if (regnum == -1 - || getfpregs_supplies (get_regcache_arch (regcache), regnum)) - { - struct fpreg fpregs; - - if (ptrace (PT_GETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't get floating point status")); - - ppc_collect_fpregset (&ppcobsd_fpregset, regcache, - regnum, &fpregs, sizeof fpregs); - - if (ptrace (PT_SETFPREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) - perror_with_name (_("Couldn't write floating point status")); - } -#endif -} - - -static int -ppcobsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - struct switchframe sf; - struct callframe cf; - int i, regnum; - - /* The following is true for OpenBSD 3.7: - - The pcb contains %r1 (the stack pointer) at the point of the - context switch in cpu_switch(). At that point we have a stack - frame as described by `struct switchframe', and below that a call - frame as described by `struct callframe'. From this information - we reconstruct the register state as it would look when we are in - cpu_switch(). */ - - /* 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 (regcache, gdbarch_sp_regnum (gdbarch), &sf.sp); - regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &sf.cr); - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2); - for (i = 0, regnum = tdep->ppc_gp0_regnum + 13; i < 19; i++, regnum++) - regcache_raw_supply (regcache, regnum, &sf.fixreg[i]); - - read_memory (sf.sp, (gdb_byte *)&cf, sizeof cf); - regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch), &cf.lr); - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30); - regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_ppcobsd_nat (void); - -void -_initialize_ppcobsd_nat (void) -{ - struct target_ops *t; - - /* Add in local overrides. */ - t = inf_ptrace_target (); - t->to_fetch_registers = ppcobsd_fetch_registers; - t->to_store_registers = ppcobsd_store_registers; - obsd_add_target (t); - - /* General-purpose registers. */ - ppcobsd_reg_offsets.r0_offset = offsetof (struct reg, gpr); - ppcobsd_reg_offsets.gpr_size = 4; - ppcobsd_reg_offsets.xr_size = 4; - ppcobsd_reg_offsets.pc_offset = offsetof (struct reg, pc); - ppcobsd_reg_offsets.ps_offset = offsetof (struct reg, ps); - ppcobsd_reg_offsets.cr_offset = offsetof (struct reg, cnd); - ppcobsd_reg_offsets.lr_offset = offsetof (struct reg, lr); - ppcobsd_reg_offsets.ctr_offset = offsetof (struct reg, cnt); - ppcobsd_reg_offsets.xer_offset = offsetof (struct reg, xer); - ppcobsd_reg_offsets.mq_offset = offsetof (struct reg, mq); - - /* Floating-point registers. */ - ppcobsd_reg_offsets.f0_offset = offsetof (struct reg, fpr); - ppcobsd_reg_offsets.fpscr_offset = -1; -#ifdef PT_GETFPREGS - ppcobsd_fpreg_offsets.f0_offset = offsetof (struct fpreg, fpr); - ppcobsd_fpreg_offsets.fpscr_offset = offsetof (struct fpreg, fpscr); - ppcobsd_fpreg_offsets.fpscr_size = 4; -#endif - - /* AltiVec registers. */ - ppcobsd_reg_offsets.vr0_offset = offsetof (struct vreg, vreg); - ppcobsd_reg_offsets.vscr_offset = offsetof (struct vreg, vscr); - ppcobsd_reg_offsets.vrsave_offset = offsetof (struct vreg, vrsave); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (ppcobsd_supply_pcb); -} diff --git a/gdb/ppcobsd-tdep.c b/gdb/ppcobsd-tdep.c deleted file mode 100644 index bc5a5a8189c..00000000000 --- a/gdb/ppcobsd-tdep.c +++ /dev/null @@ -1,327 +0,0 @@ -/* Target-dependent code for OpenBSD/powerpc. - - Copyright (C) 2004-2016 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 "frame-unwind.h" -#include "gdbtypes.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "symtab.h" -#include "trad-frame.h" - -#include "ppc-tdep.h" -#include "ppcobsd-tdep.h" -#include "solib-svr4.h" - -/* Register offsets from . */ -struct ppc_reg_offsets ppcobsd_reg_offsets; -struct ppc_reg_offsets ppcobsd_fpreg_offsets; - - -/* Core file support. */ - -/* Supply register REGNUM in the general-purpose register set REGSET - from the buffer specified by GREGS and LEN to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -void -ppcobsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *gregs, size_t len) -{ - ppc_supply_gregset (regset, regcache, regnum, gregs, len); - ppc_supply_fpregset (regset, regcache, regnum, gregs, len); -} - -/* Collect register REGNUM in the general-purpose register set - REGSET, from register cache REGCACHE into the buffer specified by - GREGS and LEN. If REGNUM is -1, do this for all registers in - REGSET. */ - -void -ppcobsd_collect_gregset (const struct regset *regset, - const struct regcache *regcache, int regnum, - void *gregs, size_t len) -{ - ppc_collect_gregset (regset, regcache, regnum, gregs, len); - ppc_collect_fpregset (regset, regcache, regnum, gregs, len); -} - -/* OpenBSD/powerpc register set. */ - -const struct regset ppcobsd_gregset = -{ - &ppcobsd_reg_offsets, - ppcobsd_supply_gregset -}; - -const struct regset ppcobsd_fpregset = -{ - &ppcobsd_fpreg_offsets, - ppc_supply_fpregset -}; - -/* Iterate over core file register note sections. */ - -static void -ppcobsd_iterate_over_regset_sections (struct gdbarch *gdbarch, - iterate_over_regset_sections_cb *cb, - void *cb_data, - const struct regcache *regcache) -{ - cb (".reg", 412, &ppcobsd_gregset, NULL, cb_data); -} - - -/* Signal trampolines. */ - -/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page - in virtual memory. The randomness makes it somewhat tricky to - detect it, but fortunately we can rely on the fact that the start - of the sigtramp routine is page-aligned. We recognize the - trampoline by looking for the code that invokes the sigreturn - system call. The offset where we can find that code varies from - release to release. - - By the way, the mapping mentioned above is read-only, so you cannot - place a breakpoint in the signal trampoline. */ - -/* Default page size. */ -static const int ppcobsd_page_size = 4096; - -/* Offset for sigreturn(2). */ -static const int ppcobsd_sigreturn_offset[] = { - 0x98, /* OpenBSD 3.8 */ - 0x0c, /* OpenBSD 3.2 */ - -1 -}; - -static int -ppcobsd_sigtramp_frame_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR pc = get_frame_pc (this_frame); - CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1)); - const int *offset; - const char *name; - - find_pc_partial_function (pc, &name, NULL, NULL); - if (name) - return 0; - - for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++) - { - gdb_byte buf[2 * PPC_INSN_SIZE]; - unsigned long insn; - - if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, - buf, sizeof buf)) - continue; - - /* Check for "li r0,SYS_sigreturn". */ - insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); - if (insn != 0x38000067) - continue; - - /* Check for "sc". */ - insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, - PPC_INSN_SIZE, byte_order); - if (insn != 0x44000002) - continue; - - return 1; - } - - return 0; -} - -static struct trad_frame_cache * -ppcobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) -{ - struct gdbarch *gdbarch = get_frame_arch (this_frame); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct trad_frame_cache *cache; - CORE_ADDR addr, base, func; - gdb_byte buf[PPC_INSN_SIZE]; - unsigned long insn, sigcontext_offset; - int i; - - if (*this_cache) - return (struct trad_frame_cache *) *this_cache; - - cache = trad_frame_cache_zalloc (this_frame); - *this_cache = cache; - - func = get_frame_pc (this_frame); - func &= ~(ppcobsd_page_size - 1); - if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf)) - return cache; - - /* Calculate the offset where we can find `struct sigcontext'. We - base our calculation on the amount of stack space reserved by the - first instruction of the signal trampoline. */ - insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); - sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8; - - base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); - addr = base + sigcontext_offset + 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 (cache, regnum, addr); - } - trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr); - addr += tdep->wordsize; - trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr); - /* SRR0? */ - addr += tdep->wordsize; - - /* Construct the frame ID using the function start. */ - trad_frame_set_id (cache, frame_id_build (base, func)); - - return cache; -} - -static void -ppcobsd_sigtramp_frame_this_id (struct frame_info *this_frame, - void **this_cache, struct frame_id *this_id) -{ - struct trad_frame_cache *cache = - ppcobsd_sigtramp_frame_cache (this_frame, this_cache); - - trad_frame_get_id (cache, this_id); -} - -static struct value * -ppcobsd_sigtramp_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct trad_frame_cache *cache = - ppcobsd_sigtramp_frame_cache (this_frame, this_cache); - - return trad_frame_get_register (cache, this_frame, regnum); -} - -static const struct frame_unwind ppcobsd_sigtramp_frame_unwind = { - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - ppcobsd_sigtramp_frame_this_id, - ppcobsd_sigtramp_frame_prev_register, - NULL, - ppcobsd_sigtramp_frame_sniffer -}; - - -static void -ppcobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* OpenBSD 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); - - /* OpenBSD currently uses a broken GCC. */ - set_gdbarch_return_value (gdbarch, ppc_sysv_abi_broken_return_value); - - /* OpenBSD 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, ppcobsd_iterate_over_regset_sections); - - frame_unwind_append_unwinder (gdbarch, &ppcobsd_sigtramp_frame_unwind); -} - - -/* OpenBSD uses uses the traditional NetBSD core file format, even for - ports that use ELF. */ -#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF - -static enum gdb_osabi -ppcobsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_NETBSD_CORE; - - return GDB_OSABI_UNKNOWN; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_ppcobsd_tdep (void); - -void -_initialize_ppcobsd_tdep (void) -{ - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_powerpc, bfd_target_unknown_flavour, - ppcobsd_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_OPENBSD_ELF, - ppcobsd_init_abi); - gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_OPENBSD_ELF, - ppcobsd_init_abi); - - /* Avoid initializing the register offsets again if they were - already initialized by ppcobsd-nat.c. */ - if (ppcobsd_reg_offsets.pc_offset == 0) - { - /* General-purpose registers. */ - ppcobsd_reg_offsets.r0_offset = 0; - ppcobsd_reg_offsets.gpr_size = 4; - ppcobsd_reg_offsets.xr_size = 4; - ppcobsd_reg_offsets.pc_offset = 384; - ppcobsd_reg_offsets.ps_offset = 388; - ppcobsd_reg_offsets.cr_offset = 392; - ppcobsd_reg_offsets.lr_offset = 396; - ppcobsd_reg_offsets.ctr_offset = 400; - ppcobsd_reg_offsets.xer_offset = 404; - ppcobsd_reg_offsets.mq_offset = 408; - - /* Floating-point registers. */ - ppcobsd_reg_offsets.f0_offset = 128; - ppcobsd_reg_offsets.fpscr_offset = -1; - - /* AltiVec registers. */ - ppcobsd_reg_offsets.vr0_offset = 0; - ppcobsd_reg_offsets.vscr_offset = 512; - ppcobsd_reg_offsets.vrsave_offset = 520; - } - - if (ppcobsd_fpreg_offsets.fpscr_offset == 0) - { - /* Floating-point registers. */ - ppcobsd_reg_offsets.f0_offset = 0; - ppcobsd_reg_offsets.fpscr_offset = 256; - ppcobsd_reg_offsets.fpscr_size = 4; - } -} diff --git a/gdb/ppcobsd-tdep.h b/gdb/ppcobsd-tdep.h deleted file mode 100644 index 568e94810e8..00000000000 --- a/gdb/ppcobsd-tdep.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Target-dependent code for OpenBSD/powerpc. - - Copyright (C) 2004-2016 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 PPCOBSD_TDEP_H -#define PPCOBSD_TDEP_H - -struct regset; -struct regcache; - -/* Register offsets for OpenBSD/powerpc. */ -extern struct ppc_reg_offsets ppcobsd_reg_offsets; -extern struct ppc_reg_offsets ppcobsd_fpreg_offsets; - -/* Register sets for OpenBSD/powerpc. */ -extern const struct regset ppcobsd_gregset; -extern const struct regset ppcobsd_fpregset; - - -/* Supply register REGNUM in the general-purpose register set REGSET - from the buffer specified by GREGS and LEN to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -extern void ppcobsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, int regnum, - const void *gregs, size_t len); - -/* Collect register REGNUM in the general-purpose register set - REGSET, from register cache REGCACHE into the buffer specified by - GREGS and LEN. If REGNUM is -1, do this for all registers in - REGSET. */ - -extern void ppcobsd_collect_gregset (const struct regset *regset, - const struct regcache *regcache, - int regnum, void *gregs, size_t len); - -#endif /* ppcobsd-tdep.h */ diff --git a/gdb/sh-nbsd-nat.c b/gdb/sh-nbsd-nat.c new file mode 100644 index 00000000000..b4fd55d991a --- /dev/null +++ b/gdb/sh-nbsd-nat.c @@ -0,0 +1,102 @@ +/* Native-dependent code for NetBSD/sh. + + Copyright (C) 2002-2016 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 "regcache.h" + + +/* 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) + +static void +shnbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + if (regno == -1 || GETREGS_SUPPLIES (get_regcache_arch (regcache), regno)) + { + struct reg inferior_registers; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0) == -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; + } +} + +static void +shnbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regno) +{ + if (regno == -1 || GETREGS_SUPPLIES (get_regcache_arch (regcache), regno)) + { + struct reg inferior_registers; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0) == -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, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &inferior_registers, 0) == -1) + perror_with_name (_("Couldn't set registers")); + + if (regno != -1) + return; + } +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_shnbsd_nat (void); + +void +_initialize_shnbsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = shnbsd_fetch_inferior_registers; + t->to_store_registers = shnbsd_store_inferior_registers; + add_target (t); +} diff --git a/gdb/sh-nbsd-tdep.c b/gdb/sh-nbsd-tdep.c new file mode 100644 index 00000000000..b5c70ef91c3 --- /dev/null +++ b/gdb/sh-nbsd-tdep.c @@ -0,0 +1,101 @@ +/* Target-dependent code for NetBSD/sh. + + Copyright (C) 2002-2016 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 "solib-svr4.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); + + 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); +} + + +/* OpenBSD uses uses the traditional NetBSD core file format, even for + ports that use ELF. */ +#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF + +static enum gdb_osabi +shnbsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_CORE; + + return GDB_OSABI_UNKNOWN; +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_shnbsd_tdep; + +void +_initialize_shnbsd_tdep (void) +{ + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_sh, bfd_target_unknown_flavour, + shnbsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD_ELF, + shnbsd_init_abi); + gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_OPENBSD_ELF, + shnbsd_init_abi); +} diff --git a/gdb/shnbsd-nat.c b/gdb/shnbsd-nat.c deleted file mode 100644 index b4fd55d991a..00000000000 --- a/gdb/shnbsd-nat.c +++ /dev/null @@ -1,102 +0,0 @@ -/* Native-dependent code for NetBSD/sh. - - Copyright (C) 2002-2016 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 "regcache.h" - - -/* 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) - -static void -shnbsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - if (regno == -1 || GETREGS_SUPPLIES (get_regcache_arch (regcache), regno)) - { - struct reg inferior_registers; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0) == -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; - } -} - -static void -shnbsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regno) -{ - if (regno == -1 || GETREGS_SUPPLIES (get_regcache_arch (regcache), regno)) - { - struct reg inferior_registers; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0) == -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, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &inferior_registers, 0) == -1) - perror_with_name (_("Couldn't set registers")); - - if (regno != -1) - return; - } -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_shnbsd_nat (void); - -void -_initialize_shnbsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = shnbsd_fetch_inferior_registers; - t->to_store_registers = shnbsd_store_inferior_registers; - add_target (t); -} diff --git a/gdb/shnbsd-tdep.c b/gdb/shnbsd-tdep.c deleted file mode 100644 index b5c70ef91c3..00000000000 --- a/gdb/shnbsd-tdep.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Target-dependent code for NetBSD/sh. - - Copyright (C) 2002-2016 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 "solib-svr4.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); - - 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); -} - - -/* OpenBSD uses uses the traditional NetBSD core file format, even for - ports that use ELF. */ -#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF - -static enum gdb_osabi -shnbsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_NETBSD_CORE; - - return GDB_OSABI_UNKNOWN; -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_shnbsd_tdep; - -void -_initialize_shnbsd_tdep (void) -{ - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_sh, bfd_target_unknown_flavour, - shnbsd_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD_ELF, - shnbsd_init_abi); - gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_OPENBSD_ELF, - shnbsd_init_abi); -} diff --git a/gdb/sparc-nbsd-nat.c b/gdb/sparc-nbsd-nat.c new file mode 100644 index 00000000000..230be1b7a25 --- /dev/null +++ b/gdb/sparc-nbsd-nat.c @@ -0,0 +1,73 @@ +/* Native-dependent code for NetBSD/sparc. + + Copyright (C) 2002-2016 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 (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); + regcache_raw_supply (regcache, SPARC_O7_REGNUM, &pcb->pcb_pc); + regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, &pcb->pcb_psr); + regcache_raw_supply (regcache, SPARC32_WIM_REGNUM, &pcb->pcb_wim); + regcache_raw_supply (regcache, SPARC32_PC_REGNUM, &pcb->pcb_pc); + + sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparcnbsd_nat (void); + +void +_initialize_sparcnbsd_nat (void) +{ + sparc_gregmap = &sparc32nbsd_gregmap; + sparc_fpregmap = &sparc32_bsd_fpregmap; + + /* We've got nothing to add to the generic SPARC target. */ + add_target (sparc_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 new file mode 100644 index 00000000000..7fa384de649 --- /dev/null +++ b/gdb/sparc-nbsd-tdep.c @@ -0,0 +1,378 @@ +/* Target-dependent code for NetBSD/sparc. + + Copyright (C) 2002-2016 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 "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 + }; + +static void +sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (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); +} + +static void +sparc32nbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + sparc32nbsd_init_abi (info, gdbarch); +} + +void +sparc32nbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + sparc32nbsd_init_abi (info, gdbarch); + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + +static enum gdb_osabi +sparcnbsd_aout_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "a.out-sparc-netbsd") == 0) + return GDB_OSABI_NETBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + +/* OpenBSD uses the traditional NetBSD core file format, even for + ports that use ELF. Therefore, if the default OS ABI is OpenBSD + ELF, we return that instead of NetBSD a.out. This is mainly for + the benfit of OpenBSD/sparc64, which inherits the sniffer below + since we include this file for an OpenBSD/sparc64 target. For + OpenBSD/sparc, the NetBSD a.out OS ABI is probably similar enough + to both the OpenBSD a.out and the OpenBSD ELF OS ABI. */ +#if defined (GDB_OSABI_DEFAULT) && (GDB_OSABI_DEFAULT == GDB_OSABI_OPENBSD_ELF) +#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF +#else +#define GDB_OSABI_NETBSD_CORE GDB_OSABI_NETBSD_AOUT +#endif + +static enum gdb_osabi +sparcnbsd_core_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) + return GDB_OSABI_NETBSD_CORE; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparcnbsd_tdep (void); + +void +_initialize_sparcnbsd_tdep (void) +{ + gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_aout_flavour, + sparcnbsd_aout_osabi_sniffer); + + /* BFD doesn't set a flavour for NetBSD style a.out core files. */ + gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_unknown_flavour, + sparcnbsd_core_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_AOUT, + sparc32nbsd_aout_init_abi); + gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_ELF, + sparc32nbsd_elf_init_abi); +} diff --git a/gdb/sparc-obsd-tdep.c b/gdb/sparc-obsd-tdep.c new file mode 100644 index 00000000000..21c8d6a8148 --- /dev/null +++ b/gdb/sparc-obsd-tdep.c @@ -0,0 +1,258 @@ +/* Target-dependent code for OpenBSD/sparc. + + Copyright (C) 2004-2016 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 "floatformat.h" +#include "frame.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "osabi.h" +#include "regcache.h" +#include "symtab.h" +#include "trad-frame.h" + +#include "obsd-tdep.h" +#include "sparc-tdep.h" +#include "solib-svr4.h" +#include "bsd-uthread.h" + +/* Signal trampolines. */ + +/* The OpenBSD kernel maps the signal trampoline at some random + location in user space, which means that the traditional BSD way of + detecting it won't work. + + The signal trampoline will be mapped at an address that is page + aligned. We recognize the signal trampoline by looking for the + sigreturn system call. */ + +static const int sparc32obsd_page_size = 4096; + +static int +sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) +{ + CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1)); + unsigned long insn; + + if (name) + return 0; + + /* Check for "restore %g0, SYS_sigreturn, %g1". */ + insn = sparc_fetch_instruction (start_pc + 0xec); + if (insn != 0x83e82067) + return 0; + + /* Check for "t ST_SYSCALL". */ + insn = sparc_fetch_instruction (start_pc + 0xf4); + if (insn != 0x91d02000) + return 0; + + return 1; +} + +static struct sparc_frame_cache * +sparc32obsd_sigtramp_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 = get_frame_pc (this_frame); + cache->pc &= ~(sparc32obsd_page_size - 1); + + /* 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 +sparc32obsd_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct sparc_frame_cache *cache = + sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static struct value * +sparc32obsd_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct sparc_frame_cache *cache = + sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); +} + +static int +sparc32obsd_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 (sparc32obsd_pc_in_sigtramp (pc, name)) + return 1; + + return 0; +} +static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + sparc32obsd_sigtramp_frame_this_id, + sparc32obsd_sigtramp_frame_prev_register, + NULL, + sparc32obsd_sigtramp_frame_sniffer +}; + + + +/* Offset wthin the thread structure where we can find %fp and %i7. */ +#define SPARC32OBSD_UTHREAD_FP_OFFSET 128 +#define SPARC32OBSD_UTHREAD_PC_OFFSET 132 + +static void +sparc32obsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; + gdb_byte buf[4]; + + gdb_assert (regnum >= -1); + + fp = read_memory_unsigned_integer (fp_addr, 4, byte_order); + if (regnum == SPARC_SP_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 4, byte_order, fp); + regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf); + + if (regnum == SPARC_SP_REGNUM) + return; + } + + if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM + || regnum == -1) + { + CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; + + i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order); + if (regnum == SPARC32_PC_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 4, byte_order, i7 + 8); + regcache_raw_supply (regcache, SPARC32_PC_REGNUM, buf); + } + if (regnum == SPARC32_NPC_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 4, byte_order, i7 + 12); + regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, buf); + } + + if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM) + return; + } + + sparc_supply_rwindow (regcache, fp, regnum); +} + +static void +sparc32obsd_collect_uthread(const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp; + gdb_byte buf[4]; + + gdb_assert (regnum >= -1); + + if (regnum == SPARC_SP_REGNUM || regnum == -1) + { + CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; + + regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); + write_memory (fp_addr,buf, 4); + } + + if (regnum == SPARC32_PC_REGNUM || regnum == -1) + { + CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; + + regcache_raw_collect (regcache, SPARC32_PC_REGNUM, buf); + i7 = extract_unsigned_integer (buf, 4, byte_order) - 8; + write_memory_unsigned_integer (i7_addr, 4, byte_order, i7); + + if (regnum == SPARC32_PC_REGNUM) + return; + } + + regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 4, byte_order); + sparc_collect_rwindow (regcache, sp, regnum); +} + + +static void +sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* OpenBSD/sparc is very similar to NetBSD/sparc ELF. */ + sparc32nbsd_elf_init_abi (info, gdbarch); + + set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); + + frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind); + + /* OpenBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc32obsd_tdep (void); + +void +_initialize_sparc32obsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF, + sparc32obsd_init_abi); +} diff --git a/gdb/sparc64-fbsd-nat.c b/gdb/sparc64-fbsd-nat.c new file mode 100644 index 00000000000..6c3cb7e2533 --- /dev/null +++ b/gdb/sparc64-fbsd-nat.c @@ -0,0 +1,79 @@ +/* Native-dependent code for FreeBSD/sparc64. + + Copyright (C) 2003-2016 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 "fbsd-nat.h" +#include "sparc64-tdep.h" +#include "sparc-nat.h" + + +/* Support for debugging kernel virtual memory images. */ + +#include +#include + +#include "bsd-kvm.h" + +static int +sparc64fbsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + /* The following is true for FreeBSD 5.4: + + The pcb contains %sp and %pc. Since the register windows are + explicitly flushed, we can find the `local' and `in' registers on + the stack. */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->pcb_sp == 0) + return 0; + + regcache_raw_supply (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); + regcache_raw_supply (regcache, SPARC64_PC_REGNUM, &pcb->pcb_pc); + + /* Synthesize %npc. */ + pcb->pcb_pc += 4; + regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, &pcb->pcb_pc); + + /* Read `local' and `in' registers from the stack. */ + sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc64fbsd_nat (void); + +void +_initialize_sparc64fbsd_nat (void) +{ + struct target_ops *t; + + /* Add some extra features to the generic SPARC target. */ + t = sparc_target (); + fbsd_nat_add_target (t); + + sparc_gregmap = &sparc64fbsd_gregmap; + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (sparc64fbsd_kvm_supply_pcb); +} diff --git a/gdb/sparc64-fbsd-tdep.c b/gdb/sparc64-fbsd-tdep.c new file mode 100644 index 00000000000..27ca52e66a2 --- /dev/null +++ b/gdb/sparc64-fbsd-tdep.c @@ -0,0 +1,252 @@ +/* Target-dependent code for FreeBSD/sparc64. + + Copyright (C) 2003-2016 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 "frame.h" +#include "frame-unwind.h" +#include "gdbcore.h" +#include "osabi.h" +#include "regcache.h" +#include "regset.h" +#include "target.h" +#include "trad-frame.h" + +#include "sparc64-tdep.h" +#include "fbsd-tdep.h" +#include "solib-svr4.h" + +/* From . */ +const struct sparc_gregmap sparc64fbsd_gregmap = +{ + 26 * 8, /* "tstate" */ + 25 * 8, /* %pc */ + 24 * 8, /* %npc */ + 28 * 8, /* %y */ + 16 * 8, /* %fprs */ + -1, + 1 * 8, /* %g1 */ + -1, /* %l0 */ + 8 /* sizeof (%y) */ +}; + + +static void +sparc64fbsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + sparc64_supply_gregset (&sparc64fbsd_gregmap, regcache, regnum, gregs); +} + +static void +sparc64fbsd_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs, size_t len) +{ + sparc64_collect_gregset (&sparc64fbsd_gregmap, regcache, regnum, gregs); +} + +static void +sparc64fbsd_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); +} + +static void +sparc64fbsd_collect_fpregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *fpregs, size_t len) +{ + sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); +} + + +/* Signal trampolines. */ + +static int +sparc64fbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) +{ + return (name && strcmp (name, "__sigtramp") == 0); +} + +static struct sparc_frame_cache * +sparc64fbsd_sigtramp_frame_cache (struct frame_info *this_frame, + void **this_cache) +{ + struct sparc_frame_cache *cache; + CORE_ADDR addr, mcontext_addr, sp; + LONGEST fprs; + int regnum; + + if (*this_cache) + return (struct sparc_frame_cache *) *this_cache; + + cache = sparc_frame_cache (this_frame, this_cache); + gdb_assert (cache == *this_cache); + + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + /* The third argument is a pointer to an instance of `ucontext_t', + which has a member `uc_mcontext' that contains the saved + registers. */ + addr = get_frame_register_unsigned (this_frame, SPARC_O2_REGNUM); + mcontext_addr = addr + 64; + + /* The following registers travel in the `mc_local' slots of + `mcontext_t'. */ + addr = mcontext_addr + 16 * 8; + cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 0 * 8; + cache->saved_regs[SPARC64_FSR_REGNUM].addr = addr + 1 * 8; + + /* The following registers travel in the `mc_in' slots of + `mcontext_t'. */ + addr = mcontext_addr + 24 * 8; + cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 0 * 8; + cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 1 * 8; + cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 2 * 8; + cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 4 * 8; + + /* The `global' and `out' registers travel in the `mc_global' and + `mc_out' slots of `mcontext_t', except for %g0. Since %g0 is + always zero, keep the identity encoding. */ + for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 8; + regnum <= SPARC_O7_REGNUM; regnum++, addr += 8) + cache->saved_regs[regnum].addr = addr; + + /* The `local' and `in' registers have been saved in the register + save area. */ + addr = cache->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) + cache->saved_regs[regnum].addr = addr; + + /* The floating-point registers are only saved if the FEF bit in + %fprs has been set. */ + +#define FPRS_FEF (1 << 2) + + addr = cache->saved_regs[SPARC64_FPRS_REGNUM].addr; + fprs = get_frame_memory_unsigned (this_frame, addr, 8); + if (fprs & FPRS_FEF) + { + for (regnum = SPARC_F0_REGNUM, addr = mcontext_addr + 32 * 8; + regnum <= SPARC_F31_REGNUM; regnum++, addr += 4) + cache->saved_regs[regnum].addr = addr; + + for (regnum = SPARC64_F32_REGNUM; + regnum <= SPARC64_F62_REGNUM; regnum++, addr += 8) + cache->saved_regs[regnum].addr = addr; + } + + return cache; +} + +static void +sparc64fbsd_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct sparc_frame_cache *cache = + sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static struct value * +sparc64fbsd_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct sparc_frame_cache *cache = + sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache); + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); +} + +static int +sparc64fbsd_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 (sparc64fbsd_pc_in_sigtramp (pc, name)) + return 1; + + return 0; +} + +static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + sparc64fbsd_sigtramp_frame_this_id, + sparc64fbsd_sigtramp_frame_prev_register, + NULL, + sparc64fbsd_sigtramp_frame_sniffer +}; + + +static const struct regset sparc64fbsd_gregset = + { + NULL, sparc64fbsd_supply_gregset, sparc64fbsd_collect_gregset + }; + +static const struct regset sparc64fbsd_fpregset = + { + NULL, sparc64fbsd_supply_fpregset, sparc64fbsd_collect_fpregset + }; + +static void +sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Generic FreeBSD support. */ + fbsd_init_abi (info, gdbarch); + + tdep->gregset = &sparc64fbsd_gregset; + tdep->sizeof_gregset = 256; + + tdep->fpregset = &sparc64fbsd_fpregset; + tdep->sizeof_fpregset = 272; + + frame_unwind_append_unwinder (gdbarch, &sparc64fbsd_sigtramp_frame_unwind); + + sparc64_init_abi (info, gdbarch); + + /* FreeBSD/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); +} + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc64fbsd_tdep (void); + +void +_initialize_sparc64fbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, + GDB_OSABI_FREEBSD_ELF, sparc64fbsd_init_abi); +} diff --git a/gdb/sparc64-nbsd-nat.c b/gdb/sparc64-nbsd-nat.c new file mode 100644 index 00000000000..696bdcb9368 --- /dev/null +++ b/gdb/sparc64-nbsd-nat.c @@ -0,0 +1,189 @@ +/* Native-dependent code for NetBSD/sparc64. + + Copyright (C) 2003-2016 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 (get_regcache_arch (regcache)) == 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 (get_regcache_arch (regcache)) == 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 (get_regcache_arch (regcache)) == 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 (get_regcache_arch (regcache)) == 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 (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); + regcache_raw_supply (regcache, SPARC64_PC_REGNUM, &pcb->pcb_pc); + + state = pcb->pcb_pstate << 8 | pcb->pcb_cwp; + regcache_raw_supply (regcache, SPARC64_STATE_REGNUM, &state); + + sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc64nbsd_nat (void); + +void +_initialize_sparc64nbsd_nat (void) +{ + 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; + + /* We've got nothing to add to the generic SPARC target. */ + add_target (sparc_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 new file mode 100644 index 00000000000..1abb721e2e0 --- /dev/null +++ b/gdb/sparc64-nbsd-tdep.c @@ -0,0 +1,280 @@ +/* Target-dependent code for NetBSD/sparc64. + + Copyright (C) 2002-2016 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); + + 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); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc64nbsd_tdep (void); + +void +_initialize_sparc64nbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, + GDB_OSABI_NETBSD_ELF, sparc64nbsd_init_abi); +} diff --git a/gdb/sparc64-obsd-nat.c b/gdb/sparc64-obsd-nat.c new file mode 100644 index 00000000000..02ce9b5616c --- /dev/null +++ b/gdb/sparc64-obsd-nat.c @@ -0,0 +1,131 @@ +/* Native-dependent code for OpenBSD/sparc64. + + Copyright (C) 2003-2016 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" +#include "obsd-nat.h" + +/* Determine whether `gregset_t' contains register REGNUM. */ + +static int +sparc64obsd_gregset_supplies_p (struct gdbarch *gdbarch, int 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 +sparc64obsd_fpregset_supplies_p (struct gdbarch *gdbarch, int 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 +sparc64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + u_int64_t state; + int regnum; + + /* The following is true for OpenBSD 3.0: + + 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 (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); + regcache_raw_supply (regcache, SPARC64_PC_REGNUM, &pcb->pcb_pc); + + state = pcb->pcb_pstate << 8 | pcb->pcb_cwp; + regcache_raw_supply (regcache, SPARC64_STATE_REGNUM, &state); + + sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc64obsd_nat (void); + +void +_initialize_sparc64obsd_nat (void) +{ + sparc_supply_gregset = sparc64_supply_gregset; + sparc_collect_gregset = sparc64_collect_gregset; + sparc_supply_fpregset = sparc64_supply_fpregset; + sparc_collect_fpregset = sparc64_collect_fpregset; + sparc_gregset_supplies_p = sparc64obsd_gregset_supplies_p; + sparc_fpregset_supplies_p = sparc64obsd_fpregset_supplies_p; + + sparc_gregmap = &sparc64nbsd_gregmap; + sparc_fpregmap = &sparc64_bsd_fpregmap; + + /* Add some extra features to the generic SPARC target. */ + obsd_add_target (sparc_target ()); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (sparc64obsd_supply_pcb); +} diff --git a/gdb/sparc64-obsd-tdep.c b/gdb/sparc64-obsd-tdep.c new file mode 100644 index 00000000000..a90ae1dc103 --- /dev/null +++ b/gdb/sparc64-obsd-tdep.c @@ -0,0 +1,452 @@ +/* Target-dependent code for OpenBSD/sparc64. + + Copyright (C) 2004-2016 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 "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 "trad-frame.h" + +#include "obsd-tdep.h" +#include "sparc64-tdep.h" +#include "solib-svr4.h" +#include "bsd-uthread.h" + +/* Older OpenBSD versions used the traditional NetBSD core file + format, even for ports that use ELF. These core files don't use + multiple register sets. Instead, the general-purpose and + floating-point registers are lumped together in a single section. + Unlike on NetBSD, OpenBSD uses a different layout for its + general-purpose registers than the layout used for ptrace(2). + + Newer OpenBSD versions use ELF core files. Here the register sets + match the ptrace(2) layout. */ + +/* From . */ +const struct sparc_gregmap sparc64obsd_gregmap = +{ + 0 * 8, /* "tstate" */ + 1 * 8, /* %pc */ + 2 * 8, /* %npc */ + 3 * 8, /* %y */ + -1, /* %fprs */ + -1, + 5 * 8, /* %g1 */ + 20 * 8, /* %l0 */ + 4 /* sizeof (%y) */ +}; + +const struct sparc_gregmap sparc64obsd_core_gregmap = +{ + 0 * 8, /* "tstate" */ + 1 * 8, /* %pc */ + 2 * 8, /* %npc */ + 3 * 8, /* %y */ + -1, /* %fprs */ + -1, + 7 * 8, /* %g1 */ + 22 * 8, /* %l0 */ + 4 /* sizeof (%y) */ +}; + +static void +sparc64obsd_supply_gregset (const struct regset *regset, + struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + const void *fpregs = (char *)gregs + 288; + + if (len < 832) + { + sparc64_supply_gregset (&sparc64obsd_gregmap, regcache, regnum, gregs); + return; + } + + sparc64_supply_gregset (&sparc64obsd_core_gregmap, regcache, regnum, gregs); + sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); +} + +static void +sparc64obsd_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. */ + +/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page + in virtual memory. The randomness makes it somewhat tricky to + detect it, but fortunately we can rely on the fact that the start + of the sigtramp routine is page-aligned. We recognize the + trampoline by looking for the code that invokes the sigreturn + system call. The offset where we can find that code varies from + release to release. + + By the way, the mapping mentioned above is read-only, so you cannot + place a breakpoint in the signal trampoline. */ + +/* Default page size. */ +static const int sparc64obsd_page_size = 8192; + +/* Offset for sigreturn(2). */ +static const int sparc64obsd_sigreturn_offset[] = { + 0xf0, /* OpenBSD 3.8 */ + 0xec, /* OpenBSD 3.6 */ + 0xe8, /* OpenBSD 3.2 */ + -1 +}; + +static int +sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) +{ + CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1)); + unsigned long insn; + const int *offset; + + if (name) + return 0; + + for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++) + { + /* Check for "restore %g0, SYS_sigreturn, %g1". */ + insn = sparc_fetch_instruction (start_pc + *offset); + if (insn != 0x83e82067) + continue; + + /* Check for "t ST_SYSCALL". */ + insn = sparc_fetch_instruction (start_pc + *offset + 8); + if (insn != 0x91d02000) + continue; + + return 1; + } + + return 0; +} + +static struct sparc_frame_cache * +sparc64obsd_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 = get_frame_pc (this_frame); + cache->pc &= ~(sparc64obsd_page_size - 1); + + /* 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 + 16; + cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame); + + return cache; +} + +static void +sparc64obsd_frame_this_id (struct frame_info *this_frame, void **this_cache, + struct frame_id *this_id) +{ + struct sparc_frame_cache *cache = + sparc64obsd_frame_cache (this_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static struct value * +sparc64obsd_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct sparc_frame_cache *cache = + sparc64obsd_frame_cache (this_frame, this_cache); + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); +} + +static int +sparc64obsd_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 (sparc64obsd_pc_in_sigtramp (pc, name)) + return 1; + + return 0; +} + +static const struct frame_unwind sparc64obsd_frame_unwind = +{ + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + sparc64obsd_frame_this_id, + sparc64obsd_frame_prev_register, + NULL, + sparc64obsd_sigtramp_frame_sniffer +}; + +/* Kernel debugging support. */ + +static struct sparc_frame_cache * +sparc64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) +{ + struct sparc_frame_cache *cache; + CORE_ADDR sp, trapframe_addr; + int regnum; + + if (*this_cache) + return (struct sparc_frame_cache *) *this_cache; + + cache = sparc_frame_cache (this_frame, this_cache); + gdb_assert (cache == *this_cache); + + sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM); + trapframe_addr = sp + BIAS + 176; + + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr; + cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8; + cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16; + + for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++) + cache->saved_regs[regnum].addr = + trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8; + + return cache; +} + +static void +sparc64obsd_trapframe_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + struct sparc_frame_cache *cache = + sparc64obsd_trapframe_cache (this_frame, this_cache); + + (*this_id) = frame_id_build (cache->base, cache->pc); +} + +static struct value * +sparc64obsd_trapframe_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct sparc_frame_cache *cache = + sparc64obsd_trapframe_cache (this_frame, this_cache); + + return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); +} + +static int +sparc64obsd_trapframe_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + CORE_ADDR pc; + ULONGEST pstate; + const char *name; + + /* Check whether we are in privileged mode, and bail out if we're not. */ + pstate = get_frame_register_unsigned (this_frame, SPARC64_PSTATE_REGNUM); + if ((pstate & SPARC64_PSTATE_PRIV) == 0) + return 0; + + pc = get_frame_address_in_block (this_frame); + find_pc_partial_function (pc, &name, NULL, NULL); + if (name && strcmp (name, "Lslowtrap_reenter") == 0) + return 1; + + return 0; +} + +static const struct frame_unwind sparc64obsd_trapframe_unwind = +{ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + sparc64obsd_trapframe_this_id, + sparc64obsd_trapframe_prev_register, + NULL, + sparc64obsd_trapframe_sniffer +}; + + +/* Threads support. */ + +/* Offset wthin the thread structure where we can find %fp and %i7. */ +#define SPARC64OBSD_UTHREAD_FP_OFFSET 232 +#define SPARC64OBSD_UTHREAD_PC_OFFSET 240 + +static void +sparc64obsd_supply_uthread (struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR fp, fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET; + gdb_byte buf[8]; + + gdb_assert (regnum >= -1); + + fp = read_memory_unsigned_integer (fp_addr, 8, byte_order); + if (regnum == SPARC_SP_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 8, byte_order, fp); + regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf); + + if (regnum == SPARC_SP_REGNUM) + return; + } + + if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM + || regnum == -1) + { + CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET; + + i7 = read_memory_unsigned_integer (i7_addr, 8, byte_order); + if (regnum == SPARC64_PC_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 8, byte_order, i7 + 8); + regcache_raw_supply (regcache, SPARC64_PC_REGNUM, buf); + } + if (regnum == SPARC64_NPC_REGNUM || regnum == -1) + { + store_unsigned_integer (buf, 8, byte_order, i7 + 12); + regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, buf); + } + + if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM) + return; + } + + sparc_supply_rwindow (regcache, fp, regnum); +} + +static void +sparc64obsd_collect_uthread(const struct regcache *regcache, + int regnum, CORE_ADDR addr) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR sp; + gdb_byte buf[8]; + + gdb_assert (regnum >= -1); + + if (regnum == SPARC_SP_REGNUM || regnum == -1) + { + CORE_ADDR fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET; + + regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); + write_memory (fp_addr,buf, 8); + } + + if (regnum == SPARC64_PC_REGNUM || regnum == -1) + { + CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET; + + regcache_raw_collect (regcache, SPARC64_PC_REGNUM, buf); + i7 = extract_unsigned_integer (buf, 8, byte_order) - 8; + write_memory_unsigned_integer (i7_addr, 8, byte_order, i7); + + if (regnum == SPARC64_PC_REGNUM) + return; + } + + regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 8, byte_order); + sparc_collect_rwindow (regcache, sp, regnum); +} + + +static const struct regset sparc64obsd_gregset = + { + NULL, sparc64obsd_supply_gregset, NULL + }; + +static const struct regset sparc64obsd_fpregset = + { + NULL, sparc64obsd_supply_fpregset, NULL + }; + +static void +sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + tdep->gregset = &sparc64obsd_gregset; + tdep->sizeof_gregset = 288; + tdep->fpregset = &sparc64obsd_fpregset; + tdep->sizeof_fpregset = 272; + + /* Make sure we can single-step "new" syscalls. */ + tdep->step_trap = sparcnbsd_step_trap; + + frame_unwind_append_unwinder (gdbarch, &sparc64obsd_frame_unwind); + frame_unwind_append_unwinder (gdbarch, &sparc64obsd_trapframe_unwind); + + sparc64_init_abi (info, gdbarch); + obsd_init_abi (info, gdbarch); + + /* OpenBSD/sparc64 has SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_lp64_fetch_link_map_offsets); + set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); + + /* OpenBSD provides a user-level threads implementation. */ + bsd_uthread_set_supply_uthread (gdbarch, sparc64obsd_supply_uthread); + bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_sparc64obsd_tdep (void); + +void +_initialize_sparc64obsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, + GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi); +} diff --git a/gdb/sparc64-tdep.h b/gdb/sparc64-tdep.h index 9140264ec54..eb925df65a8 100644 --- a/gdb/sparc64-tdep.h +++ b/gdb/sparc64-tdep.h @@ -119,12 +119,12 @@ extern const struct sparc_fpregmap sparc64_sol2_fpregmap; extern void sparc64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch); -/* Variables exported from sparc64fbsd-tdep.c. */ +/* Variables exported from sparc64-fbsd-tdep.c. */ /* Register offsets for FreeBSD/sparc64. */ extern const struct sparc_gregmap sparc64fbsd_gregmap; -/* Functions and variables exported from sparc64nbsd-tdep.c. */ +/* Functions and variables exported from sparc64-nbsd-tdep.c. */ /* Register offsets for NetBSD/sparc64. */ extern const struct sparc_gregmap sparc64nbsd_gregmap; diff --git a/gdb/sparc64fbsd-nat.c b/gdb/sparc64fbsd-nat.c deleted file mode 100644 index 6c3cb7e2533..00000000000 --- a/gdb/sparc64fbsd-nat.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Native-dependent code for FreeBSD/sparc64. - - Copyright (C) 2003-2016 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 "fbsd-nat.h" -#include "sparc64-tdep.h" -#include "sparc-nat.h" - - -/* Support for debugging kernel virtual memory images. */ - -#include -#include - -#include "bsd-kvm.h" - -static int -sparc64fbsd_kvm_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - /* The following is true for FreeBSD 5.4: - - The pcb contains %sp and %pc. Since the register windows are - explicitly flushed, we can find the `local' and `in' registers on - the stack. */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->pcb_sp == 0) - return 0; - - regcache_raw_supply (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); - regcache_raw_supply (regcache, SPARC64_PC_REGNUM, &pcb->pcb_pc); - - /* Synthesize %npc. */ - pcb->pcb_pc += 4; - regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, &pcb->pcb_pc); - - /* Read `local' and `in' registers from the stack. */ - sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparc64fbsd_nat (void); - -void -_initialize_sparc64fbsd_nat (void) -{ - struct target_ops *t; - - /* Add some extra features to the generic SPARC target. */ - t = sparc_target (); - fbsd_nat_add_target (t); - - sparc_gregmap = &sparc64fbsd_gregmap; - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (sparc64fbsd_kvm_supply_pcb); -} diff --git a/gdb/sparc64fbsd-tdep.c b/gdb/sparc64fbsd-tdep.c deleted file mode 100644 index 27ca52e66a2..00000000000 --- a/gdb/sparc64fbsd-tdep.c +++ /dev/null @@ -1,252 +0,0 @@ -/* Target-dependent code for FreeBSD/sparc64. - - Copyright (C) 2003-2016 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 "frame.h" -#include "frame-unwind.h" -#include "gdbcore.h" -#include "osabi.h" -#include "regcache.h" -#include "regset.h" -#include "target.h" -#include "trad-frame.h" - -#include "sparc64-tdep.h" -#include "fbsd-tdep.h" -#include "solib-svr4.h" - -/* From . */ -const struct sparc_gregmap sparc64fbsd_gregmap = -{ - 26 * 8, /* "tstate" */ - 25 * 8, /* %pc */ - 24 * 8, /* %npc */ - 28 * 8, /* %y */ - 16 * 8, /* %fprs */ - -1, - 1 * 8, /* %g1 */ - -1, /* %l0 */ - 8 /* sizeof (%y) */ -}; - - -static void -sparc64fbsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - sparc64_supply_gregset (&sparc64fbsd_gregmap, regcache, regnum, gregs); -} - -static void -sparc64fbsd_collect_gregset (const struct regset *regset, - const struct regcache *regcache, - int regnum, void *gregs, size_t len) -{ - sparc64_collect_gregset (&sparc64fbsd_gregmap, regcache, regnum, gregs); -} - -static void -sparc64fbsd_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); -} - -static void -sparc64fbsd_collect_fpregset (const struct regset *regset, - const struct regcache *regcache, - int regnum, void *fpregs, size_t len) -{ - sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); -} - - -/* Signal trampolines. */ - -static int -sparc64fbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) -{ - return (name && strcmp (name, "__sigtramp") == 0); -} - -static struct sparc_frame_cache * -sparc64fbsd_sigtramp_frame_cache (struct frame_info *this_frame, - void **this_cache) -{ - struct sparc_frame_cache *cache; - CORE_ADDR addr, mcontext_addr, sp; - LONGEST fprs; - int regnum; - - if (*this_cache) - return (struct sparc_frame_cache *) *this_cache; - - cache = sparc_frame_cache (this_frame, this_cache); - gdb_assert (cache == *this_cache); - - cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); - - /* The third argument is a pointer to an instance of `ucontext_t', - which has a member `uc_mcontext' that contains the saved - registers. */ - addr = get_frame_register_unsigned (this_frame, SPARC_O2_REGNUM); - mcontext_addr = addr + 64; - - /* The following registers travel in the `mc_local' slots of - `mcontext_t'. */ - addr = mcontext_addr + 16 * 8; - cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 0 * 8; - cache->saved_regs[SPARC64_FSR_REGNUM].addr = addr + 1 * 8; - - /* The following registers travel in the `mc_in' slots of - `mcontext_t'. */ - addr = mcontext_addr + 24 * 8; - cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 0 * 8; - cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 1 * 8; - cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 2 * 8; - cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 4 * 8; - - /* The `global' and `out' registers travel in the `mc_global' and - `mc_out' slots of `mcontext_t', except for %g0. Since %g0 is - always zero, keep the identity encoding. */ - for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 8; - regnum <= SPARC_O7_REGNUM; regnum++, addr += 8) - cache->saved_regs[regnum].addr = addr; - - /* The `local' and `in' registers have been saved in the register - save area. */ - addr = cache->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) - cache->saved_regs[regnum].addr = addr; - - /* The floating-point registers are only saved if the FEF bit in - %fprs has been set. */ - -#define FPRS_FEF (1 << 2) - - addr = cache->saved_regs[SPARC64_FPRS_REGNUM].addr; - fprs = get_frame_memory_unsigned (this_frame, addr, 8); - if (fprs & FPRS_FEF) - { - for (regnum = SPARC_F0_REGNUM, addr = mcontext_addr + 32 * 8; - regnum <= SPARC_F31_REGNUM; regnum++, addr += 4) - cache->saved_regs[regnum].addr = addr; - - for (regnum = SPARC64_F32_REGNUM; - regnum <= SPARC64_F62_REGNUM; regnum++, addr += 8) - cache->saved_regs[regnum].addr = addr; - } - - return cache; -} - -static void -sparc64fbsd_sigtramp_frame_this_id (struct frame_info *this_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct sparc_frame_cache *cache = - sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache); - - (*this_id) = frame_id_build (cache->base, cache->pc); -} - -static struct value * -sparc64fbsd_sigtramp_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct sparc_frame_cache *cache = - sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache); - - return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); -} - -static int -sparc64fbsd_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 (sparc64fbsd_pc_in_sigtramp (pc, name)) - return 1; - - return 0; -} - -static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind = -{ - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - sparc64fbsd_sigtramp_frame_this_id, - sparc64fbsd_sigtramp_frame_prev_register, - NULL, - sparc64fbsd_sigtramp_frame_sniffer -}; - - -static const struct regset sparc64fbsd_gregset = - { - NULL, sparc64fbsd_supply_gregset, sparc64fbsd_collect_gregset - }; - -static const struct regset sparc64fbsd_fpregset = - { - NULL, sparc64fbsd_supply_fpregset, sparc64fbsd_collect_fpregset - }; - -static void -sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - /* Generic FreeBSD support. */ - fbsd_init_abi (info, gdbarch); - - tdep->gregset = &sparc64fbsd_gregset; - tdep->sizeof_gregset = 256; - - tdep->fpregset = &sparc64fbsd_fpregset; - tdep->sizeof_fpregset = 272; - - frame_unwind_append_unwinder (gdbarch, &sparc64fbsd_sigtramp_frame_unwind); - - sparc64_init_abi (info, gdbarch); - - /* FreeBSD/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); -} - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparc64fbsd_tdep (void); - -void -_initialize_sparc64fbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, - GDB_OSABI_FREEBSD_ELF, sparc64fbsd_init_abi); -} diff --git a/gdb/sparc64nbsd-nat.c b/gdb/sparc64nbsd-nat.c deleted file mode 100644 index 696bdcb9368..00000000000 --- a/gdb/sparc64nbsd-nat.c +++ /dev/null @@ -1,189 +0,0 @@ -/* Native-dependent code for NetBSD/sparc64. - - Copyright (C) 2003-2016 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 (get_regcache_arch (regcache)) == 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 (get_regcache_arch (regcache)) == 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 (get_regcache_arch (regcache)) == 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 (get_regcache_arch (regcache)) == 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 (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); - regcache_raw_supply (regcache, SPARC64_PC_REGNUM, &pcb->pcb_pc); - - state = pcb->pcb_pstate << 8 | pcb->pcb_cwp; - regcache_raw_supply (regcache, SPARC64_STATE_REGNUM, &state); - - sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparc64nbsd_nat (void); - -void -_initialize_sparc64nbsd_nat (void) -{ - 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; - - /* We've got nothing to add to the generic SPARC target. */ - add_target (sparc_target ()); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (sparc64nbsd_supply_pcb); -} diff --git a/gdb/sparc64nbsd-tdep.c b/gdb/sparc64nbsd-tdep.c deleted file mode 100644 index 1abb721e2e0..00000000000 --- a/gdb/sparc64nbsd-tdep.c +++ /dev/null @@ -1,280 +0,0 @@ -/* Target-dependent code for NetBSD/sparc64. - - Copyright (C) 2002-2016 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); - - 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); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparc64nbsd_tdep (void); - -void -_initialize_sparc64nbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, - GDB_OSABI_NETBSD_ELF, sparc64nbsd_init_abi); -} diff --git a/gdb/sparc64obsd-nat.c b/gdb/sparc64obsd-nat.c deleted file mode 100644 index 02ce9b5616c..00000000000 --- a/gdb/sparc64obsd-nat.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Native-dependent code for OpenBSD/sparc64. - - Copyright (C) 2003-2016 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" -#include "obsd-nat.h" - -/* Determine whether `gregset_t' contains register REGNUM. */ - -static int -sparc64obsd_gregset_supplies_p (struct gdbarch *gdbarch, int 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 -sparc64obsd_fpregset_supplies_p (struct gdbarch *gdbarch, int 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 -sparc64obsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - u_int64_t state; - int regnum; - - /* The following is true for OpenBSD 3.0: - - 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 (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); - regcache_raw_supply (regcache, SPARC64_PC_REGNUM, &pcb->pcb_pc); - - state = pcb->pcb_pstate << 8 | pcb->pcb_cwp; - regcache_raw_supply (regcache, SPARC64_STATE_REGNUM, &state); - - sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparc64obsd_nat (void); - -void -_initialize_sparc64obsd_nat (void) -{ - sparc_supply_gregset = sparc64_supply_gregset; - sparc_collect_gregset = sparc64_collect_gregset; - sparc_supply_fpregset = sparc64_supply_fpregset; - sparc_collect_fpregset = sparc64_collect_fpregset; - sparc_gregset_supplies_p = sparc64obsd_gregset_supplies_p; - sparc_fpregset_supplies_p = sparc64obsd_fpregset_supplies_p; - - sparc_gregmap = &sparc64nbsd_gregmap; - sparc_fpregmap = &sparc64_bsd_fpregmap; - - /* Add some extra features to the generic SPARC target. */ - obsd_add_target (sparc_target ()); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (sparc64obsd_supply_pcb); -} diff --git a/gdb/sparc64obsd-tdep.c b/gdb/sparc64obsd-tdep.c deleted file mode 100644 index a90ae1dc103..00000000000 --- a/gdb/sparc64obsd-tdep.c +++ /dev/null @@ -1,452 +0,0 @@ -/* Target-dependent code for OpenBSD/sparc64. - - Copyright (C) 2004-2016 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 "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 "trad-frame.h" - -#include "obsd-tdep.h" -#include "sparc64-tdep.h" -#include "solib-svr4.h" -#include "bsd-uthread.h" - -/* Older OpenBSD versions used the traditional NetBSD core file - format, even for ports that use ELF. These core files don't use - multiple register sets. Instead, the general-purpose and - floating-point registers are lumped together in a single section. - Unlike on NetBSD, OpenBSD uses a different layout for its - general-purpose registers than the layout used for ptrace(2). - - Newer OpenBSD versions use ELF core files. Here the register sets - match the ptrace(2) layout. */ - -/* From . */ -const struct sparc_gregmap sparc64obsd_gregmap = -{ - 0 * 8, /* "tstate" */ - 1 * 8, /* %pc */ - 2 * 8, /* %npc */ - 3 * 8, /* %y */ - -1, /* %fprs */ - -1, - 5 * 8, /* %g1 */ - 20 * 8, /* %l0 */ - 4 /* sizeof (%y) */ -}; - -const struct sparc_gregmap sparc64obsd_core_gregmap = -{ - 0 * 8, /* "tstate" */ - 1 * 8, /* %pc */ - 2 * 8, /* %npc */ - 3 * 8, /* %y */ - -1, /* %fprs */ - -1, - 7 * 8, /* %g1 */ - 22 * 8, /* %l0 */ - 4 /* sizeof (%y) */ -}; - -static void -sparc64obsd_supply_gregset (const struct regset *regset, - struct regcache *regcache, - int regnum, const void *gregs, size_t len) -{ - const void *fpregs = (char *)gregs + 288; - - if (len < 832) - { - sparc64_supply_gregset (&sparc64obsd_gregmap, regcache, regnum, gregs); - return; - } - - sparc64_supply_gregset (&sparc64obsd_core_gregmap, regcache, regnum, gregs); - sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs); -} - -static void -sparc64obsd_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. */ - -/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page - in virtual memory. The randomness makes it somewhat tricky to - detect it, but fortunately we can rely on the fact that the start - of the sigtramp routine is page-aligned. We recognize the - trampoline by looking for the code that invokes the sigreturn - system call. The offset where we can find that code varies from - release to release. - - By the way, the mapping mentioned above is read-only, so you cannot - place a breakpoint in the signal trampoline. */ - -/* Default page size. */ -static const int sparc64obsd_page_size = 8192; - -/* Offset for sigreturn(2). */ -static const int sparc64obsd_sigreturn_offset[] = { - 0xf0, /* OpenBSD 3.8 */ - 0xec, /* OpenBSD 3.6 */ - 0xe8, /* OpenBSD 3.2 */ - -1 -}; - -static int -sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) -{ - CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1)); - unsigned long insn; - const int *offset; - - if (name) - return 0; - - for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++) - { - /* Check for "restore %g0, SYS_sigreturn, %g1". */ - insn = sparc_fetch_instruction (start_pc + *offset); - if (insn != 0x83e82067) - continue; - - /* Check for "t ST_SYSCALL". */ - insn = sparc_fetch_instruction (start_pc + *offset + 8); - if (insn != 0x91d02000) - continue; - - return 1; - } - - return 0; -} - -static struct sparc_frame_cache * -sparc64obsd_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 = get_frame_pc (this_frame); - cache->pc &= ~(sparc64obsd_page_size - 1); - - /* 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 + 16; - cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, this_frame); - - return cache; -} - -static void -sparc64obsd_frame_this_id (struct frame_info *this_frame, void **this_cache, - struct frame_id *this_id) -{ - struct sparc_frame_cache *cache = - sparc64obsd_frame_cache (this_frame, this_cache); - - (*this_id) = frame_id_build (cache->base, cache->pc); -} - -static struct value * -sparc64obsd_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct sparc_frame_cache *cache = - sparc64obsd_frame_cache (this_frame, this_cache); - - return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); -} - -static int -sparc64obsd_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 (sparc64obsd_pc_in_sigtramp (pc, name)) - return 1; - - return 0; -} - -static const struct frame_unwind sparc64obsd_frame_unwind = -{ - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - sparc64obsd_frame_this_id, - sparc64obsd_frame_prev_register, - NULL, - sparc64obsd_sigtramp_frame_sniffer -}; - -/* Kernel debugging support. */ - -static struct sparc_frame_cache * -sparc64obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache) -{ - struct sparc_frame_cache *cache; - CORE_ADDR sp, trapframe_addr; - int regnum; - - if (*this_cache) - return (struct sparc_frame_cache *) *this_cache; - - cache = sparc_frame_cache (this_frame, this_cache); - gdb_assert (cache == *this_cache); - - sp = get_frame_register_unsigned (this_frame, SPARC_SP_REGNUM); - trapframe_addr = sp + BIAS + 176; - - cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); - - cache->saved_regs[SPARC64_STATE_REGNUM].addr = trapframe_addr; - cache->saved_regs[SPARC64_PC_REGNUM].addr = trapframe_addr + 8; - cache->saved_regs[SPARC64_NPC_REGNUM].addr = trapframe_addr + 16; - - for (regnum = SPARC_G0_REGNUM; regnum <= SPARC_I7_REGNUM; regnum++) - cache->saved_regs[regnum].addr = - trapframe_addr + 48 + (regnum - SPARC_G0_REGNUM) * 8; - - return cache; -} - -static void -sparc64obsd_trapframe_this_id (struct frame_info *this_frame, - void **this_cache, struct frame_id *this_id) -{ - struct sparc_frame_cache *cache = - sparc64obsd_trapframe_cache (this_frame, this_cache); - - (*this_id) = frame_id_build (cache->base, cache->pc); -} - -static struct value * -sparc64obsd_trapframe_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct sparc_frame_cache *cache = - sparc64obsd_trapframe_cache (this_frame, this_cache); - - return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); -} - -static int -sparc64obsd_trapframe_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_cache) -{ - CORE_ADDR pc; - ULONGEST pstate; - const char *name; - - /* Check whether we are in privileged mode, and bail out if we're not. */ - pstate = get_frame_register_unsigned (this_frame, SPARC64_PSTATE_REGNUM); - if ((pstate & SPARC64_PSTATE_PRIV) == 0) - return 0; - - pc = get_frame_address_in_block (this_frame); - find_pc_partial_function (pc, &name, NULL, NULL); - if (name && strcmp (name, "Lslowtrap_reenter") == 0) - return 1; - - return 0; -} - -static const struct frame_unwind sparc64obsd_trapframe_unwind = -{ - NORMAL_FRAME, - default_frame_unwind_stop_reason, - sparc64obsd_trapframe_this_id, - sparc64obsd_trapframe_prev_register, - NULL, - sparc64obsd_trapframe_sniffer -}; - - -/* Threads support. */ - -/* Offset wthin the thread structure where we can find %fp and %i7. */ -#define SPARC64OBSD_UTHREAD_FP_OFFSET 232 -#define SPARC64OBSD_UTHREAD_PC_OFFSET 240 - -static void -sparc64obsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR fp, fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET; - gdb_byte buf[8]; - - gdb_assert (regnum >= -1); - - fp = read_memory_unsigned_integer (fp_addr, 8, byte_order); - if (regnum == SPARC_SP_REGNUM || regnum == -1) - { - store_unsigned_integer (buf, 8, byte_order, fp); - regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf); - - if (regnum == SPARC_SP_REGNUM) - return; - } - - if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM - || regnum == -1) - { - CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET; - - i7 = read_memory_unsigned_integer (i7_addr, 8, byte_order); - if (regnum == SPARC64_PC_REGNUM || regnum == -1) - { - store_unsigned_integer (buf, 8, byte_order, i7 + 8); - regcache_raw_supply (regcache, SPARC64_PC_REGNUM, buf); - } - if (regnum == SPARC64_NPC_REGNUM || regnum == -1) - { - store_unsigned_integer (buf, 8, byte_order, i7 + 12); - regcache_raw_supply (regcache, SPARC64_NPC_REGNUM, buf); - } - - if (regnum == SPARC64_PC_REGNUM || regnum == SPARC64_NPC_REGNUM) - return; - } - - sparc_supply_rwindow (regcache, fp, regnum); -} - -static void -sparc64obsd_collect_uthread(const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp; - gdb_byte buf[8]; - - gdb_assert (regnum >= -1); - - if (regnum == SPARC_SP_REGNUM || regnum == -1) - { - CORE_ADDR fp_addr = addr + SPARC64OBSD_UTHREAD_FP_OFFSET; - - regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); - write_memory (fp_addr,buf, 8); - } - - if (regnum == SPARC64_PC_REGNUM || regnum == -1) - { - CORE_ADDR i7, i7_addr = addr + SPARC64OBSD_UTHREAD_PC_OFFSET; - - regcache_raw_collect (regcache, SPARC64_PC_REGNUM, buf); - i7 = extract_unsigned_integer (buf, 8, byte_order) - 8; - write_memory_unsigned_integer (i7_addr, 8, byte_order, i7); - - if (regnum == SPARC64_PC_REGNUM) - return; - } - - regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); - sp = extract_unsigned_integer (buf, 8, byte_order); - sparc_collect_rwindow (regcache, sp, regnum); -} - - -static const struct regset sparc64obsd_gregset = - { - NULL, sparc64obsd_supply_gregset, NULL - }; - -static const struct regset sparc64obsd_fpregset = - { - NULL, sparc64obsd_supply_fpregset, NULL - }; - -static void -sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - tdep->gregset = &sparc64obsd_gregset; - tdep->sizeof_gregset = 288; - tdep->fpregset = &sparc64obsd_fpregset; - tdep->sizeof_fpregset = 272; - - /* Make sure we can single-step "new" syscalls. */ - tdep->step_trap = sparcnbsd_step_trap; - - frame_unwind_append_unwinder (gdbarch, &sparc64obsd_frame_unwind); - frame_unwind_append_unwinder (gdbarch, &sparc64obsd_trapframe_unwind); - - sparc64_init_abi (info, gdbarch); - obsd_init_abi (info, gdbarch); - - /* OpenBSD/sparc64 has SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_lp64_fetch_link_map_offsets); - set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); - - /* OpenBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, sparc64obsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, sparc64obsd_collect_uthread); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparc64obsd_tdep (void); - -void -_initialize_sparc64obsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9, - GDB_OSABI_OPENBSD_ELF, sparc64obsd_init_abi); -} diff --git a/gdb/sparcnbsd-nat.c b/gdb/sparcnbsd-nat.c deleted file mode 100644 index 230be1b7a25..00000000000 --- a/gdb/sparcnbsd-nat.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Native-dependent code for NetBSD/sparc. - - Copyright (C) 2002-2016 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 (regcache, SPARC_SP_REGNUM, &pcb->pcb_sp); - regcache_raw_supply (regcache, SPARC_O7_REGNUM, &pcb->pcb_pc); - regcache_raw_supply (regcache, SPARC32_PSR_REGNUM, &pcb->pcb_psr); - regcache_raw_supply (regcache, SPARC32_WIM_REGNUM, &pcb->pcb_wim); - regcache_raw_supply (regcache, SPARC32_PC_REGNUM, &pcb->pcb_pc); - - sparc_supply_rwindow (regcache, pcb->pcb_sp, -1); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparcnbsd_nat (void); - -void -_initialize_sparcnbsd_nat (void) -{ - sparc_gregmap = &sparc32nbsd_gregmap; - sparc_fpregmap = &sparc32_bsd_fpregmap; - - /* We've got nothing to add to the generic SPARC target. */ - add_target (sparc_target ()); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (sparc32nbsd_supply_pcb); -} diff --git a/gdb/sparcnbsd-tdep.c b/gdb/sparcnbsd-tdep.c deleted file mode 100644 index 7fa384de649..00000000000 --- a/gdb/sparcnbsd-tdep.c +++ /dev/null @@ -1,378 +0,0 @@ -/* Target-dependent code for NetBSD/sparc. - - Copyright (C) 2002-2016 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 "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 - }; - -static void -sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (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); -} - -static void -sparc32nbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - sparc32nbsd_init_abi (info, gdbarch); -} - -void -sparc32nbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - sparc32nbsd_init_abi (info, gdbarch); - - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - -static enum gdb_osabi -sparcnbsd_aout_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "a.out-sparc-netbsd") == 0) - return GDB_OSABI_NETBSD_AOUT; - - return GDB_OSABI_UNKNOWN; -} - -/* OpenBSD uses the traditional NetBSD core file format, even for - ports that use ELF. Therefore, if the default OS ABI is OpenBSD - ELF, we return that instead of NetBSD a.out. This is mainly for - the benfit of OpenBSD/sparc64, which inherits the sniffer below - since we include this file for an OpenBSD/sparc64 target. For - OpenBSD/sparc, the NetBSD a.out OS ABI is probably similar enough - to both the OpenBSD a.out and the OpenBSD ELF OS ABI. */ -#if defined (GDB_OSABI_DEFAULT) && (GDB_OSABI_DEFAULT == GDB_OSABI_OPENBSD_ELF) -#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF -#else -#define GDB_OSABI_NETBSD_CORE GDB_OSABI_NETBSD_AOUT -#endif - -static enum gdb_osabi -sparcnbsd_core_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0) - return GDB_OSABI_NETBSD_CORE; - - return GDB_OSABI_UNKNOWN; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparcnbsd_tdep (void); - -void -_initialize_sparcnbsd_tdep (void) -{ - gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_aout_flavour, - sparcnbsd_aout_osabi_sniffer); - - /* BFD doesn't set a flavour for NetBSD style a.out core files. */ - gdbarch_register_osabi_sniffer (bfd_arch_sparc, bfd_target_unknown_flavour, - sparcnbsd_core_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_AOUT, - sparc32nbsd_aout_init_abi); - gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_NETBSD_ELF, - sparc32nbsd_elf_init_abi); -} diff --git a/gdb/sparcobsd-tdep.c b/gdb/sparcobsd-tdep.c deleted file mode 100644 index 21c8d6a8148..00000000000 --- a/gdb/sparcobsd-tdep.c +++ /dev/null @@ -1,258 +0,0 @@ -/* Target-dependent code for OpenBSD/sparc. - - Copyright (C) 2004-2016 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 "floatformat.h" -#include "frame.h" -#include "frame-unwind.h" -#include "gdbcore.h" -#include "osabi.h" -#include "regcache.h" -#include "symtab.h" -#include "trad-frame.h" - -#include "obsd-tdep.h" -#include "sparc-tdep.h" -#include "solib-svr4.h" -#include "bsd-uthread.h" - -/* Signal trampolines. */ - -/* The OpenBSD kernel maps the signal trampoline at some random - location in user space, which means that the traditional BSD way of - detecting it won't work. - - The signal trampoline will be mapped at an address that is page - aligned. We recognize the signal trampoline by looking for the - sigreturn system call. */ - -static const int sparc32obsd_page_size = 4096; - -static int -sparc32obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name) -{ - CORE_ADDR start_pc = (pc & ~(sparc32obsd_page_size - 1)); - unsigned long insn; - - if (name) - return 0; - - /* Check for "restore %g0, SYS_sigreturn, %g1". */ - insn = sparc_fetch_instruction (start_pc + 0xec); - if (insn != 0x83e82067) - return 0; - - /* Check for "t ST_SYSCALL". */ - insn = sparc_fetch_instruction (start_pc + 0xf4); - if (insn != 0x91d02000) - return 0; - - return 1; -} - -static struct sparc_frame_cache * -sparc32obsd_sigtramp_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 = get_frame_pc (this_frame); - cache->pc &= ~(sparc32obsd_page_size - 1); - - /* 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 -sparc32obsd_sigtramp_frame_this_id (struct frame_info *this_frame, - void **this_cache, - struct frame_id *this_id) -{ - struct sparc_frame_cache *cache = - sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); - - (*this_id) = frame_id_build (cache->base, cache->pc); -} - -static struct value * -sparc32obsd_sigtramp_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct sparc_frame_cache *cache = - sparc32obsd_sigtramp_frame_cache (this_frame, this_cache); - - return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum); -} - -static int -sparc32obsd_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 (sparc32obsd_pc_in_sigtramp (pc, name)) - return 1; - - return 0; -} -static const struct frame_unwind sparc32obsd_sigtramp_frame_unwind = -{ - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - sparc32obsd_sigtramp_frame_this_id, - sparc32obsd_sigtramp_frame_prev_register, - NULL, - sparc32obsd_sigtramp_frame_sniffer -}; - - - -/* Offset wthin the thread structure where we can find %fp and %i7. */ -#define SPARC32OBSD_UTHREAD_FP_OFFSET 128 -#define SPARC32OBSD_UTHREAD_PC_OFFSET 132 - -static void -sparc32obsd_supply_uthread (struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR fp, fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; - gdb_byte buf[4]; - - gdb_assert (regnum >= -1); - - fp = read_memory_unsigned_integer (fp_addr, 4, byte_order); - if (regnum == SPARC_SP_REGNUM || regnum == -1) - { - store_unsigned_integer (buf, 4, byte_order, fp); - regcache_raw_supply (regcache, SPARC_SP_REGNUM, buf); - - if (regnum == SPARC_SP_REGNUM) - return; - } - - if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM - || regnum == -1) - { - CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; - - i7 = read_memory_unsigned_integer (i7_addr, 4, byte_order); - if (regnum == SPARC32_PC_REGNUM || regnum == -1) - { - store_unsigned_integer (buf, 4, byte_order, i7 + 8); - regcache_raw_supply (regcache, SPARC32_PC_REGNUM, buf); - } - if (regnum == SPARC32_NPC_REGNUM || regnum == -1) - { - store_unsigned_integer (buf, 4, byte_order, i7 + 12); - regcache_raw_supply (regcache, SPARC32_NPC_REGNUM, buf); - } - - if (regnum == SPARC32_PC_REGNUM || regnum == SPARC32_NPC_REGNUM) - return; - } - - sparc_supply_rwindow (regcache, fp, regnum); -} - -static void -sparc32obsd_collect_uthread(const struct regcache *regcache, - int regnum, CORE_ADDR addr) -{ - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - CORE_ADDR sp; - gdb_byte buf[4]; - - gdb_assert (regnum >= -1); - - if (regnum == SPARC_SP_REGNUM || regnum == -1) - { - CORE_ADDR fp_addr = addr + SPARC32OBSD_UTHREAD_FP_OFFSET; - - regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); - write_memory (fp_addr,buf, 4); - } - - if (regnum == SPARC32_PC_REGNUM || regnum == -1) - { - CORE_ADDR i7, i7_addr = addr + SPARC32OBSD_UTHREAD_PC_OFFSET; - - regcache_raw_collect (regcache, SPARC32_PC_REGNUM, buf); - i7 = extract_unsigned_integer (buf, 4, byte_order) - 8; - write_memory_unsigned_integer (i7_addr, 4, byte_order, i7); - - if (regnum == SPARC32_PC_REGNUM) - return; - } - - regcache_raw_collect (regcache, SPARC_SP_REGNUM, buf); - sp = extract_unsigned_integer (buf, 4, byte_order); - sparc_collect_rwindow (regcache, sp, regnum); -} - - -static void -sparc32obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* OpenBSD/sparc is very similar to NetBSD/sparc ELF. */ - sparc32nbsd_elf_init_abi (info, gdbarch); - - set_gdbarch_skip_solib_resolver (gdbarch, obsd_skip_solib_resolver); - - frame_unwind_append_unwinder (gdbarch, &sparc32obsd_sigtramp_frame_unwind); - - /* OpenBSD provides a user-level threads implementation. */ - bsd_uthread_set_supply_uthread (gdbarch, sparc32obsd_supply_uthread); - bsd_uthread_set_collect_uthread (gdbarch, sparc32obsd_collect_uthread); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_sparc32obsd_tdep (void); - -void -_initialize_sparc32obsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_sparc, 0, GDB_OSABI_OPENBSD_ELF, - sparc32obsd_init_abi); -} diff --git a/gdb/vax-bsd-nat.c b/gdb/vax-bsd-nat.c new file mode 100644 index 00000000000..60069b21fb7 --- /dev/null +++ b/gdb/vax-bsd-nat.c @@ -0,0 +1,146 @@ +/* Native-dependent code for modern VAX BSD's. + + Copyright (C) 2004-2016 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 "target.h" + +#include +#include +#include + +#include "vax-tdep.h" +#include "inf-ptrace.h" + +/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ + +static void +vaxbsd_supply_gregset (struct regcache *regcache, const void *gregs) +{ + const gdb_byte *regs = gregs; + int regnum; + + for (regnum = 0; regnum < VAX_NUM_REGS; regnum++) + regcache_raw_supply (regcache, regnum, regs + regnum * 4); +} + +/* Collect the general-purpose registers from REGCACHE and store them + in GREGS. */ + +static void +vaxbsd_collect_gregset (const struct regcache *regcache, + void *gregs, int regnum) +{ + gdb_byte *regs = gregs; + int i; + + for (i = 0; i <= VAX_NUM_REGS; i++) + { + if (regnum == -1 || regnum == i) + regcache_raw_collect (regcache, i, regs + i * 4); + } +} + + +/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this + for all registers. */ + +static void +vaxbsd_fetch_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + vaxbsd_supply_gregset (regcache, ®s); +} + +/* Store register REGNUM back into the inferior. If REGNUM is -1, do + this for all registers. */ + +static void +vaxbsd_store_inferior_registers (struct target_ops *ops, + struct regcache *regcache, int regnum) +{ + struct reg regs; + + if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't get registers")); + + vaxbsd_collect_gregset (regcache, ®s, regnum); + + if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) ®s, 0) == -1) + perror_with_name (_("Couldn't write registers")); +} + + +/* Support for debugging kernel virtual memory images. */ + +#include + +#include "bsd-kvm.h" + +static int +vaxbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) +{ + int regnum; + + /* The following is true for OpenBSD 3.5: + + The pcb contains the register state at the context switch inside + cpu_switch(). */ + + /* The stack pointer shouldn't be zero. */ + if (pcb->KSP == 0) + return 0; + + for (regnum = VAX_R0_REGNUM; regnum < VAX_AP_REGNUM; regnum++) + regcache_raw_supply (regcache, regnum, &pcb->R[regnum - VAX_R0_REGNUM]); + regcache_raw_supply (regcache, VAX_AP_REGNUM, &pcb->AP); + regcache_raw_supply (regcache, VAX_FP_REGNUM, &pcb->FP); + regcache_raw_supply (regcache, VAX_SP_REGNUM, &pcb->KSP); + regcache_raw_supply (regcache, VAX_PC_REGNUM, &pcb->PC); + regcache_raw_supply (regcache, VAX_PS_REGNUM, &pcb->PSL); + + return 1; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_vaxbsd_nat (void); + +void +_initialize_vaxbsd_nat (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + t->to_fetch_registers = vaxbsd_fetch_inferior_registers; + t->to_store_registers = vaxbsd_store_inferior_registers; + add_target (t); + + /* Support debugging kernel virtual memory images. */ + bsd_kvm_add_target (vaxbsd_supply_pcb); +} diff --git a/gdb/vax-nbsd-tdep.c b/gdb/vax-nbsd-tdep.c new file mode 100644 index 00000000000..1302dcd1811 --- /dev/null +++ b/gdb/vax-nbsd-tdep.c @@ -0,0 +1,46 @@ +/* Target-dependent code for NetBSD/vax. + + Copyright (C) 2004-2016 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 "solib-svr4.h" + +/* NetBSD ELF. */ + +static void +vaxnbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + /* NetBSD ELF uses SVR4-style shared libraries. */ + set_solib_svr4_fetch_link_map_offsets + (gdbarch, svr4_ilp32_fetch_link_map_offsets); +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_vaxnbsd_tdep (void); + +void +_initialize_vaxnbsd_tdep (void) +{ + gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_NETBSD_ELF, + vaxnbsd_elf_init_abi); +} diff --git a/gdb/vax-obsd-tdep.c b/gdb/vax-obsd-tdep.c new file mode 100644 index 00000000000..ee48ac62a7f --- /dev/null +++ b/gdb/vax-obsd-tdep.c @@ -0,0 +1,178 @@ +/* Target-dependent code for OpenBSD/vax. + + Copyright (C) 2005-2016 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 "frame-unwind.h" +#include "osabi.h" +#include "symtab.h" +#include "trad-frame.h" + +#include "vax-tdep.h" + +/* Signal trampolines. */ + +/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page + in virtual memory. The randomness makes it somewhat tricky to + detect it, but fortunately we can rely on the fact that the start + of the sigtramp routine is page-aligned. We recognize the + trampoline by looking for the code that invokes the sigreturn + system call. The offset where we can find that code varies from + release to release. + + By the way, the mapping mentioned above is read-only, so you cannot + place a breakpoint in the signal trampoline. */ + +/* Default page size. */ +static const int vaxobsd_page_size = 4096; + +/* Offset for sigreturn(2). */ +static const int vaxobsd_sigreturn_offset = 0x11; + +/* Instruction sequence for sigreturn(2). VAX doesn't have + fixed-length instructions so we include the ensuing exit(2) to + reduce the chance of spurious matches. */ +static const gdb_byte vaxobsd_sigreturn[] = { + 0xbc, 0x8f, 0x67, 0x00, /* chmk $SYS_sigreturn */ + 0xbc, 0x01 /* chmk $SYS_exit */ +}; + +static int +vaxobsd_sigtramp_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_cache) +{ + CORE_ADDR pc = get_frame_pc (this_frame); + CORE_ADDR start_pc = (pc & ~(vaxobsd_page_size - 1)); + CORE_ADDR sigreturn_addr = start_pc + vaxobsd_sigreturn_offset; + gdb_byte *buf; + const char *name; + + find_pc_partial_function (pc, &name, NULL, NULL); + if (name) + return 0; + + buf = (gdb_byte *) alloca (sizeof vaxobsd_sigreturn); + if (!safe_frame_unwind_memory (this_frame, sigreturn_addr, + buf, sizeof vaxobsd_sigreturn)) + return 0; + + if (memcmp(buf, vaxobsd_sigreturn, sizeof vaxobsd_sigreturn) == 0) + return 1; + + return 0; +} + +static struct trad_frame_cache * +vaxobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + struct trad_frame_cache *cache; + CORE_ADDR addr, base, func; + + if (*this_cache) + return (struct trad_frame_cache *) *this_cache; + + cache = trad_frame_cache_zalloc (this_frame); + *this_cache = cache; + + func = get_frame_pc (this_frame); + func &= ~(vaxobsd_page_size - 1); + + base = get_frame_register_unsigned (this_frame, VAX_SP_REGNUM); + addr = get_frame_memory_unsigned (this_frame, base - 4, 4); + + trad_frame_set_reg_addr (cache, VAX_SP_REGNUM, addr + 8); + trad_frame_set_reg_addr (cache, VAX_FP_REGNUM, addr + 12); + trad_frame_set_reg_addr (cache, VAX_AP_REGNUM, addr + 16); + trad_frame_set_reg_addr (cache, VAX_PC_REGNUM, addr + 20); + trad_frame_set_reg_addr (cache, VAX_PS_REGNUM, addr + 24); + + /* Construct the frame ID using the function start. */ + trad_frame_set_id (cache, frame_id_build (base, func)); + + return cache; +} + +static void +vaxobsd_sigtramp_frame_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + struct trad_frame_cache *cache = + vaxobsd_sigtramp_frame_cache (this_frame, this_cache); + + trad_frame_get_id (cache, this_id); +} + +static struct value * +vaxobsd_sigtramp_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct trad_frame_cache *cache = + vaxobsd_sigtramp_frame_cache (this_frame, this_cache); + + return trad_frame_get_register (cache, this_frame, regnum); +} + +static const struct frame_unwind vaxobsd_sigtramp_frame_unwind = { + SIGTRAMP_FRAME, + default_frame_unwind_stop_reason, + vaxobsd_sigtramp_frame_this_id, + vaxobsd_sigtramp_frame_prev_register, + NULL, + vaxobsd_sigtramp_sniffer +}; + + +/* OpenBSD a.out. */ + +static void +vaxobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ + frame_unwind_append_unwinder (gdbarch, &vaxobsd_sigtramp_frame_unwind); +} + +/* FIXME: kettenis/20050821: Since OpenBSD/vax binaries are + indistingushable from NetBSD/vax a.out binaries, building a GDB + that should support both these targets will probably not work as + expected. */ +#define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT + +static enum gdb_osabi +vaxobsd_aout_osabi_sniffer (bfd *abfd) +{ + if (strcmp (bfd_get_target (abfd), "a.out-vax-netbsd") == 0) + return GDB_OSABI_OPENBSD_AOUT; + + return GDB_OSABI_UNKNOWN; +} + + +/* Provide a prototype to silence -Wmissing-prototypes. */ +void _initialize_vaxobsd_tdep (void); + +void +_initialize_vaxobsd_tdep (void) +{ + gdbarch_register_osabi_sniffer (bfd_arch_vax, bfd_target_aout_flavour, + vaxobsd_aout_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_OPENBSD_AOUT, + vaxobsd_init_abi); +} diff --git a/gdb/vaxbsd-nat.c b/gdb/vaxbsd-nat.c deleted file mode 100644 index 60069b21fb7..00000000000 --- a/gdb/vaxbsd-nat.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Native-dependent code for modern VAX BSD's. - - Copyright (C) 2004-2016 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 "target.h" - -#include -#include -#include - -#include "vax-tdep.h" -#include "inf-ptrace.h" - -/* Supply the general-purpose registers stored in GREGS to REGCACHE. */ - -static void -vaxbsd_supply_gregset (struct regcache *regcache, const void *gregs) -{ - const gdb_byte *regs = gregs; - int regnum; - - for (regnum = 0; regnum < VAX_NUM_REGS; regnum++) - regcache_raw_supply (regcache, regnum, regs + regnum * 4); -} - -/* Collect the general-purpose registers from REGCACHE and store them - in GREGS. */ - -static void -vaxbsd_collect_gregset (const struct regcache *regcache, - void *gregs, int regnum) -{ - gdb_byte *regs = gregs; - int i; - - for (i = 0; i <= VAX_NUM_REGS; i++) - { - if (regnum == -1 || regnum == i) - regcache_raw_collect (regcache, i, regs + i * 4); - } -} - - -/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this - for all registers. */ - -static void -vaxbsd_fetch_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - vaxbsd_supply_gregset (regcache, ®s); -} - -/* Store register REGNUM back into the inferior. If REGNUM is -1, do - this for all registers. */ - -static void -vaxbsd_store_inferior_registers (struct target_ops *ops, - struct regcache *regcache, int regnum) -{ - struct reg regs; - - if (ptrace (PT_GETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't get registers")); - - vaxbsd_collect_gregset (regcache, ®s, regnum); - - if (ptrace (PT_SETREGS, ptid_get_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) ®s, 0) == -1) - perror_with_name (_("Couldn't write registers")); -} - - -/* Support for debugging kernel virtual memory images. */ - -#include - -#include "bsd-kvm.h" - -static int -vaxbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) -{ - int regnum; - - /* The following is true for OpenBSD 3.5: - - The pcb contains the register state at the context switch inside - cpu_switch(). */ - - /* The stack pointer shouldn't be zero. */ - if (pcb->KSP == 0) - return 0; - - for (regnum = VAX_R0_REGNUM; regnum < VAX_AP_REGNUM; regnum++) - regcache_raw_supply (regcache, regnum, &pcb->R[regnum - VAX_R0_REGNUM]); - regcache_raw_supply (regcache, VAX_AP_REGNUM, &pcb->AP); - regcache_raw_supply (regcache, VAX_FP_REGNUM, &pcb->FP); - regcache_raw_supply (regcache, VAX_SP_REGNUM, &pcb->KSP); - regcache_raw_supply (regcache, VAX_PC_REGNUM, &pcb->PC); - regcache_raw_supply (regcache, VAX_PS_REGNUM, &pcb->PSL); - - return 1; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_vaxbsd_nat (void); - -void -_initialize_vaxbsd_nat (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - t->to_fetch_registers = vaxbsd_fetch_inferior_registers; - t->to_store_registers = vaxbsd_store_inferior_registers; - add_target (t); - - /* Support debugging kernel virtual memory images. */ - bsd_kvm_add_target (vaxbsd_supply_pcb); -} diff --git a/gdb/vaxnbsd-tdep.c b/gdb/vaxnbsd-tdep.c deleted file mode 100644 index 1302dcd1811..00000000000 --- a/gdb/vaxnbsd-tdep.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Target-dependent code for NetBSD/vax. - - Copyright (C) 2004-2016 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 "solib-svr4.h" - -/* NetBSD ELF. */ - -static void -vaxnbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - /* NetBSD ELF uses SVR4-style shared libraries. */ - set_solib_svr4_fetch_link_map_offsets - (gdbarch, svr4_ilp32_fetch_link_map_offsets); -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_vaxnbsd_tdep (void); - -void -_initialize_vaxnbsd_tdep (void) -{ - gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_NETBSD_ELF, - vaxnbsd_elf_init_abi); -} diff --git a/gdb/vaxobsd-tdep.c b/gdb/vaxobsd-tdep.c deleted file mode 100644 index ee48ac62a7f..00000000000 --- a/gdb/vaxobsd-tdep.c +++ /dev/null @@ -1,178 +0,0 @@ -/* Target-dependent code for OpenBSD/vax. - - Copyright (C) 2005-2016 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 "frame-unwind.h" -#include "osabi.h" -#include "symtab.h" -#include "trad-frame.h" - -#include "vax-tdep.h" - -/* Signal trampolines. */ - -/* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page - in virtual memory. The randomness makes it somewhat tricky to - detect it, but fortunately we can rely on the fact that the start - of the sigtramp routine is page-aligned. We recognize the - trampoline by looking for the code that invokes the sigreturn - system call. The offset where we can find that code varies from - release to release. - - By the way, the mapping mentioned above is read-only, so you cannot - place a breakpoint in the signal trampoline. */ - -/* Default page size. */ -static const int vaxobsd_page_size = 4096; - -/* Offset for sigreturn(2). */ -static const int vaxobsd_sigreturn_offset = 0x11; - -/* Instruction sequence for sigreturn(2). VAX doesn't have - fixed-length instructions so we include the ensuing exit(2) to - reduce the chance of spurious matches. */ -static const gdb_byte vaxobsd_sigreturn[] = { - 0xbc, 0x8f, 0x67, 0x00, /* chmk $SYS_sigreturn */ - 0xbc, 0x01 /* chmk $SYS_exit */ -}; - -static int -vaxobsd_sigtramp_sniffer (const struct frame_unwind *self, - struct frame_info *this_frame, - void **this_cache) -{ - CORE_ADDR pc = get_frame_pc (this_frame); - CORE_ADDR start_pc = (pc & ~(vaxobsd_page_size - 1)); - CORE_ADDR sigreturn_addr = start_pc + vaxobsd_sigreturn_offset; - gdb_byte *buf; - const char *name; - - find_pc_partial_function (pc, &name, NULL, NULL); - if (name) - return 0; - - buf = (gdb_byte *) alloca (sizeof vaxobsd_sigreturn); - if (!safe_frame_unwind_memory (this_frame, sigreturn_addr, - buf, sizeof vaxobsd_sigreturn)) - return 0; - - if (memcmp(buf, vaxobsd_sigreturn, sizeof vaxobsd_sigreturn) == 0) - return 1; - - return 0; -} - -static struct trad_frame_cache * -vaxobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) -{ - struct trad_frame_cache *cache; - CORE_ADDR addr, base, func; - - if (*this_cache) - return (struct trad_frame_cache *) *this_cache; - - cache = trad_frame_cache_zalloc (this_frame); - *this_cache = cache; - - func = get_frame_pc (this_frame); - func &= ~(vaxobsd_page_size - 1); - - base = get_frame_register_unsigned (this_frame, VAX_SP_REGNUM); - addr = get_frame_memory_unsigned (this_frame, base - 4, 4); - - trad_frame_set_reg_addr (cache, VAX_SP_REGNUM, addr + 8); - trad_frame_set_reg_addr (cache, VAX_FP_REGNUM, addr + 12); - trad_frame_set_reg_addr (cache, VAX_AP_REGNUM, addr + 16); - trad_frame_set_reg_addr (cache, VAX_PC_REGNUM, addr + 20); - trad_frame_set_reg_addr (cache, VAX_PS_REGNUM, addr + 24); - - /* Construct the frame ID using the function start. */ - trad_frame_set_id (cache, frame_id_build (base, func)); - - return cache; -} - -static void -vaxobsd_sigtramp_frame_this_id (struct frame_info *this_frame, - void **this_cache, struct frame_id *this_id) -{ - struct trad_frame_cache *cache = - vaxobsd_sigtramp_frame_cache (this_frame, this_cache); - - trad_frame_get_id (cache, this_id); -} - -static struct value * -vaxobsd_sigtramp_frame_prev_register (struct frame_info *this_frame, - void **this_cache, int regnum) -{ - struct trad_frame_cache *cache = - vaxobsd_sigtramp_frame_cache (this_frame, this_cache); - - return trad_frame_get_register (cache, this_frame, regnum); -} - -static const struct frame_unwind vaxobsd_sigtramp_frame_unwind = { - SIGTRAMP_FRAME, - default_frame_unwind_stop_reason, - vaxobsd_sigtramp_frame_this_id, - vaxobsd_sigtramp_frame_prev_register, - NULL, - vaxobsd_sigtramp_sniffer -}; - - -/* OpenBSD a.out. */ - -static void -vaxobsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) -{ - frame_unwind_append_unwinder (gdbarch, &vaxobsd_sigtramp_frame_unwind); -} - -/* FIXME: kettenis/20050821: Since OpenBSD/vax binaries are - indistingushable from NetBSD/vax a.out binaries, building a GDB - that should support both these targets will probably not work as - expected. */ -#define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT - -static enum gdb_osabi -vaxobsd_aout_osabi_sniffer (bfd *abfd) -{ - if (strcmp (bfd_get_target (abfd), "a.out-vax-netbsd") == 0) - return GDB_OSABI_OPENBSD_AOUT; - - return GDB_OSABI_UNKNOWN; -} - - -/* Provide a prototype to silence -Wmissing-prototypes. */ -void _initialize_vaxobsd_tdep (void); - -void -_initialize_vaxobsd_tdep (void) -{ - gdbarch_register_osabi_sniffer (bfd_arch_vax, bfd_target_aout_flavour, - vaxobsd_aout_osabi_sniffer); - - gdbarch_register_osabi (bfd_arch_vax, 0, GDB_OSABI_OPENBSD_AOUT, - vaxobsd_init_abi); -} diff --git a/gdb/x86-bsd-nat.c b/gdb/x86-bsd-nat.c new file mode 100644 index 00000000000..1998476cc16 --- /dev/null +++ b/gdb/x86-bsd-nat.c @@ -0,0 +1,156 @@ +/* Native-dependent code for X86 BSD's. + + Copyright (C) 2003-2016 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 "gdbthread.h" + +/* We include to make sure `struct fxsave64' is defined on + NetBSD, since NetBSD's needs it. */ +#include +#include +#include +#include + +#include "x86-nat.h" +#include "x86-bsd-nat.h" +#include "inf-ptrace.h" + + +#ifdef PT_GETXSTATE_INFO +size_t x86bsd_xsave_len; +#endif + +/* Support for debug registers. */ + +#ifdef HAVE_PT_GETDBREGS +static void (*super_mourn_inferior) (struct target_ops *ops); + +/* Implement the "to_mourn_inferior" target_ops method. */ + +static void +x86bsd_mourn_inferior (struct target_ops *ops) +{ + x86_cleanup_dregs (); + super_mourn_inferior (ops); +} + +/* Not all versions of FreeBSD/i386 that support the debug registers + have this macro. */ +#ifndef DBREG_DRX +#define DBREG_DRX(d, x) ((&d->dr0)[x]) +#endif + +static unsigned long +x86bsd_dr_get (ptid_t ptid, int regnum) +{ + struct dbreg dbregs; + + if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) + perror_with_name (_("Couldn't read debug registers")); + + return DBREG_DRX ((&dbregs), regnum); +} + +static void +x86bsd_dr_set (int regnum, unsigned long value) +{ + struct thread_info *thread; + struct dbreg dbregs; + + if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), + (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) + perror_with_name (_("Couldn't get debug registers")); + + /* For some mysterious reason, some of the reserved bits in the + debug control register get set. Mask these off, otherwise the + ptrace call below will fail. */ + DBREG_DRX ((&dbregs), 7) &= ~(0xffffffff0000fc00); + + DBREG_DRX ((&dbregs), regnum) = value; + + ALL_NON_EXITED_THREADS (thread) + if (thread->inf == current_inferior ()) + { + if (ptrace (PT_SETDBREGS, get_ptrace_pid (thread->ptid), + (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) + perror_with_name (_("Couldn't write debug registers")); + } +} + +static void +x86bsd_dr_set_control (unsigned long control) +{ + x86bsd_dr_set (7, control); +} + +static void +x86bsd_dr_set_addr (int regnum, CORE_ADDR addr) +{ + gdb_assert (regnum >= 0 && regnum <= 4); + + x86bsd_dr_set (regnum, addr); +} + +static CORE_ADDR +x86bsd_dr_get_addr (int regnum) +{ + return x86bsd_dr_get (inferior_ptid, regnum); +} + +static unsigned long +x86bsd_dr_get_status (void) +{ + return x86bsd_dr_get (inferior_ptid, 6); +} + +static unsigned long +x86bsd_dr_get_control (void) +{ + return x86bsd_dr_get (inferior_ptid, 7); +} + +#endif /* PT_GETDBREGS */ + +/* Create a prototype *BSD/x86 target. The client can override it + with local methods. */ + +struct target_ops * +x86bsd_target (void) +{ + struct target_ops *t; + + t = inf_ptrace_target (); + +#ifdef HAVE_PT_GETDBREGS + x86_use_watchpoints (t); + + x86_dr_low.set_control = x86bsd_dr_set_control; + x86_dr_low.set_addr = x86bsd_dr_set_addr; + x86_dr_low.get_addr = x86bsd_dr_get_addr; + x86_dr_low.get_status = x86bsd_dr_get_status; + x86_dr_low.get_control = x86bsd_dr_get_control; + x86_set_debug_register_length (sizeof (void *)); + super_mourn_inferior = t->to_mourn_inferior; + t->to_mourn_inferior = x86bsd_mourn_inferior; +#endif /* HAVE_PT_GETDBREGS */ + + return t; +} diff --git a/gdb/x86-bsd-nat.h b/gdb/x86-bsd-nat.h new file mode 100644 index 00000000000..a13ff48de5f --- /dev/null +++ b/gdb/x86-bsd-nat.h @@ -0,0 +1,31 @@ +/* Native-dependent code for x86 BSD's. + + Copyright (C) 2011-2016 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 X86_BSD_NAT_H +#define X86_BSD_NAT_H + +/* Low level x86 XSAVE info. */ +extern size_t x86bsd_xsave_len; + +/* Create a prototype *BSD/x86 target. The client can override it + with local methods. */ + +extern struct target_ops *x86bsd_target (void); + +#endif /* x86-bsd-nat.h */ diff --git a/gdb/x86bsd-nat.c b/gdb/x86bsd-nat.c deleted file mode 100644 index bde25ab7724..00000000000 --- a/gdb/x86bsd-nat.c +++ /dev/null @@ -1,156 +0,0 @@ -/* Native-dependent code for X86 BSD's. - - Copyright (C) 2003-2016 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 "gdbthread.h" - -/* We include to make sure `struct fxsave64' is defined on - NetBSD, since NetBSD's needs it. */ -#include -#include -#include -#include - -#include "x86-nat.h" -#include "x86bsd-nat.h" -#include "inf-ptrace.h" - - -#ifdef PT_GETXSTATE_INFO -size_t x86bsd_xsave_len; -#endif - -/* Support for debug registers. */ - -#ifdef HAVE_PT_GETDBREGS -static void (*super_mourn_inferior) (struct target_ops *ops); - -/* Implement the "to_mourn_inferior" target_ops method. */ - -static void -x86bsd_mourn_inferior (struct target_ops *ops) -{ - x86_cleanup_dregs (); - super_mourn_inferior (ops); -} - -/* Not all versions of FreeBSD/i386 that support the debug registers - have this macro. */ -#ifndef DBREG_DRX -#define DBREG_DRX(d, x) ((&d->dr0)[x]) -#endif - -static unsigned long -x86bsd_dr_get (ptid_t ptid, int regnum) -{ - struct dbreg dbregs; - - if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) - perror_with_name (_("Couldn't read debug registers")); - - return DBREG_DRX ((&dbregs), regnum); -} - -static void -x86bsd_dr_set (int regnum, unsigned long value) -{ - struct thread_info *thread; - struct dbreg dbregs; - - if (ptrace (PT_GETDBREGS, get_ptrace_pid (inferior_ptid), - (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) - perror_with_name (_("Couldn't get debug registers")); - - /* For some mysterious reason, some of the reserved bits in the - debug control register get set. Mask these off, otherwise the - ptrace call below will fail. */ - DBREG_DRX ((&dbregs), 7) &= ~(0xffffffff0000fc00); - - DBREG_DRX ((&dbregs), regnum) = value; - - ALL_NON_EXITED_THREADS (thread) - if (thread->inf == current_inferior ()) - { - if (ptrace (PT_SETDBREGS, get_ptrace_pid (thread->ptid), - (PTRACE_TYPE_ARG3) &dbregs, 0) == -1) - perror_with_name (_("Couldn't write debug registers")); - } -} - -static void -x86bsd_dr_set_control (unsigned long control) -{ - x86bsd_dr_set (7, control); -} - -static void -x86bsd_dr_set_addr (int regnum, CORE_ADDR addr) -{ - gdb_assert (regnum >= 0 && regnum <= 4); - - x86bsd_dr_set (regnum, addr); -} - -static CORE_ADDR -x86bsd_dr_get_addr (int regnum) -{ - return x86bsd_dr_get (inferior_ptid, regnum); -} - -static unsigned long -x86bsd_dr_get_status (void) -{ - return x86bsd_dr_get (inferior_ptid, 6); -} - -static unsigned long -x86bsd_dr_get_control (void) -{ - return x86bsd_dr_get (inferior_ptid, 7); -} - -#endif /* PT_GETDBREGS */ - -/* Create a prototype *BSD/x86 target. The client can override it - with local methods. */ - -struct target_ops * -x86bsd_target (void) -{ - struct target_ops *t; - - t = inf_ptrace_target (); - -#ifdef HAVE_PT_GETDBREGS - x86_use_watchpoints (t); - - x86_dr_low.set_control = x86bsd_dr_set_control; - x86_dr_low.set_addr = x86bsd_dr_set_addr; - x86_dr_low.get_addr = x86bsd_dr_get_addr; - x86_dr_low.get_status = x86bsd_dr_get_status; - x86_dr_low.get_control = x86bsd_dr_get_control; - x86_set_debug_register_length (sizeof (void *)); - super_mourn_inferior = t->to_mourn_inferior; - t->to_mourn_inferior = x86bsd_mourn_inferior; -#endif /* HAVE_PT_GETDBREGS */ - - return t; -} diff --git a/gdb/x86bsd-nat.h b/gdb/x86bsd-nat.h deleted file mode 100644 index 6d39697000f..00000000000 --- a/gdb/x86bsd-nat.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Native-dependent code for x86 BSD's. - - Copyright (C) 2011-2016 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 X86BSD_NAT_H -#define X86BSD_NAT_H - -/* Low level x86 XSAVE info. */ -extern size_t x86bsd_xsave_len; - -/* Create a prototype *BSD/x86 target. The client can override it - with local methods. */ - -extern struct target_ops *x86bsd_target (void); - -#endif /* x86bsd-nat.h */