cmd/dist: fix build failure of misc/cgo/test on arm64
authorXiangdong Ji <xiangdong.ji@arm.com>
Wed, 5 Aug 2020 06:02:58 +0000 (06:02 +0000)
committerShengjing Zhu <zhsj@debian.org>
Sat, 8 May 2021 06:22:26 +0000 (07:22 +0100)
Test7978 of misc/cgo/test fails in 'dist test' on arm64 if the C compiler
is of GCC-9.4 or above and its 'outline atomics' feature is enabled, since
the internal linking hasn't yet supported "__attribute__((constructor))"
and also mis-handles hidden visibility.

Two changes are made for 'misc/cgo/test' to fix the issue:
  1. passing "-tags=internal" for the internal linking PIE case.
  2. skipping Test7978 on arm64 for the internal linking cases.

This CL fixes 'dist test' failure only, user is expected to pass the option
'-mno-outline-atomics' via CGO_CFLAGS if running into the same problem when
building cgo program using internal linking.

Updates #39466
Change-Id: I2011bb051cae7c43eb0f1c78c7f4fbdb94bf78a6

Gbp-Pq: Name 0004-cmd-dist-fix-build-failure-of-misc-cgo-test-on-arm64.patch

misc/cgo/test/issue7978.go [new file with mode: 0644]
misc/cgo/test/issue7978b.go [new file with mode: 0644]
misc/cgo/test/testx.go
src/cmd/dist/test.go

diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go
new file mode 100644 (file)
index 0000000..18d418f
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !arm64 !internal
+
+package cgotest
+
+import (
+       "runtime"
+       "runtime/debug"
+       "strings"
+       "sync/atomic"
+       "testing"
+)
+
+/*
+#include <stdint.h>
+
+void issue7978cb(void);
+
+// use ugly atomic variable sync since that doesn't require calling back into
+// Go code or OS dependencies
+static void issue7978c(uint32_t *sync) {
+       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
+               ;
+       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
+       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
+               ;
+       issue7978cb();
+       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
+       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
+               ;
+}
+
+*/
+import "C"
+
+// issue 7978
+
+var issue7978sync uint32
+
+func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) {
+       runtime.GC()
+       buf := make([]byte, 65536)
+       trace := string(buf[:runtime.Stack(buf, true)])
+       for _, goroutine := range strings.Split(trace, "\n\n") {
+               if strings.Contains(goroutine, "test.issue7978go") {
+                       trace := strings.Split(goroutine, "\n")
+                       // look for the expected function in the stack
+                       for i := 0; i < depth; i++ {
+                               if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) {
+                                       t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine)
+                                       return
+                               }
+                               if strings.Contains(trace[1+2*i], wantFunc) {
+                                       return
+                               }
+                       }
+                       t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine)
+                       return
+               }
+       }
+       t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace)
+}
+
+func issue7978wait(store uint32, wait uint32) {
+       if store != 0 {
+               atomic.StoreUint32(&issue7978sync, store)
+       }
+       for atomic.LoadUint32(&issue7978sync) != wait {
+               runtime.Gosched()
+       }
+}
+
+//export issue7978cb
+func issue7978cb() {
+       // Force a stack growth from the callback to put extra
+       // pressure on the runtime. See issue #17785.
+       growStack(64)
+       issue7978wait(3, 4)
+}
+
+func growStack(n int) int {
+       var buf [128]int
+       if n == 0 {
+               return 0
+       }
+       return buf[growStack(n-1)]
+}
+
+func issue7978go() {
+       C.issue7978c((*C.uint32_t)(&issue7978sync))
+       issue7978wait(7, 8)
+}
+
+func test7978(t *testing.T) {
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gccgo can not do stack traces of C code")
+       }
+       debug.SetTraceback("2")
+       issue7978sync = 0
+       go issue7978go()
+       // test in c code, before callback
+       issue7978wait(0, 1)
+       issue7978check(t, "_Cfunc_issue7978c(", "", 1)
+       // test in go code, during callback
+       issue7978wait(2, 3)
+       issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
+       // test in c code, after callback
+       issue7978wait(4, 5)
+       issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
+       // test in go code, after return from cgo
+       issue7978wait(6, 7)
+       issue7978check(t, "test.issue7978go(", "", 3)
+       atomic.StoreUint32(&issue7978sync, 8)
+}
diff --git a/misc/cgo/test/issue7978b.go b/misc/cgo/test/issue7978b.go
new file mode 100644 (file)
index 0000000..3ab11ee
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// GCC-9.4 and above on arm64 introduced the "outline atomics" that the
+// current internal linking doesn't support.
+// See issue #39466.
+
+// +build arm64,internal
+
+package cgotest
+
+import (
+       "runtime"
+       "testing"
+)
+
+func test7978(t *testing.T) {
+       if runtime.Compiler == "gccgo" {
+               t.Skip("gccgo can not do stack traces of C code")
+       }
+
+       t.Skip("skip on arm64+internal")
+}
index 7fbc5c64b31cdbcb6e0d525e1dc6e53906479e59..08c3287c60132fd4cffb232ac6c59e655911540f 100644 (file)
@@ -12,10 +12,7 @@ package cgotest
 
 import (
        "runtime"
-       "runtime/debug"
-       "strings"
        "sync"
-       "sync/atomic"
        "testing"
        "time"
        "unsafe"
@@ -75,28 +72,6 @@ extern int CheckIssue6907C(_GoString_);
 
 extern void f7665(void);
 
-// issue 7978
-// Stack tracing didn't work during cgo code after calling a Go
-// callback.  Make sure GC works and the stack trace is correct.
-
-#include <stdint.h>
-
-void issue7978cb(void);
-
-// use ugly atomic variable sync since that doesn't require calling back into
-// Go code or OS dependencies
-static void issue7978c(uint32_t *sync) {
-       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
-               ;
-       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
-       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
-               ;
-       issue7978cb();
-       __atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
-       while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
-               ;
-}
-
 // issue 8331 part 2 - part 1 in test.go
 // A typedef of an unnamed struct is the same struct when
 // #include'd twice.  No runtime test; just make sure it compiles.
@@ -440,86 +415,6 @@ func test7665(t *testing.T) {
        }
 }
 
-// issue 7978
-
-var issue7978sync uint32
-
-func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) {
-       runtime.GC()
-       buf := make([]byte, 65536)
-       trace := string(buf[:runtime.Stack(buf, true)])
-       for _, goroutine := range strings.Split(trace, "\n\n") {
-               if strings.Contains(goroutine, "test.issue7978go") {
-                       trace := strings.Split(goroutine, "\n")
-                       // look for the expected function in the stack
-                       for i := 0; i < depth; i++ {
-                               if badFunc != "" && strings.Contains(trace[1+2*i], badFunc) {
-                                       t.Errorf("bad stack: found %s in the stack:\n%s", badFunc, goroutine)
-                                       return
-                               }
-                               if strings.Contains(trace[1+2*i], wantFunc) {
-                                       return
-                               }
-                       }
-                       t.Errorf("bad stack: didn't find %s in the stack:\n%s", wantFunc, goroutine)
-                       return
-               }
-       }
-       t.Errorf("bad stack: goroutine not found. Full stack dump:\n%s", trace)
-}
-
-func issue7978wait(store uint32, wait uint32) {
-       if store != 0 {
-               atomic.StoreUint32(&issue7978sync, store)
-       }
-       for atomic.LoadUint32(&issue7978sync) != wait {
-               runtime.Gosched()
-       }
-}
-
-//export issue7978cb
-func issue7978cb() {
-       // Force a stack growth from the callback to put extra
-       // pressure on the runtime. See issue #17785.
-       growStack(64)
-       issue7978wait(3, 4)
-}
-
-func growStack(n int) int {
-       var buf [128]int
-       if n == 0 {
-               return 0
-       }
-       return buf[growStack(n-1)]
-}
-
-func issue7978go() {
-       C.issue7978c((*C.uint32_t)(&issue7978sync))
-       issue7978wait(7, 8)
-}
-
-func test7978(t *testing.T) {
-       if runtime.Compiler == "gccgo" {
-               t.Skip("gccgo can not do stack traces of C code")
-       }
-       debug.SetTraceback("2")
-       issue7978sync = 0
-       go issue7978go()
-       // test in c code, before callback
-       issue7978wait(0, 1)
-       issue7978check(t, "_Cfunc_issue7978c(", "", 1)
-       // test in go code, during callback
-       issue7978wait(2, 3)
-       issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3)
-       // test in c code, after callback
-       issue7978wait(4, 5)
-       issue7978check(t, "_Cfunc_issue7978c(", "_cgoexpwrap", 1)
-       // test in go code, after return from cgo
-       issue7978wait(6, 7)
-       issue7978check(t, "test.issue7978go(", "", 3)
-       atomic.StoreUint32(&issue7978sync, 8)
-}
-
 // issue 8331 part 2
 
 var issue8331Var C.issue8331
index 2dc945921524abf1d14aa86618085ef30de735d8..ef0c743a680c6b13e8df907874366a1d0e34f259 100644 (file)
@@ -1145,7 +1145,7 @@ func (t *tester) cgoTest(dt *distTest) error {
                        if t.supportedBuildmode("pie") {
                                t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
                                if t.internalLink() && t.internalLinkPIE() {
-                                       t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal")
+                                       t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal")
                                }
                                t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie")
                                t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie")