diff options
| author | Cherry Zhang <cherryyz@google.com> | 2021-04-27 14:57:11 -0400 |
|---|---|---|
| committer | Cherry Zhang <cherryyz@google.com> | 2021-04-29 16:29:52 +0000 |
| commit | f7c6f6210be16d6ecfdece7c283fcd4ddc28b151 (patch) | |
| tree | 89995aa0b5aeb6cb07d2b557fbc0095a1a923892 | |
| parent | 948a262455346c6035df6bd5dc36c5d4b6aca409 (diff) | |
| download | go-f7c6f6210be16d6ecfdece7c283fcd4ddc28b151.tar.xz | |
cmd/link: test trampolines with cgo
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>
| -rw-r--r-- | src/cmd/link/link_test.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index bf4c2ab91e..8805ff1f02 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -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 |
