]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/link: test trampolines with cgo
authorCherry Zhang <cherryyz@google.com>
Tue, 27 Apr 2021 18:57:11 +0000 (14:57 -0400)
committerCherry Zhang <cherryyz@google.com>
Thu, 29 Apr 2021 16:29:52 +0000 (16:29 +0000)
Updates #40492, #30949.

Change-Id: I6d7923ac83275c5ab08958f7a501f7975aea151a
Reviewed-on: https://go-review.googlesource.com/c/go/+/314456
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
src/cmd/link/link_test.go

index bf4c2ab91e1224213d2bda7dab73dce5742e6484..8805ff1f02cacbb4cc4db2f59af85a5ab51227a3 100644 (file)
@@ -651,6 +651,77 @@ func TestTrampoline(t *testing.T) {
        }
 }
 
+const testTrampCgoSrc = `
+package main
+
+// #include <stdio.h>
+// void CHello() { printf("hello\n"); fflush(stdout); }
+import "C"
+
+func main() {
+       C.CHello()
+}
+`
+
+func TestTrampolineCgo(t *testing.T) {
+       // Test that trampoline insertion works for cgo code.
+       // For stress test, we set -debugtramp=2 flag, which sets a very low
+       // threshold for trampoline generation, and essentially all cross-package
+       // calls will use trampolines.
+       switch runtime.GOARCH {
+       case "arm", "arm64", "ppc64", "ppc64le":
+       default:
+               t.Skipf("trampoline insertion is not implemented on %s", runtime.GOARCH)
+       }
+
+       testenv.MustHaveGoBuild(t)
+       testenv.MustHaveCGO(t)
+
+       t.Parallel()
+
+       tmpdir := t.TempDir()
+
+       src := filepath.Join(tmpdir, "hello.go")
+       err := ioutil.WriteFile(src, []byte(testTrampCgoSrc), 0666)
+       if err != nil {
+               t.Fatal(err)
+       }
+       exe := filepath.Join(tmpdir, "hello.exe")
+
+       cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2", "-o", exe, src)
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("build failed: %v\n%s", err, out)
+       }
+       cmd = exec.Command(exe)
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Errorf("executable failed to run: %v\n%s", err, out)
+       }
+       if string(out) != "hello\n" {
+               t.Errorf("unexpected output:\n%s", out)
+       }
+
+       // Test internal linking mode.
+
+       if runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || (runtime.GOARCH == "arm64" && runtime.GOOS == "windows") || !testenv.CanInternalLink() {
+               return // internal linking cgo is not supported
+       }
+       cmd = exec.Command(testenv.GoToolPath(t), "build", "-ldflags=-debugtramp=2 -linkmode=internal", "-o", exe, src)
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("build failed: %v\n%s", err, out)
+       }
+       cmd = exec.Command(exe)
+       out, err = cmd.CombinedOutput()
+       if err != nil {
+               t.Errorf("executable failed to run: %v\n%s", err, out)
+       }
+       if string(out) != "hello\n" {
+               t.Errorf("unexpected output:\n%s", out)
+       }
+}
+
 func TestIndexMismatch(t *testing.T) {
        // Test that index mismatch will cause a link-time error (not run-time error).
        // This shouldn't happen with "go build". We invoke the compiler and the linker