aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/cgo/internal
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/cgo/internal')
-rw-r--r--src/cmd/cgo/internal/test/callback_windows.go109
-rw-r--r--src/cmd/cgo/internal/test/callstub_linux_ppc64le.go20
-rw-r--r--src/cmd/cgo/internal/test/issue1435.go8
-rw-r--r--src/cmd/cgo/internal/test/issue18146.go4
-rw-r--r--src/cmd/cgo/internal/test/issue4029.c2
-rw-r--r--src/cmd/cgo/internal/test/issue4029.go7
-rw-r--r--src/cmd/cgo/internal/test/issue4029w.go2
-rw-r--r--src/cmd/cgo/internal/test/issue4339.c4
-rw-r--r--src/cmd/cgo/internal/test/issue4339.h4
-rw-r--r--src/cmd/cgo/internal/test/issue8756.go4
-rw-r--r--src/cmd/cgo/internal/test/issue8756/issue8756.go4
-rw-r--r--src/cmd/cgo/internal/test/issue8828/trivial.go4
-rw-r--r--src/cmd/cgo/internal/test/issue9026/issue9026.go4
-rw-r--r--src/cmd/cgo/internal/test/issue9400/asm_mips64x.s2
-rw-r--r--src/cmd/cgo/internal/test/issue9400/asm_riscv64.s2
-rw-r--r--src/cmd/cgo/internal/test/issue9400_linux.go2
-rw-r--r--src/cmd/cgo/internal/test/issue9510a/a.go4
-rw-r--r--src/cmd/cgo/internal/test/issue9510b/b.go4
-rw-r--r--src/cmd/cgo/internal/test/linux_ppc64le_test.go13
-rw-r--r--src/cmd/cgo/internal/test/seh_internal_windows_test.go16
-rw-r--r--src/cmd/cgo/internal/test/seh_windows_test.go11
-rw-r--r--src/cmd/cgo/internal/test/stubtest_linux_ppc64le.S122
-rw-r--r--src/cmd/cgo/internal/test/test.go20
-rw-r--r--src/cmd/cgo/internal/testcshared/cshared_test.go18
-rw-r--r--src/cmd/cgo/internal/testcshared/testdata/libgo5/libgo5.go19
-rw-r--r--src/cmd/cgo/internal/testcshared/testdata/main4.c22
-rw-r--r--src/cmd/cgo/internal/testcshared/testdata/main5.c62
-rw-r--r--src/cmd/cgo/internal/testerrors/errors_test.go28
-rw-r--r--src/cmd/cgo/internal/testerrors/ptr_test.go13
-rw-r--r--src/cmd/cgo/internal/testerrors/testdata/err5.go3
-rw-r--r--src/cmd/cgo/internal/testerrors/testdata/notmatchedcfunction.go15
-rw-r--r--src/cmd/cgo/internal/testfortran/fortran_test.go16
-rw-r--r--src/cmd/cgo/internal/testfortran/testdata/testprog/fortran.go9
-rw-r--r--src/cmd/cgo/internal/testgodefs/testdata/fieldtypedef.go2
-rw-r--r--src/cmd/cgo/internal/testplugin/plugin_test.go25
-rw-r--r--src/cmd/cgo/internal/testsanitizers/cc_test.go24
-rw-r--r--src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go3
-rw-r--r--src/cmd/cgo/internal/testsanitizers/msan_test.go3
-rw-r--r--src/cmd/cgo/internal/testshared/shared_test.go10
-rw-r--r--src/cmd/cgo/internal/testshared/testdata/dep2/dep2.go6
-rw-r--r--src/cmd/cgo/internal/testshared/testdata/depBase/dep.go16
-rw-r--r--src/cmd/cgo/internal/testshared/testdata/depBaseInternal/dep.go13
-rw-r--r--src/cmd/cgo/internal/testshared/testdata/issue62277/issue62277_test.go16
-rw-r--r--src/cmd/cgo/internal/testshared/testdata/issue62277/p/p.go17
44 files changed, 611 insertions, 101 deletions
diff --git a/src/cmd/cgo/internal/test/callback_windows.go b/src/cmd/cgo/internal/test/callback_windows.go
new file mode 100644
index 0000000000..77bdfa4dd3
--- /dev/null
+++ b/src/cmd/cgo/internal/test/callback_windows.go
@@ -0,0 +1,109 @@
+// Copyright 2023 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.
+
+package cgotest
+
+/*
+#include <windows.h>
+USHORT backtrace(ULONG FramesToCapture, PVOID *BackTrace) {
+#ifdef _AMD64_
+ CONTEXT context;
+ RtlCaptureContext(&context);
+ ULONG64 ControlPc;
+ ControlPc = context.Rip;
+ int i;
+ for (i = 0; i < FramesToCapture; i++) {
+ PRUNTIME_FUNCTION FunctionEntry;
+ ULONG64 ImageBase;
+ VOID *HandlerData;
+ ULONG64 EstablisherFrame;
+
+ FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
+
+ if (!FunctionEntry) {
+ // For simplicity, don't unwind leaf entries, which are not used in this test.
+ break;
+ } else {
+ RtlVirtualUnwind(0, ImageBase, ControlPc, FunctionEntry, &context, &HandlerData, &EstablisherFrame, NULL);
+ }
+
+ ControlPc = context.Rip;
+ // Check if we left the user range.
+ if (ControlPc < 0x10000) {
+ break;
+ }
+
+ BackTrace[i] = (PVOID)(ControlPc);
+ }
+ return i;
+#else
+ return 0;
+#endif
+}
+*/
+import "C"
+
+import (
+ "internal/testenv"
+ "reflect"
+ "runtime"
+ "strings"
+ "testing"
+ "unsafe"
+)
+
+// Test that the stack can be unwound through a call out and call back
+// into Go.
+func testCallbackCallersSEH(t *testing.T) {
+ testenv.SkipIfOptimizationOff(t) // This test requires inlining.
+ if runtime.Compiler != "gc" {
+ // The exact function names are not going to be the same.
+ t.Skip("skipping for non-gc toolchain")
+ }
+ if runtime.GOARCH != "amd64" {
+ // TODO: support SEH on other architectures.
+ t.Skip("skipping on non-amd64")
+ }
+ // Only frames in the test package are checked.
+ want := []string{
+ "test._Cfunc_backtrace",
+ "test.testCallbackCallersSEH.func1.1",
+ "test.testCallbackCallersSEH.func1",
+ "test.goCallback",
+ "test._Cfunc_callback",
+ "test.nestedCall.func1",
+ "test.nestedCall",
+ "test.testCallbackCallersSEH",
+ "test.TestCallbackCallersSEH",
+ }
+ pc := make([]uintptr, 100)
+ n := 0
+ nestedCall(func() {
+ n = int(C.backtrace(C.DWORD(len(pc)), (*C.PVOID)(unsafe.Pointer(&pc[0]))))
+ })
+ got := make([]string, 0, n)
+ for i := 0; i < n; i++ {
+ f := runtime.FuncForPC(pc[i] - 1)
+ if f == nil {
+ continue
+ }
+ fname := f.Name()
+ switch fname {
+ case "goCallback":
+ // TODO(qmuntal): investigate why this function doesn't appear
+ // when using the external linker.
+ continue
+ }
+ // In module mode, this package has a fully-qualified import path.
+ // Remove it if present.
+ fname = strings.TrimPrefix(fname, "cmd/cgo/internal/")
+ if !strings.HasPrefix(fname, "test.") {
+ continue
+ }
+ got = append(got, fname)
+ }
+ if !reflect.DeepEqual(want, got) {
+ t.Errorf("incorrect backtrace:\nwant:\t%v\ngot:\t%v", want, got)
+ }
+}
diff --git a/src/cmd/cgo/internal/test/callstub_linux_ppc64le.go b/src/cmd/cgo/internal/test/callstub_linux_ppc64le.go
new file mode 100644
index 0000000000..93c29e1c7c
--- /dev/null
+++ b/src/cmd/cgo/internal/test/callstub_linux_ppc64le.go
@@ -0,0 +1,20 @@
+// Copyright 2023 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.
+
+package cgotest
+
+// extern int notoc_func(void);
+// int TestPPC64Stubs(void) {
+// return notoc_func();
+// }
+import "C"
+import "testing"
+
+func testPPC64CallStubs(t *testing.T) {
+ // Verify the trampolines run on the testing machine. If they
+ // do not, or are missing, a crash is expected.
+ if C.TestPPC64Stubs() != 0 {
+ t.Skipf("This test requires binutils 2.35 or newer.")
+ }
+}
diff --git a/src/cmd/cgo/internal/test/issue1435.go b/src/cmd/cgo/internal/test/issue1435.go
index a672e26aa0..1588d39ea9 100644
--- a/src/cmd/cgo/internal/test/issue1435.go
+++ b/src/cmd/cgo/internal/test/issue1435.go
@@ -8,6 +8,7 @@ package cgotest
import (
"fmt"
+ "internal/testenv"
"os"
"runtime"
"sort"
@@ -145,6 +146,13 @@ func test1435(t *testing.T) {
if syscall.Getuid() != 0 {
t.Skip("skipping root only test")
}
+ if testing.Short() && testenv.Builder() != "" && os.Getenv("USER") == "swarming" {
+ // The Go build system's swarming user is known not to be root.
+ // Unfortunately, it sometimes appears as root due the current
+ // implementation of a no-network check using 'unshare -n -r'.
+ // Since this test does need root to work, we need to skip it.
+ t.Skip("skipping root only test on a non-root builder")
+ }
if runtime.GOOS == "linux" {
if _, err := os.Stat("/etc/alpine-release"); err == nil {
t.Skip("skipping failing test on alpine - go.dev/issue/19938")
diff --git a/src/cmd/cgo/internal/test/issue18146.go b/src/cmd/cgo/internal/test/issue18146.go
index d302bd029f..112b7ee2e7 100644
--- a/src/cmd/cgo/internal/test/issue18146.go
+++ b/src/cmd/cgo/internal/test/issue18146.go
@@ -72,7 +72,7 @@ func test18146(t *testing.T) {
}()
}
runtime.GOMAXPROCS(threads)
- argv := append(os.Args, "-test.run=NoSuchTestExists")
+ argv := append(os.Args, "-test.run=^$")
if err := syscall.Exec(os.Args[0], argv, os.Environ()); err != nil {
t.Fatal(err)
}
@@ -85,7 +85,7 @@ func test18146(t *testing.T) {
}
}()
- args := append(append([]string(nil), os.Args[1:]...), "-test.run=Test18146")
+ args := append(append([]string(nil), os.Args[1:]...), "-test.run=^Test18146$")
for n := attempts; n > 0; n-- {
cmd := exec.Command(os.Args[0], args...)
cmd.Env = append(os.Environ(), "test18146=exec")
diff --git a/src/cmd/cgo/internal/test/issue4029.c b/src/cmd/cgo/internal/test/issue4029.c
index 212d6922f8..7a8fdc11b4 100644
--- a/src/cmd/cgo/internal/test/issue4029.c
+++ b/src/cmd/cgo/internal/test/issue4029.c
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !windows && !static && (!darwin || (!internal_pie && !arm64))
+//go:build !windows && !static && !(darwin && internal)
#include <stdint.h>
#include <dlfcn.h>
diff --git a/src/cmd/cgo/internal/test/issue4029.go b/src/cmd/cgo/internal/test/issue4029.go
index 686b7679f3..506c999bdb 100644
--- a/src/cmd/cgo/internal/test/issue4029.go
+++ b/src/cmd/cgo/internal/test/issue4029.go
@@ -2,11 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !windows && !static && (!darwin || (!internal_pie && !arm64))
+//go:build !windows && !static && !(darwin && internal)
-// Excluded in darwin internal linking PIE mode, as dynamic export is not
-// supported.
-// Excluded in internal linking mode on darwin/arm64, as it is always PIE.
+// Excluded in darwin internal linking PIE (which is the default) mode,
+// as dynamic export is not supported.
package cgotest
diff --git a/src/cmd/cgo/internal/test/issue4029w.go b/src/cmd/cgo/internal/test/issue4029w.go
index 91dad6abcb..aa4c2f59bd 100644
--- a/src/cmd/cgo/internal/test/issue4029w.go
+++ b/src/cmd/cgo/internal/test/issue4029w.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build windows || static || (darwin && internal_pie) || (darwin && arm64)
+//go:build windows || static || (darwin && internal)
package cgotest
diff --git a/src/cmd/cgo/internal/test/issue4339.c b/src/cmd/cgo/internal/test/issue4339.c
index 15d0004078..d0e64878d1 100644
--- a/src/cmd/cgo/internal/test/issue4339.c
+++ b/src/cmd/cgo/internal/test/issue4339.c
@@ -1,3 +1,7 @@
+// Copyright 2013 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.
+
#include <stdio.h>
#include "issue4339.h"
diff --git a/src/cmd/cgo/internal/test/issue4339.h b/src/cmd/cgo/internal/test/issue4339.h
index 20f6cebb6b..99a09960e2 100644
--- a/src/cmd/cgo/internal/test/issue4339.h
+++ b/src/cmd/cgo/internal/test/issue4339.h
@@ -1,3 +1,7 @@
+// Copyright 2013 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.
+
typedef struct Issue4339 Issue4339;
struct Issue4339 {
diff --git a/src/cmd/cgo/internal/test/issue8756.go b/src/cmd/cgo/internal/test/issue8756.go
index 817f449e96..d8eadfde6d 100644
--- a/src/cmd/cgo/internal/test/issue8756.go
+++ b/src/cmd/cgo/internal/test/issue8756.go
@@ -1,3 +1,7 @@
+// Copyright 2016 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.
+
package cgotest
/*
diff --git a/src/cmd/cgo/internal/test/issue8756/issue8756.go b/src/cmd/cgo/internal/test/issue8756/issue8756.go
index 223397f067..02a1424b9f 100644
--- a/src/cmd/cgo/internal/test/issue8756/issue8756.go
+++ b/src/cmd/cgo/internal/test/issue8756/issue8756.go
@@ -1,3 +1,7 @@
+// Copyright 2016 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.
+
package issue8756
/*
diff --git a/src/cmd/cgo/internal/test/issue8828/trivial.go b/src/cmd/cgo/internal/test/issue8828/trivial.go
index e7b9a4e573..9f2619654f 100644
--- a/src/cmd/cgo/internal/test/issue8828/trivial.go
+++ b/src/cmd/cgo/internal/test/issue8828/trivial.go
@@ -1,3 +1,7 @@
+// Copyright 2014 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.
+
package issue8828
//void foo();
diff --git a/src/cmd/cgo/internal/test/issue9026/issue9026.go b/src/cmd/cgo/internal/test/issue9026/issue9026.go
index ff269ca9eb..13bc180321 100644
--- a/src/cmd/cgo/internal/test/issue9026/issue9026.go
+++ b/src/cmd/cgo/internal/test/issue9026/issue9026.go
@@ -1,3 +1,7 @@
+// Copyright 2014 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.
+
package issue9026
// This file appears in its own package since the assertion tests the
diff --git a/src/cmd/cgo/internal/test/issue9400/asm_mips64x.s b/src/cmd/cgo/internal/test/issue9400/asm_mips64x.s
index 1f492eafe9..3edba3dd82 100644
--- a/src/cmd/cgo/internal/test/issue9400/asm_mips64x.s
+++ b/src/cmd/cgo/internal/test/issue9400/asm_mips64x.s
@@ -1,4 +1,4 @@
-// Copyright 2016 The Go Authors. All rights reserved.
+// Copyright 2016 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.
diff --git a/src/cmd/cgo/internal/test/issue9400/asm_riscv64.s b/src/cmd/cgo/internal/test/issue9400/asm_riscv64.s
index fa34f6bd37..0f10e3a326 100644
--- a/src/cmd/cgo/internal/test/issue9400/asm_riscv64.s
+++ b/src/cmd/cgo/internal/test/issue9400/asm_riscv64.s
@@ -1,4 +1,4 @@
-// Copyright 2020 The Go Authors. All rights reserved.
+// 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.
diff --git a/src/cmd/cgo/internal/test/issue9400_linux.go b/src/cmd/cgo/internal/test/issue9400_linux.go
index 1511e25876..41b9ab9dc7 100644
--- a/src/cmd/cgo/internal/test/issue9400_linux.go
+++ b/src/cmd/cgo/internal/test/issue9400_linux.go
@@ -48,7 +48,7 @@ func test9400(t *testing.T) {
}
// Disable GC for the duration of the test.
- // This avoids a potential GC deadlock when spinning in uninterruptable ASM below #49695.
+ // This avoids a potential GC deadlock when spinning in uninterruptible ASM below #49695.
defer debug.SetGCPercent(debug.SetGCPercent(-1))
// SetGCPercent waits until the mark phase is over, but the runtime
// also preempts at the start of the sweep phase, so make sure that's
diff --git a/src/cmd/cgo/internal/test/issue9510a/a.go b/src/cmd/cgo/internal/test/issue9510a/a.go
index 1a5224b8c6..f0a0128d10 100644
--- a/src/cmd/cgo/internal/test/issue9510a/a.go
+++ b/src/cmd/cgo/internal/test/issue9510a/a.go
@@ -1,3 +1,7 @@
+// Copyright 2015 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.
+
package issue9510a
/*
diff --git a/src/cmd/cgo/internal/test/issue9510b/b.go b/src/cmd/cgo/internal/test/issue9510b/b.go
index 5016b39597..6e22508c32 100644
--- a/src/cmd/cgo/internal/test/issue9510b/b.go
+++ b/src/cmd/cgo/internal/test/issue9510b/b.go
@@ -1,3 +1,7 @@
+// Copyright 2015 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.
+
package issue9510b
/*
diff --git a/src/cmd/cgo/internal/test/linux_ppc64le_test.go b/src/cmd/cgo/internal/test/linux_ppc64le_test.go
new file mode 100644
index 0000000000..67b6b161d6
--- /dev/null
+++ b/src/cmd/cgo/internal/test/linux_ppc64le_test.go
@@ -0,0 +1,13 @@
+// Copyright 2023 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.
+
+//go:build ppc64le && linux && cgo
+
+package cgotest
+
+import "testing"
+
+func TestPPC64CallStubs(t *testing.T) {
+ testPPC64CallStubs(t)
+}
diff --git a/src/cmd/cgo/internal/test/seh_internal_windows_test.go b/src/cmd/cgo/internal/test/seh_internal_windows_test.go
new file mode 100644
index 0000000000..708ffdc6f6
--- /dev/null
+++ b/src/cmd/cgo/internal/test/seh_internal_windows_test.go
@@ -0,0 +1,16 @@
+// Copyright 2024 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.
+
+//go:build cgo && windows && internal
+
+package cgotest
+
+import (
+ "internal/testenv"
+ "testing"
+)
+
+func TestCallbackCallersSEH(t *testing.T) {
+ testenv.SkipFlaky(t, 65116)
+}
diff --git a/src/cmd/cgo/internal/test/seh_windows_test.go b/src/cmd/cgo/internal/test/seh_windows_test.go
new file mode 100644
index 0000000000..4a8d5bbd4d
--- /dev/null
+++ b/src/cmd/cgo/internal/test/seh_windows_test.go
@@ -0,0 +1,11 @@
+// Copyright 2023 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.
+
+//go:build cgo && windows && !internal
+
+package cgotest
+
+import "testing"
+
+func TestCallbackCallersSEH(t *testing.T) { testCallbackCallersSEH(t) }
diff --git a/src/cmd/cgo/internal/test/stubtest_linux_ppc64le.S b/src/cmd/cgo/internal/test/stubtest_linux_ppc64le.S
new file mode 100644
index 0000000000..0c519705a5
--- /dev/null
+++ b/src/cmd/cgo/internal/test/stubtest_linux_ppc64le.S
@@ -0,0 +1,122 @@
+// Copyright 2023 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.
+
+// When linking C ELFv2 objects, the Go linker may need to insert calling stubs.
+// A call stub is usually needed when the ELFv2 st_other attribute is different
+// between caller and callee.
+//
+// The type of call stub inserted will vary depending on GOPPC64 and the
+// buildmode (e.g pie builds shared code, default builds fixed-position code).
+// CI is set up to run for P8 and P10 machines, and this test is run in both
+// pie and default modes.
+//
+// Several functions are written with interesting st_other attributes, and
+// call each other to test various calling combinations which require stubs.
+//
+// The call tree is as follows, starting from TestPPC64Stubs (A C function):
+// TestPPC64Stubs (compiled PIC by default by Go)
+// notoc_func [called TOC -> NOTOC (but R2 is preserved)]
+// toc_func [called NOTOC -> TOC]
+// notoc_nor2_func [called TOC -> NOTOC]
+// random [dynamic TOC call]
+// random [dynamic NOTOC call]
+//
+// Depending on the GOPPC64/buildmode used, and type of call, one of 7 stubs may need inserted:
+//
+// TOC -> NOTOC: Save R2, call global entry. (valid for any GOPPC64)
+// TOC save slot is rewrittent to restore TOC.
+// NOTOC -> TOC [P10]: A PIC call stub using P10 instructions to call the global entry
+// NOTOC -> TOC [P8]: A PIC call stub using P8 instructions to call the global entry
+//
+// TOC -> dynamic: A PLT call stub is generated which saves R2.
+// TOC save slot is rewritten to restore TOC.
+// NOTOC -> dynamic [P10]: A stub using pcrel instructions is generated.
+// NOTOC -> dynamic [P8/default]: A P8 compatible, non-PIC stub is generated
+// NOTOC -> dynamic [P8/pie]: A P8 compatible, PIC stub is generated
+//
+//
+// Some notes about other cases:
+// TOC -> TOC, NOTOC -> NOTOC, NOTOC -> TOC local calls do not require require call stubs.
+// TOC -> NOTOC (R2 is preserved, st_other==0): A special case where a call stub is not needed.
+
+// This test requires a binutils with power10 and ELFv2 1.5 support. This is earliest verified version.
+.if .gasversion. >= 23500
+
+// A function which does not guarantee R2 is preserved.
+// R2 is clobbered here to ensure the stubs preserve it.
+ .globl notoc_nor2_func
+ .type notoc_nor2_func, @function
+notoc_nor2_func:
+ .localentry notoc_nor2_func,1
+ li 2,0
+ blr
+
+// A function which expects R2 to hold TOC, and has a distinct local entry.
+ .globl toc_func
+ .type toc_func, @function
+toc_func:
+ addis 2,12,.TOC.-toc_func@ha
+ addi 2,2,.TOC.-toc_func@l
+ .localentry toc_func, .-toc_func
+ mflr 0
+ std 0,16(1)
+ stdu 1,-32(1)
+
+ // Call a NOTOC function which clobbers R2.
+ bl notoc_nor2_func
+ nop
+
+ // Call libc random. This should generate a TOC relative plt stub.
+ bl random
+ nop
+
+ addi 1,1,32
+ ld 0,16(1)
+ mtlr 0
+ blr
+
+// An ELFv2 st_other==0 function. It preserves R2 (TOC), but does not use it.
+ .globl notoc_func
+ .type notoc_func, @function
+notoc_func:
+ // Save R2 and LR and stack a frame.
+ mflr 0
+ std 0,16(1)
+ stdu 1,-32(1)
+
+ // Save R2 in TOC save slot.
+ std 2,24(1)
+
+ // clobber R2
+ li 2,0
+
+ // Call type2_func. A call stub from notoc to toc should be inserted.
+ bl toc_func@notoc
+
+ // Call libc random. A notoc plt stub should be inserted.
+ bl random@notoc
+
+ // Return 0 to indicate the test ran.
+ li 3,0
+
+ // Restore R2
+ ld 2,24(1)
+
+ // Restore LR and pop stack
+ addi 1,1,32
+ ld 0,16(1)
+ mtlr 0
+ blr
+
+.else
+
+// A stub for older binutils
+ .globl notoc_func
+ .type notoc_func, @function
+notoc_func:
+ // Return 1 to indicate the test was skipped.
+ li 3,1
+ blr
+
+.endif
diff --git a/src/cmd/cgo/internal/test/test.go b/src/cmd/cgo/internal/test/test.go
index 7da5a856b3..9b3790eb11 100644
--- a/src/cmd/cgo/internal/test/test.go
+++ b/src/cmd/cgo/internal/test/test.go
@@ -115,6 +115,14 @@ int add(int x, int y) {
return x+y;
};
+// escape vs noescape
+
+// TODO(#56378): enable in Go 1.23:
+// #cgo noescape handleGoStringPointerNoescape
+void handleGoStringPointerNoescape(void *s) {}
+
+void handleGoStringPointerEscape(void *s) {}
+
// Following mimics vulkan complex definitions for benchmarking cgocheck overhead.
typedef uint32_t VkFlags;
@@ -1106,6 +1114,18 @@ func benchCgoCall(b *testing.B) {
C.handleComplexPointer(&a0)
}
})
+ b.Run("string-pointer-escape", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var s string
+ C.handleGoStringPointerEscape(unsafe.Pointer(&s))
+ }
+ })
+ b.Run("string-pointer-noescape", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ var s string
+ C.handleGoStringPointerNoescape(unsafe.Pointer(&s))
+ }
+ })
b.Run("eight-pointers", func(b *testing.B) {
var a0, a1, a2, a3, a4, a5, a6, a7 C.VkDeviceCreateInfo
for i := 0; i < b.N; i++ {
diff --git a/src/cmd/cgo/internal/testcshared/cshared_test.go b/src/cmd/cgo/internal/testcshared/cshared_test.go
index 7fe6782b9e..7e9a274d05 100644
--- a/src/cmd/cgo/internal/testcshared/cshared_test.go
+++ b/src/cmd/cgo/internal/testcshared/cshared_test.go
@@ -182,6 +182,8 @@ func run(t *testing.T, extraEnv []string, args ...string) string {
if len(extraEnv) > 0 {
cmd.Env = append(os.Environ(), extraEnv...)
}
+ stderr := new(strings.Builder)
+ cmd.Stderr = stderr
if GOOS != "windows" {
// TestUnexportedSymbols relies on file descriptor 30
@@ -192,11 +194,13 @@ func run(t *testing.T, extraEnv []string, args ...string) string {
cmd.ExtraFiles = make([]*os.File, 28)
}
- out, err := cmd.CombinedOutput()
+ t.Logf("run: %v", args)
+ out, err := cmd.Output()
+ if stderr.Len() > 0 {
+ t.Logf("stderr:\n%s", stderr)
+ }
if err != nil {
t.Fatalf("command failed: %v\n%v\n%s\n", args, err, out)
- } else {
- t.Logf("run: %v", args)
}
return string(out)
}
@@ -602,9 +606,13 @@ func testSignalHandlers(t *testing.T, pkgname, cfile, cmd string) {
defer os.Remove(bin)
defer os.Remove(pkgname + ".h")
- out := runExe(t, nil, bin, "./"+libname)
+ args := []string{bin, "./" + libname}
+ if testing.Verbose() {
+ args = append(args, "verbose")
+ }
+ out := runExe(t, nil, args...)
if strings.TrimSpace(out) != "PASS" {
- t.Error(run(t, nil, bin, libname, "verbose"))
+ t.Errorf("%v%s", args, out)
}
}
diff --git a/src/cmd/cgo/internal/testcshared/testdata/libgo5/libgo5.go b/src/cmd/cgo/internal/testcshared/testdata/libgo5/libgo5.go
index 4ca44e5894..c70dd681fa 100644
--- a/src/cmd/cgo/internal/testcshared/testdata/libgo5/libgo5.go
+++ b/src/cmd/cgo/internal/testcshared/testdata/libgo5/libgo5.go
@@ -31,15 +31,24 @@ func ResetSIGIO() {
signal.Reset(syscall.SIGIO)
}
-// SawSIGIO returns whether we saw a SIGIO within a brief pause.
+// AwaitSIGIO blocks indefinitely until a SIGIO is reported.
+//
+//export AwaitSIGIO
+func AwaitSIGIO() {
+ <-sigioChan
+}
+
+// SawSIGIO reports whether we saw a SIGIO within a brief pause.
//
//export SawSIGIO
-func SawSIGIO() C.int {
+func SawSIGIO() bool {
+ timer := time.NewTimer(100 * time.Millisecond)
select {
case <-sigioChan:
- return 1
- case <-time.After(100 * time.Millisecond):
- return 0
+ timer.Stop()
+ return true
+ case <-timer.C:
+ return false
}
}
diff --git a/src/cmd/cgo/internal/testcshared/testdata/main4.c b/src/cmd/cgo/internal/testcshared/testdata/main4.c
index 6c16364070..467a611ae7 100644
--- a/src/cmd/cgo/internal/testcshared/testdata/main4.c
+++ b/src/cmd/cgo/internal/testcshared/testdata/main4.c
@@ -88,7 +88,7 @@ int main(int argc, char** argv) {
setsid();
if (verbose) {
- printf("calling sigaction\n");
+ fprintf(stderr, "calling sigaction\n");
}
memset(&sa, 0, sizeof sa);
@@ -107,7 +107,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling dlopen\n");
+ fprintf(stderr, "calling dlopen\n");
}
handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
@@ -117,7 +117,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling dlsym\n");
+ fprintf(stderr, "calling dlsym\n");
}
// Start some goroutines.
@@ -128,7 +128,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling RunGoroutines\n");
+ fprintf(stderr, "calling RunGoroutines\n");
}
fn();
@@ -137,7 +137,7 @@ int main(int argc, char** argv) {
// will be delivered to a goroutine.
if (verbose) {
- printf("calling pthread_sigmask\n");
+ fprintf(stderr, "calling pthread_sigmask\n");
}
if (sigemptyset(&mask) < 0) {
@@ -153,7 +153,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling kill\n");
+ fprintf(stderr, "calling kill\n");
}
if (kill(0, SIGIO) < 0) {
@@ -161,7 +161,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("waiting for sigioSeen\n");
+ fprintf(stderr, "waiting for sigioSeen\n");
}
// Wait until the signal has been delivered.
@@ -178,13 +178,13 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling setjmp\n");
+ fprintf(stderr, "calling setjmp\n");
}
// Test that a SIGSEGV on this thread is delivered to us.
if (setjmp(jmp) == 0) {
if (verbose) {
- printf("triggering SIGSEGV\n");
+ fprintf(stderr, "triggering SIGSEGV\n");
}
*nullPointer = '\0';
@@ -194,7 +194,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling dlsym\n");
+ fprintf(stderr, "calling dlsym\n");
}
// Make sure that a SIGSEGV in Go causes a run-time panic.
@@ -205,7 +205,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling TestSEGV\n");
+ fprintf(stderr, "calling TestSEGV\n");
}
fn();
diff --git a/src/cmd/cgo/internal/testcshared/testdata/main5.c b/src/cmd/cgo/internal/testcshared/testdata/main5.c
index e7bebab1ad..563329e331 100644
--- a/src/cmd/cgo/internal/testcshared/testdata/main5.c
+++ b/src/cmd/cgo/internal/testcshared/testdata/main5.c
@@ -7,6 +7,7 @@
// This is a lot like ../testcarchive/main3.c.
#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -29,8 +30,10 @@ int main(int argc, char** argv) {
int verbose;
struct sigaction sa;
void* handle;
- void (*fn1)(void);
- int (*sawSIGIO)(void);
+ void (*catchSIGIO)(void);
+ void (*resetSIGIO)(void);
+ void (*awaitSIGIO)();
+ bool (*sawSIGIO)();
int i;
struct timespec ts;
@@ -38,7 +41,7 @@ int main(int argc, char** argv) {
setvbuf(stdout, NULL, _IONBF, 0);
if (verbose) {
- printf("calling sigaction\n");
+ fprintf(stderr, "calling sigaction\n");
}
memset(&sa, 0, sizeof sa);
@@ -52,7 +55,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling dlopen\n");
+ fprintf(stderr, "calling dlopen\n");
}
handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL);
@@ -65,7 +68,7 @@ int main(int argc, char** argv) {
// installed for SIGIO.
if (verbose) {
- printf("raising SIGIO\n");
+ fprintf(stderr, "raising SIGIO\n");
}
if (raise(SIGIO) < 0) {
@@ -73,7 +76,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("waiting for sigioSeen\n");
+ fprintf(stderr, "waiting for sigioSeen\n");
}
// Wait until the signal has been delivered.
@@ -94,23 +97,23 @@ int main(int argc, char** argv) {
// Tell the Go code to catch SIGIO.
if (verbose) {
- printf("calling dlsym\n");
+ fprintf(stderr, "calling dlsym\n");
}
- fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO");
- if (fn1 == NULL) {
+ catchSIGIO = (void(*)(void))dlsym(handle, "CatchSIGIO");
+ if (catchSIGIO == NULL) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
if (verbose) {
- printf("calling CatchSIGIO\n");
+ fprintf(stderr, "calling CatchSIGIO\n");
}
- fn1();
+ catchSIGIO();
if (verbose) {
- printf("raising SIGIO\n");
+ fprintf(stderr, "raising SIGIO\n");
}
if (raise(SIGIO) < 0) {
@@ -118,24 +121,21 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling dlsym\n");
+ fprintf(stderr, "calling dlsym\n");
}
// Check that the Go code saw SIGIO.
- sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO");
- if (sawSIGIO == NULL) {
+ awaitSIGIO = (void (*)(void))dlsym(handle, "AwaitSIGIO");
+ if (awaitSIGIO == NULL) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
if (verbose) {
- printf("calling SawSIGIO\n");
+ fprintf(stderr, "calling AwaitSIGIO\n");
}
- if (!sawSIGIO()) {
- fprintf(stderr, "Go handler did not see SIGIO\n");
- exit(EXIT_FAILURE);
- }
+ awaitSIGIO();
if (sigioSeen != 0) {
fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n");
@@ -145,23 +145,29 @@ int main(int argc, char** argv) {
// Tell the Go code to stop catching SIGIO.
if (verbose) {
- printf("calling dlsym\n");
+ fprintf(stderr, "calling dlsym\n");
}
- fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO");
- if (fn1 == NULL) {
+ resetSIGIO = (void (*)(void))dlsym(handle, "ResetSIGIO");
+ if (resetSIGIO == NULL) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
if (verbose) {
- printf("calling ResetSIGIO\n");
+ fprintf(stderr, "calling ResetSIGIO\n");
}
- fn1();
+ resetSIGIO();
+
+ sawSIGIO = (bool (*)(void))dlsym(handle, "SawSIGIO");
+ if (sawSIGIO == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ exit(EXIT_FAILURE);
+ }
if (verbose) {
- printf("raising SIGIO\n");
+ fprintf(stderr, "raising SIGIO\n");
}
if (raise(SIGIO) < 0) {
@@ -169,7 +175,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("calling SawSIGIO\n");
+ fprintf(stderr, "calling SawSIGIO\n");
}
if (sawSIGIO()) {
@@ -178,7 +184,7 @@ int main(int argc, char** argv) {
}
if (verbose) {
- printf("waiting for sigioSeen\n");
+ fprintf(stderr, "waiting for sigioSeen\n");
}
// Wait until the signal has been delivered.
diff --git a/src/cmd/cgo/internal/testerrors/errors_test.go b/src/cmd/cgo/internal/testerrors/errors_test.go
index 870d05b491..86236249ca 100644
--- a/src/cmd/cgo/internal/testerrors/errors_test.go
+++ b/src/cmd/cgo/internal/testerrors/errors_test.go
@@ -39,16 +39,23 @@ func check(t *testing.T, file string) {
continue
}
- _, frag, ok := bytes.Cut(line, []byte("ERROR HERE: "))
- if !ok {
- continue
+ if _, frag, ok := bytes.Cut(line, []byte("ERROR HERE: ")); ok {
+ re, err := regexp.Compile(fmt.Sprintf(":%d:.*%s", i+1, frag))
+ if err != nil {
+ t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frag)
+ continue
+ }
+ errors = append(errors, re)
}
- re, err := regexp.Compile(fmt.Sprintf(":%d:.*%s", i+1, frag))
- if err != nil {
- t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frag)
- continue
+
+ if _, frag, ok := bytes.Cut(line, []byte("ERROR MESSAGE: ")); ok {
+ re, err := regexp.Compile(string(frag))
+ if err != nil {
+ t.Errorf("Invalid regexp after `ERROR MESSAGE: `: %#q", frag)
+ continue
+ }
+ errors = append(errors, re)
}
- errors = append(errors, re)
}
if len(errors) == 0 {
t.Fatalf("cannot find ERROR HERE")
@@ -166,3 +173,8 @@ func TestMallocCrashesOnNil(t *testing.T) {
t.Fatalf("succeeded unexpectedly")
}
}
+
+func TestNotMatchedCFunction(t *testing.T) {
+ file := "notmatchedcfunction.go"
+ check(t, file)
+}
diff --git a/src/cmd/cgo/internal/testerrors/ptr_test.go b/src/cmd/cgo/internal/testerrors/ptr_test.go
index 7f56501c58..8fff7615d3 100644
--- a/src/cmd/cgo/internal/testerrors/ptr_test.go
+++ b/src/cmd/cgo/internal/testerrors/ptr_test.go
@@ -14,7 +14,6 @@ import (
"os"
"os/exec"
"path/filepath"
- "runtime"
"slices"
"strings"
"sync/atomic"
@@ -253,7 +252,10 @@ var ptrTests = []ptrTest{
{
// Exported functions may not return Go pointers.
name: "export1",
- c: `extern unsigned char *GoFn21();`,
+ c: `#ifdef _WIN32
+ __declspec(dllexport)
+ #endif
+ extern unsigned char *GoFn21();`,
support: `//export GoFn21
func GoFn21() *byte { return new(byte) }`,
body: `C.GoFn21()`,
@@ -263,6 +265,9 @@ var ptrTests = []ptrTest{
// Returning a C pointer is fine.
name: "exportok",
c: `#include <stdlib.h>
+ #ifdef _WIN32
+ __declspec(dllexport)
+ #endif
extern unsigned char *GoFn22();`,
support: `//export GoFn22
func GoFn22() *byte { return (*byte)(C.malloc(1)) }`,
@@ -472,10 +477,6 @@ var ptrTests = []ptrTest{
func TestPointerChecks(t *testing.T) {
testenv.MustHaveGoBuild(t)
testenv.MustHaveCGO(t)
- if runtime.GOOS == "windows" {
- // TODO: Skip just the cases that fail?
- t.Skipf("some tests fail to build on %s", runtime.GOOS)
- }
var gopath string
var dir string
diff --git a/src/cmd/cgo/internal/testerrors/testdata/err5.go b/src/cmd/cgo/internal/testerrors/testdata/err5.go
index 779d745ba7..c12a290d38 100644
--- a/src/cmd/cgo/internal/testerrors/testdata/err5.go
+++ b/src/cmd/cgo/internal/testerrors/testdata/err5.go
@@ -5,6 +5,7 @@
package main
//line /tmp/_cgo_.go:1
-//go:cgo_dynamic_linker "/elf/interp" // ERROR HERE: only allowed in cgo-generated code
+//go:cgo_dynamic_linker "/elf/interp"
+// ERROR MESSAGE: only allowed in cgo-generated code
func main() {}
diff --git a/src/cmd/cgo/internal/testerrors/testdata/notmatchedcfunction.go b/src/cmd/cgo/internal/testerrors/testdata/notmatchedcfunction.go
new file mode 100644
index 0000000000..5ec9ec5d4a
--- /dev/null
+++ b/src/cmd/cgo/internal/testerrors/testdata/notmatchedcfunction.go
@@ -0,0 +1,15 @@
+// Copyright 2023 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.
+
+package main
+
+/*
+// TODO(#56378): change back to "#cgo noescape noMatchedCFunction: no matched C function" in Go 1.23
+// ERROR MESSAGE: #cgo noescape disabled until Go 1.23
+#cgo noescape noMatchedCFunction
+*/
+import "C"
+
+func main() {
+}
diff --git a/src/cmd/cgo/internal/testfortran/fortran_test.go b/src/cmd/cgo/internal/testfortran/fortran_test.go
index eaa36ac7f9..0eae7c5f53 100644
--- a/src/cmd/cgo/internal/testfortran/fortran_test.go
+++ b/src/cmd/cgo/internal/testfortran/fortran_test.go
@@ -5,7 +5,6 @@
package fortran
import (
- "fmt"
"internal/testenv"
"os"
"os/exec"
@@ -75,11 +74,18 @@ func TestFortran(t *testing.T) {
// Finally, run the actual test.
t.Log("go", "run", "./testdata/testprog")
- out, err := exec.Command("go", "run", "./testdata/testprog").CombinedOutput()
- if err == nil && string(out) != "ok\n" {
- err = fmt.Errorf("expected ok")
+ var stdout, stderr strings.Builder
+ cmd := exec.Command("go", "run", "./testdata/testprog")
+ cmd.Stdout = &stdout
+ cmd.Stderr = &stderr
+ err := cmd.Run()
+ t.Logf("%v", cmd)
+ if stderr.Len() != 0 {
+ t.Logf("stderr:\n%s", stderr.String())
}
if err != nil {
- t.Errorf("%s\nOutput:\n%s", err, string(out))
+ t.Errorf("%v\n%s", err, stdout.String())
+ } else if stdout.String() != "ok\n" {
+ t.Errorf("stdout:\n%s\nwant \"ok\"", stdout.String())
}
}
diff --git a/src/cmd/cgo/internal/testfortran/testdata/testprog/fortran.go b/src/cmd/cgo/internal/testfortran/testdata/testprog/fortran.go
index d8004ceb6d..e98d76c3e6 100644
--- a/src/cmd/cgo/internal/testfortran/testdata/testprog/fortran.go
+++ b/src/cmd/cgo/internal/testfortran/testdata/testprog/fortran.go
@@ -6,7 +6,10 @@ package main
// int the_answer();
import "C"
-import "os"
+import (
+ "fmt"
+ "os"
+)
func TheAnswer() int {
return int(C.the_answer())
@@ -14,8 +17,8 @@ func TheAnswer() int {
func main() {
if a := TheAnswer(); a != 42 {
- println("Unexpected result for The Answer. Got:", a, " Want: 42")
+ fmt.Fprintln(os.Stderr, "Unexpected result for The Answer. Got:", a, " Want: 42")
os.Exit(1)
}
- println("ok")
+ fmt.Fprintln(os.Stdout, "ok")
}
diff --git a/src/cmd/cgo/internal/testgodefs/testdata/fieldtypedef.go b/src/cmd/cgo/internal/testgodefs/testdata/fieldtypedef.go
index b0c507477f..d3ab1902c1 100644
--- a/src/cmd/cgo/internal/testgodefs/testdata/fieldtypedef.go
+++ b/src/cmd/cgo/internal/testgodefs/testdata/fieldtypedef.go
@@ -1,4 +1,4 @@
-// Copyright 2018 The Go Authors. All rights reserve d.
+// Copyright 2018 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.
diff --git a/src/cmd/cgo/internal/testplugin/plugin_test.go b/src/cmd/cgo/internal/testplugin/plugin_test.go
index 7f5b1bf4f5..1e32ff8a06 100644
--- a/src/cmd/cgo/internal/testplugin/plugin_test.go
+++ b/src/cmd/cgo/internal/testplugin/plugin_test.go
@@ -367,25 +367,16 @@ func TestForkExec(t *testing.T) {
t.Parallel()
goCmd(t, "build", "-o", "forkexec.exe", "./forkexec/main.go")
- var cmd *exec.Cmd
- done := make(chan int, 1)
-
- go func() {
- for i := 0; i < 100; i++ {
- cmd = exec.Command("./forkexec.exe", "1")
- err := cmd.Run()
- if err != nil {
- t.Errorf("running command failed: %v", err)
- break
+ for i := 0; i < 100; i++ {
+ cmd := testenv.Command(t, "./forkexec.exe", "1")
+ err := cmd.Run()
+ if err != nil {
+ if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
+ t.Logf("stderr:\n%s", ee.Stderr)
}
+ t.Errorf("running command failed: %v", err)
+ break
}
- done <- 1
- }()
- select {
- case <-done:
- case <-time.After(5 * time.Minute):
- cmd.Process.Kill()
- t.Fatalf("subprocess hang")
}
}
diff --git a/src/cmd/cgo/internal/testsanitizers/cc_test.go b/src/cmd/cgo/internal/testsanitizers/cc_test.go
index 6eb5a64f9b..e650de835a 100644
--- a/src/cmd/cgo/internal/testsanitizers/cc_test.go
+++ b/src/cmd/cgo/internal/testsanitizers/cc_test.go
@@ -16,8 +16,10 @@ import (
"encoding/json"
"errors"
"fmt"
+ "internal/testenv"
"os"
"os/exec"
+ "os/user"
"path/filepath"
"regexp"
"strconv"
@@ -266,12 +268,28 @@ func compilerSupportsLocation() bool {
case "gcc":
return compiler.major >= 10
case "clang":
+ // TODO(65606): The clang toolchain on the LUCI builders is not built against
+ // zlib, the ASAN runtime can't actually symbolize its own stack trace. Once
+ // this is resolved, one way or another, switch this back to 'true'. We still
+ // have coverage from the 'gcc' case above.
+ if inLUCIBuild() {
+ return false
+ }
return true
default:
return false
}
}
+// inLUCIBuild returns true if we're currently executing in a LUCI build.
+func inLUCIBuild() bool {
+ u, err := user.Current()
+ if err != nil {
+ return false
+ }
+ return testenv.Builder() != "" && u.Username == "swarming"
+}
+
// compilerRequiredTsanVersion reports whether the compiler is the version required by Tsan.
// Only restrictions for ppc64le are known; otherwise return true.
func compilerRequiredTsanVersion(goos, goarch string) bool {
@@ -293,11 +311,17 @@ func compilerRequiredAsanVersion(goos, goarch string) bool {
}
switch compiler.name {
case "gcc":
+ if goarch == "loong64" {
+ return compiler.major >= 14
+ }
if goarch == "ppc64le" {
return compiler.major >= 9
}
return compiler.major >= 7
case "clang":
+ if goarch == "loong64" {
+ return compiler.major >= 16
+ }
return compiler.major >= 9
default:
return false
diff --git a/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go b/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go
index f84c9f37ae..3f5b1d91c7 100644
--- a/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go
+++ b/src/cmd/cgo/internal/testsanitizers/libfuzzer_test.go
@@ -7,11 +7,14 @@
package sanitizers_test
import (
+ "internal/testenv"
"strings"
"testing"
)
func TestLibFuzzer(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+ testenv.MustHaveCGO(t)
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
diff --git a/src/cmd/cgo/internal/testsanitizers/msan_test.go b/src/cmd/cgo/internal/testsanitizers/msan_test.go
index 1a22b5246c..83d66f6660 100644
--- a/src/cmd/cgo/internal/testsanitizers/msan_test.go
+++ b/src/cmd/cgo/internal/testsanitizers/msan_test.go
@@ -8,11 +8,14 @@ package sanitizers_test
import (
"internal/platform"
+ "internal/testenv"
"strings"
"testing"
)
func TestMSAN(t *testing.T) {
+ testenv.MustHaveGoBuild(t)
+ testenv.MustHaveCGO(t)
goos, err := goEnv("GOOS")
if err != nil {
t.Fatal(err)
diff --git a/src/cmd/cgo/internal/testshared/shared_test.go b/src/cmd/cgo/internal/testshared/shared_test.go
index 796c46b9bf..814b9994f8 100644
--- a/src/cmd/cgo/internal/testshared/shared_test.go
+++ b/src/cmd/cgo/internal/testshared/shared_test.go
@@ -96,6 +96,10 @@ func goCmd(t *testing.T, args ...string) string {
// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
func testMain(m *testing.M) (int, error) {
+ if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
+ globalSkip = func(t testing.TB) { t.Skip("short mode and $GO_BUILDER_NAME not set") }
+ return m.Run(), nil
+ }
if !platform.BuildModeSupported(runtime.Compiler, "shared", runtime.GOOS, runtime.GOARCH) {
globalSkip = func(t testing.TB) { t.Skip("shared build mode not supported") }
return m.Run(), nil
@@ -1155,6 +1159,12 @@ func TestIssue47873(t *testing.T) {
goCmd(t, "run", "-linkshared", "./issue47837/main")
}
+func TestIssue62277(t *testing.T) {
+ globalSkip(t)
+ goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue62277/p")
+ goCmd(t, "test", "-linkshared", "./issue62277")
+}
+
// Test that we can build std in shared mode.
func TestStd(t *testing.T) {
if testing.Short() {
diff --git a/src/cmd/cgo/internal/testshared/testdata/dep2/dep2.go b/src/cmd/cgo/internal/testshared/testdata/dep2/dep2.go
index 94f38cf507..18d774b5fc 100644
--- a/src/cmd/cgo/internal/testshared/testdata/dep2/dep2.go
+++ b/src/cmd/cgo/internal/testshared/testdata/dep2/dep2.go
@@ -2,6 +2,12 @@ package dep2
import "testshared/depBase"
+func init() {
+ if !depBase.Initialized {
+ panic("depBase not initialized")
+ }
+}
+
var W int = 1
var hasProg depBase.HasProg
diff --git a/src/cmd/cgo/internal/testshared/testdata/depBase/dep.go b/src/cmd/cgo/internal/testshared/testdata/depBase/dep.go
index e7cc7c81eb..a143fe2ff1 100644
--- a/src/cmd/cgo/internal/testshared/testdata/depBase/dep.go
+++ b/src/cmd/cgo/internal/testshared/testdata/depBase/dep.go
@@ -7,8 +7,24 @@ package depBase
import (
"os"
"reflect"
+
+ "testshared/depBaseInternal"
)
+// Issue 61973: indirect dependencies are not initialized.
+func init() {
+ if !depBaseInternal.Initialized {
+ panic("depBaseInternal not initialized")
+ }
+ if os.Stdout == nil {
+ panic("os.Stdout is nil")
+ }
+
+ Initialized = true
+}
+
+var Initialized bool
+
var SlicePtr interface{} = &[]int{}
var V int = 1
diff --git a/src/cmd/cgo/internal/testshared/testdata/depBaseInternal/dep.go b/src/cmd/cgo/internal/testshared/testdata/depBaseInternal/dep.go
new file mode 100644
index 0000000000..906bff09c4
--- /dev/null
+++ b/src/cmd/cgo/internal/testshared/testdata/depBaseInternal/dep.go
@@ -0,0 +1,13 @@
+// Copyright 2023 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.
+
+// depBaseInternal is only imported by depBase.
+
+package depBaseInternal
+
+var Initialized bool
+
+func init() {
+ Initialized = true
+}
diff --git a/src/cmd/cgo/internal/testshared/testdata/issue62277/issue62277_test.go b/src/cmd/cgo/internal/testshared/testdata/issue62277/issue62277_test.go
new file mode 100644
index 0000000000..89a0601c9b
--- /dev/null
+++ b/src/cmd/cgo/internal/testshared/testdata/issue62277/issue62277_test.go
@@ -0,0 +1,16 @@
+// Copyright 2023 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.
+
+package issue62277_test
+
+import (
+ "testing"
+
+ "testshared/issue62277/p"
+)
+
+func TestIssue62277(t *testing.T) {
+ t.Log(p.S)
+ t.Log(p.T)
+}
diff --git a/src/cmd/cgo/internal/testshared/testdata/issue62277/p/p.go b/src/cmd/cgo/internal/testshared/testdata/issue62277/p/p.go
new file mode 100644
index 0000000000..97bde0c10f
--- /dev/null
+++ b/src/cmd/cgo/internal/testshared/testdata/issue62277/p/p.go
@@ -0,0 +1,17 @@
+// Copyright 2023 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.
+
+package p
+
+var S = func() []string {
+ return []string{"LD_LIBRARY_PATH"}
+}()
+
+var T []string
+
+func init() {
+ T = func() []string {
+ return []string{"LD_LIBRARY_PATH"}
+ }()
+}