From cba8a572c208078c1c6eb9845b54f960526c53c0 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 27 Feb 2019 22:35:10 +0000 Subject: [PATCH] re PR go/89172 (FAIL: runtime/pprof) PR go/89172 internal/cpu, runtime, runtime/pprof: handle function descriptors When using PPC64 ELF ABI v1 a function address is not a PC, but is the address of a function descriptor. The first field in the function descriptor is the actual PC (see http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi.html#FUNC-DES). The libbacktrace library knows about this, and libgo uses actual PC values consistently except for the helper function funcPC that appears in both runtime and runtime/pprof. This patch fixes funcPC by recording, in the internal/cpu package, whether function descriptors are being used. We have to check for function descriptors using a C compiler check, because GCC can be configured using --with-abi to select the ELF ABI to use. Fixes https://gcc.gnu.org/PR89172 Reviewed-on: https://go-review.googlesource.com/c/162978 From-SVN: r269266 --- gcc/go/gofrontend/MERGE | 2 +- libgo/Makefile.am | 1 + libgo/Makefile.in | 2 ++ libgo/configure | 26 ++++++++++++++++++++++++-- libgo/configure.ac | 14 ++++++++++++++ libgo/go/runtime/pprof/proto.go | 10 +++++++++- libgo/go/runtime/proc.go | 9 ++++++++- libgo/testsuite/Makefile.in | 1 + 8 files changed, 60 insertions(+), 5 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index b2f065d66a0..749e523e7df 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -c9581de3804f94c5a74ce14befce5c57368722b9 +74533ed435a1a77e6f9ec8f6cf5db1695c2568e8 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 1f78111445b..aeaa203ce5a 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -539,6 +539,7 @@ s-cpu: Makefile rm -f cpugen.go.tmp echo "package cpu" > cpugen.go.tmp echo "const CacheLinePadSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) cachelinesize`" >> cpugen.go.tmp + echo "const FunctionDescriptors = $(FUNCTION_DESCRIPTORS)" >> cpugen.go.tmp $(SHELL) $(srcdir)/mvifdiff.sh cpugen.go.tmp cpugen.go $(STAMP) $@ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 0b26158dd7d..7f398918c57 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -397,6 +397,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUNCTION_DESCRIPTORS = @FUNCTION_DESCRIPTORS@ GOARCH = @GOARCH@ GOC = @GOC@ GOFLAGS = @GOFLAGS@ @@ -2635,6 +2636,7 @@ s-cpu: Makefile rm -f cpugen.go.tmp echo "package cpu" > cpugen.go.tmp echo "const CacheLinePadSize = `$(SHELL) $(srcdir)/goarch.sh $(GOARCH) cachelinesize`" >> cpugen.go.tmp + echo "const FunctionDescriptors = $(FUNCTION_DESCRIPTORS)" >> cpugen.go.tmp $(SHELL) $(srcdir)/mvifdiff.sh cpugen.go.tmp cpugen.go $(STAMP) $@ diff --git a/libgo/configure b/libgo/configure index 0b8ebce3f9c..06b68b0f416 100755 --- a/libgo/configure +++ b/libgo/configure @@ -661,6 +661,7 @@ GO_SYSCALL_OS_ARCH_FILE GO_SYSCALL_OS_FILE GO_LIBCALL_OS_ARCH_FILE GO_LIBCALL_OS_FILE +FUNCTION_DESCRIPTORS ALLGOARCHFAMILY ALLGOARCH GOARCH @@ -11343,7 +11344,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11346 "configure" +#line 11347 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11449,7 +11450,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11452 "configure" +#line 11453 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14088,6 +14089,27 @@ esac +FUNCTION_DESCRIPTORS=false +case ${host} in + rs6000*-*-* | powerpc*-*-*) + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#if _CALL_ELF == 1 +#error descriptors +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + FUNCTION_DESCRIPTORS=false +else + FUNCTION_DESCRIPTORS=true +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ;; +esac + + GO_LIBCALL_OS_FILE= GO_LIBCALL_OS_ARCH_FILE= GO_SYSCALL_OS_FILE= diff --git a/libgo/configure.ac b/libgo/configure.ac index 44b59482c53..03c07fe8838 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -353,6 +353,20 @@ AC_SUBST(GOARCH) AC_SUBST(ALLGOARCH) AC_SUBST(ALLGOARCHFAMILY) +FUNCTION_DESCRIPTORS=false +case ${host} in + rs6000*-*-* | powerpc*-*-*) + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ +#if _CALL_ELF == 1 +#error descriptors +#endif +])], + [FUNCTION_DESCRIPTORS=false], + [FUNCTION_DESCRIPTORS=true]) + ;; +esac +AC_SUBST(FUNCTION_DESCRIPTORS) + dnl Some files are only present when needed for specific architectures. GO_LIBCALL_OS_FILE= GO_LIBCALL_OS_ARCH_FILE= diff --git a/libgo/go/runtime/pprof/proto.go b/libgo/go/runtime/pprof/proto.go index b82e738f941..27cd09e7870 100644 --- a/libgo/go/runtime/pprof/proto.go +++ b/libgo/go/runtime/pprof/proto.go @@ -8,6 +8,7 @@ import ( "bytes" "compress/gzip" "fmt" + internalcpu "internal/cpu" "io" "io/ioutil" "runtime" @@ -28,7 +29,14 @@ func funcPC(f interface{}) uintptr { data unsafe.Pointer } i := (*iface)(unsafe.Pointer(&f)) - return **(**uintptr)(i.data) + r := **(**uintptr)(i.data) + if internalcpu.FunctionDescriptors { + // With PPC64 ELF ABI v1 function descriptors the + // function address is a pointer to a struct whose + // first field is the actual PC. + r = *(*uintptr)(unsafe.Pointer(r)) + } + return r } // A profileBuilder writes a profile incrementally from a diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go index 1c944d64752..0e6c9e19b09 100644 --- a/libgo/go/runtime/proc.go +++ b/libgo/go/runtime/proc.go @@ -446,7 +446,14 @@ func releaseSudog(s *sudog) { //go:nosplit func funcPC(f interface{}) uintptr { i := (*iface)(unsafe.Pointer(&f)) - return **(**uintptr)(i.data) + r := **(**uintptr)(i.data) + if cpu.FunctionDescriptors { + // With PPC64 ELF ABI v1 function descriptors the + // function address is a pointer to a struct whose + // first field is the actual PC. + r = *(*uintptr)(unsafe.Pointer(r)) + } + return r } func lockedOSThread() bool { diff --git a/libgo/testsuite/Makefile.in b/libgo/testsuite/Makefile.in index 035a9fa9d1b..13075892705 100644 --- a/libgo/testsuite/Makefile.in +++ b/libgo/testsuite/Makefile.in @@ -157,6 +157,7 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUNCTION_DESCRIPTORS = @FUNCTION_DESCRIPTORS@ GOARCH = @GOARCH@ GOC = @GOC@ GOFLAGS = @GOFLAGS@ -- 2.30.2