aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-02-27 22:35:10 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-02-27 22:35:10 +0000
commitcba8a572c208078c1c6eb9845b54f960526c53c0 (patch)
tree2533982aacf337307ee72ee82ae77f3cb01fbd58
parente6df04c105464436e700013e1f665ebf0f94c9f2 (diff)
downloadgcc-cba8a572c208078c1c6eb9845b54f960526c53c0.zip
gcc-cba8a572c208078c1c6eb9845b54f960526c53c0.tar.gz
gcc-cba8a572c208078c1c6eb9845b54f960526c53c0.tar.bz2
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
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--libgo/Makefile.am1
-rw-r--r--libgo/Makefile.in2
-rwxr-xr-xlibgo/configure26
-rw-r--r--libgo/configure.ac14
-rw-r--r--libgo/go/runtime/pprof/proto.go10
-rw-r--r--libgo/go/runtime/proc.go9
-rw-r--r--libgo/testsuite/Makefile.in1
8 files changed, 60 insertions, 5 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index b2f065d..749e523 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 1f78111..aeaa203 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 0b26158..7f39891 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 0b8ebce..06b68b0 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 44b5948..03c07fe 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 b82e738..27cd09e 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 1c944d6..0e6c9e1 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 035a9fa..1307589 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@