diff options
Diffstat (limited to 'libgo/misc')
45 files changed, 560 insertions, 138 deletions
diff --git a/libgo/misc/cgo/errors/argposition_test.go b/libgo/misc/cgo/errors/argposition_test.go new file mode 100644 index 0000000..331095f --- /dev/null +++ b/libgo/misc/cgo/errors/argposition_test.go @@ -0,0 +1,134 @@ +// Copyright 2021 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. + +// Issue 42580: cmd/cgo: shifting identifier position in ast + +package errorstest + +import ( + "bytes" + "fmt" + "go/ast" + "go/parser" + "go/token" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "testing" +) + +type ShortPosition struct { + Line int + Column int + Visited bool +} + +type IdentPositionInfo map[string][]ShortPosition + +type Visitor struct { + identPosInfo IdentPositionInfo + fset *token.FileSet + t *testing.T +} + +func (v *Visitor) Visit(node ast.Node) ast.Visitor { + if ident, ok := node.(*ast.Ident); ok { + if expectedPositions, ok := v.identPosInfo[ident.Name]; ok { + gotMatch := false + var errorMessage strings.Builder + for caseIndex, expectedPos := range expectedPositions { + actualPosition := v.fset.PositionFor(ident.Pos(), true) + errorOccured := false + if expectedPos.Line != actualPosition.Line { + fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line) + errorOccured = true + } + if expectedPos.Column != actualPosition.Column { + fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column) + errorOccured = true + } + if errorOccured { + continue + } + gotMatch = true + expectedPositions[caseIndex].Visited = true + } + + if !gotMatch { + v.t.Errorf(errorMessage.String()) + } + } + } + return v +} + +func TestArgumentsPositions(t *testing.T) { + testdata, err := filepath.Abs("testdata") + if err != nil { + t.Fatal(err) + } + + tmpPath := t.TempDir() + + dir := filepath.Join(tmpPath, "src", "testpositions") + if err := os.MkdirAll(dir, 0755); err != nil { + t.Fatal(err) + } + + cmd := exec.Command("go", "tool", "cgo", + "-srcdir", testdata, + "-objdir", dir, + "issue42580.go") + cmd.Stderr = new(bytes.Buffer) + + err = cmd.Run() + if err != nil { + t.Fatalf("%s: %v\n%s", cmd, err, cmd.Stderr) + } + mainProcessed, err := ioutil.ReadFile(filepath.Join(dir, "issue42580.cgo1.go")) + if err != nil { + t.Fatal(err) + } + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, "", mainProcessed, parser.AllErrors) + if err != nil { + fmt.Println(err) + return + } + + expectation := IdentPositionInfo{ + "checkedPointer": []ShortPosition{ + ShortPosition{ + Line: 32, + Column: 56, + }, + }, + "singleInnerPointerChecked": []ShortPosition{ + ShortPosition{ + Line: 37, + Column: 91, + }, + }, + "doublePointerChecked": []ShortPosition{ + ShortPosition{ + Line: 42, + Column: 91, + }, + }, + } + for _, decl := range f.Decls { + if fdecl, ok := decl.(*ast.FuncDecl); ok { + ast.Walk(&Visitor{expectation, fset, t}, fdecl.Body) + } + } + for ident, positions := range expectation { + for _, position := range positions { + if !position.Visited { + t.Errorf("Position %d:%d missed for %s ident", position.Line, position.Column, ident) + } + } + } +} diff --git a/libgo/misc/cgo/errors/badsym_test.go b/libgo/misc/cgo/errors/badsym_test.go index b2701bf9..fc68756 100644 --- a/libgo/misc/cgo/errors/badsym_test.go +++ b/libgo/misc/cgo/errors/badsym_test.go @@ -6,7 +6,6 @@ package errorstest import ( "bytes" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -55,7 +54,7 @@ func TestBadSymbol(t *testing.T) { makeFile := func(mdir, base, source string) string { ret := filepath.Join(mdir, base) - if err := ioutil.WriteFile(ret, []byte(source), 0644); err != nil { + if err := os.WriteFile(ret, []byte(source), 0644); err != nil { t.Fatal(err) } return ret @@ -100,7 +99,7 @@ func TestBadSymbol(t *testing.T) { // _cgo_import.go. rewrite := func(from, to string) { - obj, err := ioutil.ReadFile(from) + obj, err := os.ReadFile(from) if err != nil { t.Fatal(err) } @@ -115,7 +114,7 @@ func TestBadSymbol(t *testing.T) { obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace)) - if err := ioutil.WriteFile(to, obj, 0644); err != nil { + if err := os.WriteFile(to, obj, 0644); err != nil { t.Fatal(err) } } diff --git a/libgo/misc/cgo/errors/errors_test.go b/libgo/misc/cgo/errors/errors_test.go index 1bdf843..68a30a4 100644 --- a/libgo/misc/cgo/errors/errors_test.go +++ b/libgo/misc/cgo/errors/errors_test.go @@ -7,7 +7,6 @@ package errorstest import ( "bytes" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -25,7 +24,7 @@ func check(t *testing.T, file string) { t.Run(file, func(t *testing.T) { t.Parallel() - contents, err := ioutil.ReadFile(path(file)) + contents, err := os.ReadFile(path(file)) if err != nil { t.Fatal(err) } @@ -41,7 +40,8 @@ func check(t *testing.T, file string) { if len(frags) == 1 { continue } - re, err := regexp.Compile(string(frags[1])) + frag := fmt.Sprintf(":%d:.*%s", i+1, frags[1]) + re, err := regexp.Compile(frag) if err != nil { t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frags[1]) continue @@ -56,7 +56,7 @@ func check(t *testing.T, file string) { } func expect(t *testing.T, file string, errors []*regexp.Regexp) { - dir, err := ioutil.TempDir("", filepath.Base(t.Name())) + dir, err := os.MkdirTemp("", filepath.Base(t.Name())) if err != nil { t.Fatal(err) } diff --git a/libgo/misc/cgo/errors/ptr_test.go b/libgo/misc/cgo/errors/ptr_test.go index 4a46b60..0f39dc8 100644 --- a/libgo/misc/cgo/errors/ptr_test.go +++ b/libgo/misc/cgo/errors/ptr_test.go @@ -10,7 +10,6 @@ import ( "bytes" "flag" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -463,7 +462,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) { gopath = *tmp dir = "" } else { - d, err := ioutil.TempDir("", filepath.Base(t.Name())) + d, err := os.MkdirTemp("", filepath.Base(t.Name())) if err != nil { t.Fatal(err) } @@ -475,7 +474,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) { if err := os.MkdirAll(src, 0777); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil { t.Fatal(err) } @@ -535,10 +534,10 @@ func buildPtrTests(t *testing.T) (dir, exe string) { fmt.Fprintf(&cgo1, "}\n\n") fmt.Fprintf(&cgo1, "%s\n", ptrTestMain) - if err := ioutil.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil { + if err := os.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil { + if err := os.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil { t.Fatal(err) } diff --git a/libgo/misc/cgo/errors/testdata/err2.go b/libgo/misc/cgo/errors/testdata/err2.go index 1d22401..a90598f 100644 --- a/libgo/misc/cgo/errors/testdata/err2.go +++ b/libgo/misc/cgo/errors/testdata/err2.go @@ -40,15 +40,15 @@ func main() { C.foop = x // ERROR HERE // issue 13129: used to output error about C.unsignedshort with CC=clang - var x C.ushort - x = int(0) // ERROR HERE: C\.ushort + var x1 C.ushort + x1 = int(0) // ERROR HERE: C\.ushort // issue 13423 _ = C.fopen() // ERROR HERE // issue 13467 - var x rune = '✈' - var _ rune = C.transform(x) // ERROR HERE: C\.int + var x2 rune = '✈' + var _ rune = C.transform(x2) // ERROR HERE: C\.int // issue 13635: used to output error about C.unsignedchar. // This test tests all such types. @@ -91,10 +91,10 @@ func main() { // issue 26745 _ = func(i int) int { - return C.i + 1 // ERROR HERE: :13 + return C.i + 1 // ERROR HERE: 14 } _ = func(i int) { - C.fi(i) // ERROR HERE: :6 + C.fi(i) // ERROR HERE: 7 } C.fi = C.fi // ERROR HERE diff --git a/libgo/misc/cgo/errors/testdata/issue42580.go b/libgo/misc/cgo/errors/testdata/issue42580.go new file mode 100644 index 0000000..aba80df --- /dev/null +++ b/libgo/misc/cgo/errors/testdata/issue42580.go @@ -0,0 +1,44 @@ +// Copyright 2021 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. + +// Issue 42580: cmd/cgo: shifting identifier position in ast + +package cgotest + +// typedef int (*intFunc) (); +// +// char* strarg = ""; +// +// int func_with_char(char* arg, void* dummy) +// {return 5;} +// +// int* get_arr(char* arg, void* dummy) +// {return NULL;} +import "C" +import "unsafe" + +// Test variables +var ( + checkedPointer = []byte{1} + doublePointerChecked = []byte{1} + singleInnerPointerChecked = []byte{1} +) + +// This test checks the positions of variable identifiers. +// Changing the positions of the test variables idents after this point will break the test. + +func TestSingleArgumentCast() C.int { + retcode := C.func_with_char((*C.char)(unsafe.Pointer(&checkedPointer[0])), unsafe.Pointer(C.strarg)) + return retcode +} + +func TestSingleArgumentCastRecFuncAsSimpleArg() C.int { + retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&singleInnerPointerChecked[0])), unsafe.Pointer(C.strarg)))), nil) + return retcode +} + +func TestSingleArgumentCastRecFunc() C.int { + retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&doublePointerChecked[0])), unsafe.Pointer(C.strarg)))), unsafe.Pointer(C.strarg)) + return retcode +} diff --git a/libgo/misc/cgo/life/life_test.go b/libgo/misc/cgo/life/life_test.go index 3c95d87..0becb26 100644 --- a/libgo/misc/cgo/life/life_test.go +++ b/libgo/misc/cgo/life/life_test.go @@ -6,7 +6,6 @@ package life_test import ( "bytes" - "io/ioutil" "log" "os" "os/exec" @@ -21,7 +20,7 @@ func TestMain(m *testing.M) { } func testMain(m *testing.M) int { - GOPATH, err := ioutil.TempDir("", "cgolife") + GOPATH, err := os.MkdirTemp("", "cgolife") if err != nil { log.Panic(err) } @@ -38,7 +37,7 @@ func testMain(m *testing.M) int { log.Panic(err) } os.Setenv("PWD", modRoot) - if err := ioutil.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil { + if err := os.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil { log.Panic(err) } diff --git a/libgo/misc/cgo/stdio/stdio_test.go b/libgo/misc/cgo/stdio/stdio_test.go index ab5d328..675418f 100644 --- a/libgo/misc/cgo/stdio/stdio_test.go +++ b/libgo/misc/cgo/stdio/stdio_test.go @@ -6,7 +6,6 @@ package stdio_test import ( "bytes" - "io/ioutil" "log" "os" "os/exec" @@ -21,7 +20,7 @@ func TestMain(m *testing.M) { } func testMain(m *testing.M) int { - GOPATH, err := ioutil.TempDir("", "cgostdio") + GOPATH, err := os.MkdirTemp("", "cgostdio") if err != nil { log.Panic(err) } @@ -38,7 +37,7 @@ func testMain(m *testing.M) int { log.Panic(err) } os.Setenv("PWD", modRoot) - if err := ioutil.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil { + if err := os.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil { log.Panic(err) } diff --git a/libgo/misc/cgo/test/callback.go b/libgo/misc/cgo/test/callback.go index 814888e..08dd9b3 100644 --- a/libgo/misc/cgo/test/callback.go +++ b/libgo/misc/cgo/test/callback.go @@ -182,7 +182,7 @@ func testCallbackCallers(t *testing.T) { "runtime.cgocallbackg1", "runtime.cgocallbackg", "runtime.cgocallback", - "runtime.asmcgocall", + "runtime.systemstack_switch", "runtime.cgocall", "test._Cfunc_callback", "test.nestedCall.func1", diff --git a/libgo/misc/cgo/test/cgo_test.go b/libgo/misc/cgo/test/cgo_test.go index f7a76d0..143f23f 100644 --- a/libgo/misc/cgo/test/cgo_test.go +++ b/libgo/misc/cgo/test/cgo_test.go @@ -59,6 +59,7 @@ func Test28896(t *testing.T) { test28896(t) } func Test30065(t *testing.T) { test30065(t) } func Test32579(t *testing.T) { test32579(t) } func Test31891(t *testing.T) { test31891(t) } +func Test45451(t *testing.T) { test45451(t) } func TestAlign(t *testing.T) { testAlign(t) } func TestAtol(t *testing.T) { testAtol(t) } func TestBlocking(t *testing.T) { testBlocking(t) } @@ -80,6 +81,7 @@ func TestNamedEnum(t *testing.T) { testNamedEnum(t) } func TestCastToEnum(t *testing.T) { testCastToEnum(t) } func TestErrno(t *testing.T) { testErrno(t) } func TestFpVar(t *testing.T) { testFpVar(t) } +func TestHandle(t *testing.T) { testHandle(t) } func TestHelpers(t *testing.T) { testHelpers(t) } func TestLibgcc(t *testing.T) { testLibgcc(t) } func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) } diff --git a/libgo/misc/cgo/test/issue1435.go b/libgo/misc/cgo/test/issue1435.go index a1c7cac..91db155 100644 --- a/libgo/misc/cgo/test/issue1435.go +++ b/libgo/misc/cgo/test/issue1435.go @@ -2,13 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux && cgo // +build linux,cgo package cgotest import ( "fmt" - "io/ioutil" + "os" + "sort" "strings" "syscall" "testing" @@ -64,7 +66,7 @@ import "C" func compareStatus(filter, expect string) error { expected := filter + expect pid := syscall.Getpid() - fs, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/task", pid)) + fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid)) if err != nil { return fmt.Errorf("unable to find %d tasks: %v", pid, err) } @@ -72,7 +74,7 @@ func compareStatus(filter, expect string) error { foundAThread := false for _, f := range fs { tf := fmt.Sprintf("/proc/%s/status", f.Name()) - d, err := ioutil.ReadFile(tf) + d, err := os.ReadFile(tf) if err != nil { // There are a surprising number of ways this // can error out on linux. We've seen all of @@ -105,11 +107,23 @@ func compareStatus(filter, expect string) error { // "Pid:\t". } if strings.HasPrefix(line, filter) { - if line != expected { - return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc) + if line == expected { + foundAThread = true + break + } + if filter == "Groups:" && strings.HasPrefix(line, "Groups:\t") { + // https://github.com/golang/go/issues/46145 + // Containers don't reliably output this line in sorted order so manually sort and compare that. + a := strings.Split(line[8:], " ") + sort.Strings(a) + got := strings.Join(a, " ") + if got == expected[8:] { + foundAThread = true + break + } + } - foundAThread = true - break + return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc) } } } diff --git a/libgo/misc/cgo/test/issue6997_linux.go b/libgo/misc/cgo/test/issue6997_linux.go index 0c98ea0..4acc8c1 100644 --- a/libgo/misc/cgo/test/issue6997_linux.go +++ b/libgo/misc/cgo/test/issue6997_linux.go @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !android // +build !android // Test that pthread_cancel works as expected -// (NPTL uses SIGRTMIN to implement thread cancelation) +// (NPTL uses SIGRTMIN to implement thread cancellation) // See https://golang.org/issue/6997 package cgotest @@ -17,8 +18,10 @@ extern int CancelThread(); */ import "C" -import "testing" -import "time" +import ( + "testing" + "time" +) func test6997(t *testing.T) { r := C.StartThread() diff --git a/libgo/misc/cgo/test/issue8148.c b/libgo/misc/cgo/test/issue8148.c new file mode 100644 index 0000000..927b434 --- /dev/null +++ b/libgo/misc/cgo/test/issue8148.c @@ -0,0 +1,11 @@ +// 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. + +#include "_cgo_export.h" + +int get8148(void) { + T t; + t.i = 42; + return issue8148Callback(&t); +} diff --git a/libgo/misc/cgo/test/issue8148.go b/libgo/misc/cgo/test/issue8148.go index f704788..aee9003 100644 --- a/libgo/misc/cgo/test/issue8148.go +++ b/libgo/misc/cgo/test/issue8148.go @@ -10,14 +10,7 @@ package cgotest /* typedef struct { int i; } T; - -int issue8148Callback(T*); - -static int get() { - T t; - t.i = 42; - return issue8148Callback(&t); -} +int get8148(void); */ import "C" @@ -27,5 +20,5 @@ func issue8148Callback(t *C.T) C.int { } func Issue8148() int { - return int(C.get()) + return int(C.get8148()) } diff --git a/libgo/misc/cgo/test/pkg_test.go b/libgo/misc/cgo/test/pkg_test.go index 94abaa0..14013a4 100644 --- a/libgo/misc/cgo/test/pkg_test.go +++ b/libgo/misc/cgo/test/pkg_test.go @@ -5,7 +5,6 @@ package cgotest import ( - "io/ioutil" "os" "os/exec" "path/filepath" @@ -37,7 +36,7 @@ func TestCrossPackageTests(t *testing.T) { } } - GOPATH, err := ioutil.TempDir("", "cgotest") + GOPATH, err := os.MkdirTemp("", "cgotest") if err != nil { t.Fatal(err) } @@ -47,7 +46,7 @@ func TestCrossPackageTests(t *testing.T) { if err := overlayDir(modRoot, "testdata"); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil { t.Fatal(err) } diff --git a/libgo/misc/cgo/test/setgid_linux.go b/libgo/misc/cgo/test/setgid_linux.go index 6773f94..7c64946 100644 --- a/libgo/misc/cgo/test/setgid_linux.go +++ b/libgo/misc/cgo/test/setgid_linux.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. -// Test that setgid does not hang on GNU/Linux. +// Test that setgid does not hang on Linux. // See https://golang.org/issue/3871 for details. package cgotest diff --git a/libgo/misc/cgo/test/test.go b/libgo/misc/cgo/test/test.go index 65823b1..3b8f548 100644 --- a/libgo/misc/cgo/test/test.go +++ b/libgo/misc/cgo/test/test.go @@ -899,6 +899,10 @@ static uint16_t issue31093F(uint16_t v) { return v; } // issue 32579 typedef struct S32579 { unsigned char data[1]; } S32579; +// issue 37033, cgo.Handle +extern void GoFunc37033(uintptr_t handle); +void cFunc37033(uintptr_t handle) { GoFunc37033(handle); } + // issue 38649 // Test that #define'd type aliases work. #define netbsd_gid unsigned int @@ -908,6 +912,9 @@ typedef struct S32579 { unsigned char data[1]; } S32579; enum Enum40494 { X_40494 }; union Union40494 { int x; }; void issue40494(enum Enum40494 e, union Union40494* up) {} + +// Issue 45451, bad handling of go:notinheap types. +typedef struct issue45451Undefined issue45451; */ import "C" @@ -920,6 +927,7 @@ import ( "os/signal" "reflect" "runtime" + "runtime/cgo" "sync" "syscall" "testing" @@ -2230,6 +2238,23 @@ func test32579(t *testing.T) { } } +// issue 37033, check if cgo.Handle works properly + +func testHandle(t *testing.T) { + ch := make(chan int) + + for i := 0; i < 42; i++ { + h := cgo.NewHandle(ch) + go func() { + C.cFunc37033(C.uintptr_t(h)) + }() + if v := <-ch; issue37033 != v { + t.Fatalf("unexpected receiving value: got %d, want %d", v, issue37033) + } + h.Delete() + } +} + // issue 38649 var issue38649 C.netbsd_gid = 42 @@ -2244,3 +2269,19 @@ var issue39877 *C.void = nil func Issue40494() { C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil)) } + +// Issue 45451. +func test45451(t *testing.T) { + var u *C.issue45451 + typ := reflect.ValueOf(u).Type().Elem() + + // The type is undefined in C so allocating it should panic. + defer func() { + if r := recover(); r == nil { + t.Error("expected panic") + } + }() + + _ = reflect.New(typ) + t.Errorf("reflect.New(%v) should have panicked", typ) +} diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_386.s b/libgo/misc/cgo/test/testdata/issue9400/asm_386.s index 7f158b5..96b8b60 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_386.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_386.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_amd64x.s b/libgo/misc/cgo/test/testdata/issue9400/asm_amd64x.s index 48b8619..99509bc 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_amd64x.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_amd64x.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build amd64 amd64p32 -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_arm.s b/libgo/misc/cgo/test/testdata/issue9400/asm_arm.s index 96c2785..cc92856 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_arm.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_arm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_arm64.s b/libgo/misc/cgo/test/testdata/issue9400/asm_arm64.s index 2ebbfcc..2565793 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_arm64.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_arm64.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_mips64x.s b/libgo/misc/cgo/test/testdata/issue9400/asm_mips64x.s index 63dc906..693231d 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_mips64x.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_mips64x.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build mips64 mips64le -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_mipsx.s b/libgo/misc/cgo/test/testdata/issue9400/asm_mipsx.s index 7a92735..63261bb 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_mipsx.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_mipsx.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build mips mipsle -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_ppc64x.s b/libgo/misc/cgo/test/testdata/issue9400/asm_ppc64x.s index c88ec3b..b5613fb 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_ppc64x.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_ppc64x.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build ppc64 ppc64le -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_riscv64.s b/libgo/misc/cgo/test/testdata/issue9400/asm_riscv64.s index 20fcc00..244dada 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_riscv64.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_riscv64.s @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build riscv64 -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testdata/issue9400/asm_s390x.s b/libgo/misc/cgo/test/testdata/issue9400/asm_s390x.s index fc9ad72..4856492 100644 --- a/libgo/misc/cgo/test/testdata/issue9400/asm_s390x.s +++ b/libgo/misc/cgo/test/testdata/issue9400/asm_s390x.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/test/testx.c b/libgo/misc/cgo/test/testx.c new file mode 100644 index 0000000..1258e326 --- /dev/null +++ b/libgo/misc/cgo/test/testx.c @@ -0,0 +1,24 @@ +// Copyright 2021 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 "_cgo_export.h" + +void lockOSThreadC(void) { + lockOSThreadCallback(); +} + +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) + ; +} + +void f7665(void) { +} diff --git a/libgo/misc/cgo/test/testx.go b/libgo/misc/cgo/test/testx.go index 2b2e69e..823c3e13 100644 --- a/libgo/misc/cgo/test/testx.go +++ b/libgo/misc/cgo/test/testx.go @@ -12,6 +12,7 @@ package cgotest import ( "runtime" + "runtime/cgo" "runtime/debug" "strings" "sync" @@ -26,7 +27,6 @@ import ( extern void doAdd(int, int); // issue 1328 -extern void BackIntoGo(void); void IntoC(void); // issue 1560 @@ -38,11 +38,7 @@ long long mysleep(int seconds); long long twoSleep(int); // issue 3775 -void lockOSThreadCallback(void); -inline static void lockOSThreadC(void) -{ - lockOSThreadCallback(); -} +void lockOSThreadC(void); int usleep(unsigned usec); // issue 4054 part 2 - part 1 in test.go @@ -81,21 +77,9 @@ extern void f7665(void); #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) - ; -} +void issue7978c(uint32_t *sync); // issue 8331 part 2 - part 1 in test.go // A typedef of an unnamed struct is the same struct when @@ -428,9 +412,6 @@ func test6907Go(t *testing.T) { // issue 7665 -//export f7665 -func f7665() {} - var bad7665 unsafe.Pointer = C.f7665 var good7665 uintptr = uintptr(C.f7665) @@ -558,6 +539,17 @@ func test31891(t *testing.T) { C.callIssue31891() } +// issue 37033, check if cgo.Handle works properly + +var issue37033 = 42 + +//export GoFunc37033 +func GoFunc37033(handle C.uintptr_t) { + h := cgo.Handle(handle) + ch := h.Value().(chan int) + ch <- issue37033 +} + // issue 38408 // A typedef pointer can be used as the element type. // No runtime test; just make sure it compiles. diff --git a/libgo/misc/cgo/testcarchive/carchive_test.go b/libgo/misc/cgo/testcarchive/carchive_test.go index b67cb2e..e5db0d6 100644 --- a/libgo/misc/cgo/testcarchive/carchive_test.go +++ b/libgo/misc/cgo/testcarchive/carchive_test.go @@ -10,7 +10,6 @@ import ( "debug/elf" "flag" "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -53,7 +52,7 @@ func testMain(m *testing.M) int { // We need a writable GOPATH in which to run the tests. // Construct one in a temporary directory. var err error - GOPATH, err = ioutil.TempDir("", "carchive_test") + GOPATH, err = os.MkdirTemp("", "carchive_test") if err != nil { log.Panic(err) } @@ -74,7 +73,7 @@ func testMain(m *testing.M) int { log.Panic(err) } os.Setenv("PWD", modRoot) - if err := ioutil.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil { + if err := os.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil { log.Panic(err) } @@ -176,7 +175,7 @@ func genHeader(t *testing.T, header, dir string) { // The 'cgo' command generates a number of additional artifacts, // but we're only interested in the header. // Shunt the rest of the outputs to a temporary directory. - objDir, err := ioutil.TempDir(GOPATH, "_obj") + objDir, err := os.MkdirTemp(GOPATH, "_obj") if err != nil { t.Fatal(err) } @@ -252,7 +251,7 @@ var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`) // the user and make the files change based on details of the location // of GOPATH. func checkLineComments(t *testing.T, hdrname string) { - hdr, err := ioutil.ReadFile(hdrname) + hdr, err := os.ReadFile(hdrname) if err != nil { if !os.IsNotExist(err) { t.Error(err) @@ -618,7 +617,7 @@ func TestExtar(t *testing.T) { t.Fatal(err) } s := strings.Replace(testar, "PWD", dir, 1) - if err := ioutil.WriteFile("testar", []byte(s), 0777); err != nil { + if err := os.WriteFile("testar", []byte(s), 0777); err != nil { t.Fatal(err) } @@ -776,7 +775,7 @@ func TestSIGPROF(t *testing.T) { // tool with -buildmode=c-archive, it passes -shared to the compiler, // so we override that. The go tool doesn't work this way, but Bazel // will likely do it in the future. And it ought to work. This test -// was added because at one time it did not work on PPC GNU/Linux. +// was added because at one time it did not work on PPC Linux. func TestCompileWithoutShared(t *testing.T) { // For simplicity, reuse the signal forwarding test. checkSignalForwardingTest(t) diff --git a/libgo/misc/cgo/testcarchive/testdata/libgo6/sigprof.go b/libgo/misc/cgo/testcarchive/testdata/libgo6/sigprof.go index 4cb05dc..31527c5 100644 --- a/libgo/misc/cgo/testcarchive/testdata/libgo6/sigprof.go +++ b/libgo/misc/cgo/testcarchive/testdata/libgo6/sigprof.go @@ -5,7 +5,7 @@ package main import ( - "io/ioutil" + "io" "runtime/pprof" ) @@ -13,7 +13,7 @@ import "C" //export go_start_profile func go_start_profile() { - pprof.StartCPUProfile(ioutil.Discard) + pprof.StartCPUProfile(io.Discard) } //export go_stop_profile diff --git a/libgo/misc/cgo/testcshared/cshared_test.go b/libgo/misc/cgo/testcshared/cshared_test.go index 3a4886c..19ad8c7 100644 --- a/libgo/misc/cgo/testcshared/cshared_test.go +++ b/libgo/misc/cgo/testcshared/cshared_test.go @@ -11,7 +11,6 @@ import ( "encoding/binary" "flag" "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -125,7 +124,7 @@ func testMain(m *testing.M) int { // Copy testdata into GOPATH/src/testcshared, along with a go.mod file // declaring the same path. - GOPATH, err := ioutil.TempDir("", "cshared_test") + GOPATH, err := os.MkdirTemp("", "cshared_test") if err != nil { log.Panic(err) } @@ -140,7 +139,7 @@ func testMain(m *testing.M) int { log.Panic(err) } os.Setenv("PWD", modRoot) - if err := ioutil.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil { + if err := os.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil { log.Panic(err) } @@ -260,7 +259,7 @@ func createHeaders() error { // The 'cgo' command generates a number of additional artifacts, // but we're only interested in the header. // Shunt the rest of the outputs to a temporary directory. - objDir, err := ioutil.TempDir("", "testcshared_obj") + objDir, err := os.MkdirTemp("", "testcshared_obj") if err != nil { return err } @@ -293,11 +292,60 @@ func createHeaders() error { "-installsuffix", "testcshared", "-o", libgoname, filepath.Join(".", "libgo", "libgo.go")} + if GOOS == "windows" && strings.HasSuffix(args[6], ".a") { + args[6] = strings.TrimSuffix(args[6], ".a") + ".dll" + } cmd = exec.Command(args[0], args[1:]...) out, err = cmd.CombinedOutput() if err != nil { return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out) } + if GOOS == "windows" { + // We can't simply pass -Wl,--out-implib, because this relies on having imports from multiple packages, + // which results in the linkers output implib getting overwritten at each step. So instead build the + // import library the traditional way, using a def file. + err = os.WriteFile("libgo.def", + []byte("LIBRARY libgo.dll\nEXPORTS\n\tDidInitRun\n\tDidMainRun\n\tDivu\n\tFromPkg\n\t_cgo_dummy_export\n"), + 0644) + if err != nil { + return fmt.Errorf("unable to write def file: %v", err) + } + out, err = exec.Command(cc[0], append(cc[1:], "-print-prog-name=dlltool")...).CombinedOutput() + if err != nil { + return fmt.Errorf("unable to find dlltool path: %v\n%s\n", err, out) + } + args := []string{strings.TrimSpace(string(out)), "-D", args[6], "-l", libgoname, "-d", "libgo.def"} + + // This is an unfortunate workaround for https://github.com/mstorsjo/llvm-mingw/issues/205 in which + // we basically reimplement the contents of the dlltool.sh wrapper: https://git.io/JZFlU + dlltoolContents, err := os.ReadFile(args[0]) + if err != nil { + return fmt.Errorf("unable to read dlltool: %v\n", err) + } + if bytes.HasPrefix(dlltoolContents, []byte("#!/bin/sh")) && bytes.Contains(dlltoolContents, []byte("llvm-dlltool")) { + base, name := filepath.Split(args[0]) + args[0] = filepath.Join(base, "llvm-dlltool") + var machine string + switch strings.SplitN(name, "-", 2)[0] { + case "i686": + machine = "i386" + case "x86_64": + machine = "i386:x86-64" + case "armv7": + machine = "arm" + case "aarch64": + machine = "arm64" + } + if len(machine) > 0 { + args = append(args, "-m", machine) + } + } + + out, err = exec.Command(args[0], args[1:]...).CombinedOutput() + if err != nil { + return fmt.Errorf("unable to run dlltool to create import library: %v\n%s\n", err, out) + } + } if runtime.GOOS != GOOS && GOOS == "android" { args = append(adbCmd(), "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname)) @@ -381,7 +429,7 @@ func main() { srcfile := filepath.Join(tmpdir, "test.go") objfile := filepath.Join(tmpdir, "test.dll") - if err := ioutil.WriteFile(srcfile, []byte(prog), 0666); err != nil { + if err := os.WriteFile(srcfile, []byte(prog), 0666); err != nil { t.Fatal(err) } argv := []string{"build", "-buildmode=c-shared"} @@ -401,7 +449,7 @@ func main() { defer f.Close() section := f.Section(".edata") if section == nil { - t.Fatalf(".edata section is not present") + t.Skip(".edata section is not present") } // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go @@ -643,7 +691,7 @@ func TestPIE(t *testing.T) { // Test that installing a second time recreates the header file. func TestCachedInstall(t *testing.T) { - tmpdir, err := ioutil.TempDir("", "cshared") + tmpdir, err := os.MkdirTemp("", "cshared") if err != nil { t.Fatal(err) } @@ -719,14 +767,14 @@ func TestCachedInstall(t *testing.T) { // copyFile copies src to dst. func copyFile(t *testing.T, dst, src string) { t.Helper() - data, err := ioutil.ReadFile(src) + data, err := os.ReadFile(src) if err != nil { t.Fatal(err) } if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(dst, data, 0666); err != nil { + if err := os.WriteFile(dst, data, 0666); err != nil { t.Fatal(err) } } @@ -743,14 +791,19 @@ func TestGo2C2Go(t *testing.T) { t.Parallel() - tmpdir, err := ioutil.TempDir("", "cshared-TestGo2C2Go") + tmpdir, err := os.MkdirTemp("", "cshared-TestGo2C2Go") if err != nil { t.Fatal(err) } defer os.RemoveAll(tmpdir) lib := filepath.Join(tmpdir, "libtestgo2c2go."+libSuffix) - run(t, nil, "go", "build", "-buildmode=c-shared", "-o", lib, "./go2c2go/go") + var env []string + if GOOS == "windows" && strings.HasSuffix(lib, ".a") { + env = append(env, "CGO_LDFLAGS=-Wl,--out-implib,"+lib, "CGO_LDFLAGS_ALLOW=.*") + lib = strings.TrimSuffix(lib, ".a") + ".dll" + } + run(t, env, "go", "build", "-buildmode=c-shared", "-o", lib, "./go2c2go/go") cgoCflags := os.Getenv("CGO_CFLAGS") if cgoCflags != "" { diff --git a/libgo/misc/cgo/testgodefs/testgodefs_test.go b/libgo/misc/cgo/testgodefs/testgodefs_test.go index 4c2312c..aae3404 100644 --- a/libgo/misc/cgo/testgodefs/testgodefs_test.go +++ b/libgo/misc/cgo/testgodefs/testgodefs_test.go @@ -6,7 +6,6 @@ package testgodefs import ( "bytes" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -34,7 +33,7 @@ func TestGoDefs(t *testing.T) { t.Fatal(err) } - gopath, err := ioutil.TempDir("", "testgodefs-gopath") + gopath, err := os.MkdirTemp("", "testgodefs-gopath") if err != nil { t.Fatal(err) } @@ -58,20 +57,20 @@ func TestGoDefs(t *testing.T) { t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) } - if err := ioutil.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil { + if err := os.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil { t.Fatal(err) } } - main, err := ioutil.ReadFile(filepath.Join("testdata", "main.go")) + main, err := os.ReadFile(filepath.Join("testdata", "main.go")) if err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil { + if err := os.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil { t.Fatal(err) } - if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil { + if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil { t.Fatal(err) } diff --git a/libgo/misc/cgo/testplugin/plugin_test.go b/libgo/misc/cgo/testplugin/plugin_test.go index 8869528..9697dbf 100644 --- a/libgo/misc/cgo/testplugin/plugin_test.go +++ b/libgo/misc/cgo/testplugin/plugin_test.go @@ -9,7 +9,6 @@ import ( "context" "flag" "fmt" - "io/ioutil" "log" "os" "os/exec" @@ -31,15 +30,28 @@ func TestMain(m *testing.M) { os.Exit(testMain(m)) } +// tmpDir is used to cleanup logged commands -- s/tmpDir/$TMPDIR/ +var tmpDir string + +// prettyPrintf prints lines with tmpDir sanitized. +func prettyPrintf(format string, args ...interface{}) { + s := fmt.Sprintf(format, args...) + if tmpDir != "" { + s = strings.ReplaceAll(s, tmpDir, "$TMPDIR") + } + fmt.Print(s) +} + func testMain(m *testing.M) int { // Copy testdata into GOPATH/src/testplugin, along with a go.mod file // declaring the same path. - GOPATH, err := ioutil.TempDir("", "plugin_test") + GOPATH, err := os.MkdirTemp("", "plugin_test") if err != nil { log.Panic(err) } defer os.RemoveAll(GOPATH) + tmpDir = GOPATH modRoot := filepath.Join(GOPATH, "src", "testplugin") altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin") @@ -50,14 +62,20 @@ func testMain(m *testing.M) int { if err := overlayDir(dstRoot, srcRoot); err != nil { log.Panic(err) } - if err := ioutil.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil { + prettyPrintf("mkdir -p %s\n", dstRoot) + prettyPrintf("rsync -a %s/ %s\n", srcRoot, dstRoot) + + if err := os.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil { log.Panic(err) } + prettyPrintf("echo 'module testplugin' > %s/go.mod\n", dstRoot) } os.Setenv("GOPATH", filepath.Join(GOPATH, "alt")) if err := os.Chdir(altRoot); err != nil { log.Panic(err) + } else { + prettyPrintf("cd %s\n", altRoot) } os.Setenv("PWD", altRoot) goCmd(nil, "build", "-buildmode=plugin", "-o", filepath.Join(modRoot, "plugin-mismatch.so"), "./plugin-mismatch") @@ -65,6 +83,8 @@ func testMain(m *testing.M) int { os.Setenv("GOPATH", GOPATH) if err := os.Chdir(modRoot); err != nil { log.Panic(err) + } else { + prettyPrintf("cd %s\n", modRoot) } os.Setenv("PWD", modRoot) @@ -72,13 +92,14 @@ func testMain(m *testing.M) int { goCmd(nil, "build", "-buildmode=plugin", "./plugin1") goCmd(nil, "build", "-buildmode=plugin", "./plugin2") - so, err := ioutil.ReadFile("plugin2.so") + so, err := os.ReadFile("plugin2.so") if err != nil { log.Panic(err) } - if err := ioutil.WriteFile("plugin2-dup.so", so, 0444); err != nil { + if err := os.WriteFile("plugin2-dup.so", so, 0444); err != nil { log.Panic(err) } + prettyPrintf("cp plugin2.so plugin2-dup.so\n") goCmd(nil, "build", "-buildmode=plugin", "-o=sub/plugin1.so", "./sub/plugin1") goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed1.so", "./unnamed1/main.go") @@ -95,8 +116,53 @@ func goCmd(t *testing.T, op string, args ...string) { run(t, "go", append([]string{op, "-gcflags", gcflags}, args...)...) } +// escape converts a string to something suitable for a shell command line. +func escape(s string) string { + s = strings.Replace(s, "\\", "\\\\", -1) + s = strings.Replace(s, "'", "\\'", -1) + // Conservative guess at characters that will force quoting + if s == "" || strings.ContainsAny(s, "\\ ;#*&$~?!|[]()<>{}`") { + s = "'" + s + "'" + } + return s +} + +// asCommandLine renders cmd as something that could be copy-and-pasted into a command line +func asCommandLine(cwd string, cmd *exec.Cmd) string { + s := "(" + if cmd.Dir != "" && cmd.Dir != cwd { + s += "cd" + escape(cmd.Dir) + ";" + } + for _, e := range cmd.Env { + if !strings.HasPrefix(e, "PATH=") && + !strings.HasPrefix(e, "HOME=") && + !strings.HasPrefix(e, "USER=") && + !strings.HasPrefix(e, "SHELL=") { + s += " " + s += escape(e) + } + } + // These EVs are relevant to this test. + for _, e := range os.Environ() { + if strings.HasPrefix(e, "PWD=") || + strings.HasPrefix(e, "GOPATH=") || + strings.HasPrefix(e, "LD_LIBRARY_PATH=") { + s += " " + s += escape(e) + } + } + for _, a := range cmd.Args { + s += " " + s += escape(a) + } + s += " )" + return s +} + func run(t *testing.T, bin string, args ...string) string { cmd := exec.Command(bin, args...) + cmdLine := asCommandLine(".", cmd) + prettyPrintf("%s\n", cmdLine) cmd.Stderr = new(strings.Builder) out, err := cmd.Output() if err != nil { @@ -197,6 +263,17 @@ func TestIssue25756(t *testing.T) { } } +// Test with main using -buildmode=pie with plugin for issue #43228 +func TestIssue25756pie(t *testing.T) { + if os.Getenv("GO_BUILDER_NAME") == "darwin-arm64-11_0-toothrot" { + t.Skip("broken on darwin/arm64 builder in sharded mode; see issue 46239") + } + + goCmd(t, "build", "-buildmode=plugin", "-o", "life.so", "./issue25756/plugin") + goCmd(t, "build", "-buildmode=pie", "-o", "issue25756pie.exe", "./issue25756/main.go") + run(t, "./issue25756pie.exe") +} + func TestMethod(t *testing.T) { // Exported symbol's method must be live. goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go") diff --git a/libgo/misc/cgo/testplugin/testdata/method2/main.go b/libgo/misc/cgo/testplugin/testdata/method2/main.go index 6a87e7b..89afbda 100644 --- a/libgo/misc/cgo/testplugin/testdata/method2/main.go +++ b/libgo/misc/cgo/testplugin/testdata/method2/main.go @@ -15,7 +15,7 @@ import ( var t p.T -type I interface { M() } +type I interface{ M() } func main() { pl, err := plugin.Open("method2.so") diff --git a/libgo/misc/cgo/testsanitizers/cc_test.go b/libgo/misc/cgo/testsanitizers/cc_test.go index 0192a66..384b625 100644 --- a/libgo/misc/cgo/testsanitizers/cc_test.go +++ b/libgo/misc/cgo/testsanitizers/cc_test.go @@ -11,7 +11,6 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -36,7 +35,7 @@ func requireOvercommit(t *testing.T) { overcommit.Once.Do(func() { var out []byte - out, overcommit.err = ioutil.ReadFile("/proc/sys/vm/overcommit_memory") + out, overcommit.err = os.ReadFile("/proc/sys/vm/overcommit_memory") if overcommit.err != nil { return } @@ -313,14 +312,14 @@ int main() { `) func (c *config) checkCSanitizer() (skip bool, err error) { - dir, err := ioutil.TempDir("", c.sanitizer) + dir, err := os.MkdirTemp("", c.sanitizer) if err != nil { return false, fmt.Errorf("failed to create temp directory: %v", err) } defer os.RemoveAll(dir) src := filepath.Join(dir, "return0.c") - if err := ioutil.WriteFile(src, cMain, 0600); err != nil { + if err := os.WriteFile(src, cMain, 0600); err != nil { return false, fmt.Errorf("failed to write C source file: %v", err) } @@ -418,7 +417,7 @@ func (d *tempDir) Join(name string) string { func newTempDir(t *testing.T) *tempDir { t.Helper() - dir, err := ioutil.TempDir("", filepath.Dir(t.Name())) + dir, err := os.MkdirTemp("", filepath.Dir(t.Name())) if err != nil { t.Fatalf("Failed to create temp dir: %v", err) } @@ -440,3 +439,14 @@ func hangProneCmd(name string, arg ...string) *exec.Cmd { } return cmd } + +// mSanSupported is a copy of the function cmd/internal/sys.MSanSupported, +// because the internal pacakage can't be used here. +func mSanSupported(goos, goarch string) bool { + switch goos { + case "linux": + return goarch == "amd64" || goarch == "arm64" + default: + return false + } +} diff --git a/libgo/misc/cgo/testsanitizers/cshared_test.go b/libgo/misc/cgo/testsanitizers/cshared_test.go index 56063ea..8fd0371 100644 --- a/libgo/misc/cgo/testsanitizers/cshared_test.go +++ b/libgo/misc/cgo/testsanitizers/cshared_test.go @@ -6,7 +6,7 @@ package sanitizers_test import ( "fmt" - "io/ioutil" + "os" "strings" "testing" ) @@ -19,6 +19,12 @@ func TestShared(t *testing.T) { if err != nil { t.Fatal(err) } + + GOARCH, err := goEnv("GOARCH") + if err != nil { + t.Fatal(err) + } + libExt := "so" if GOOS == "darwin" { libExt = "dylib" @@ -41,6 +47,11 @@ func TestShared(t *testing.T) { for _, tc := range cases { tc := tc name := strings.TrimSuffix(tc.src, ".go") + //The memory sanitizer tests require support for the -msan option. + if tc.sanitizer == "memory" && !mSanSupported(GOOS, GOARCH) { + t.Logf("skipping %s test on %s/%s; -msan option is not supported.", name, GOOS, GOARCH) + continue + } t.Run(name, func(t *testing.T) { t.Parallel() config := configure(tc.sanitizer) @@ -53,7 +64,7 @@ func TestShared(t *testing.T) { mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src))) cSrc := dir.Join("main.c") - if err := ioutil.WriteFile(cSrc, cMain, 0600); err != nil { + if err := os.WriteFile(cSrc, cMain, 0600); err != nil { t.Fatalf("failed to write C source file: %v", err) } diff --git a/libgo/misc/cgo/testsanitizers/msan_test.go b/libgo/misc/cgo/testsanitizers/msan_test.go index 5e2f975..2a3494f 100644 --- a/libgo/misc/cgo/testsanitizers/msan_test.go +++ b/libgo/misc/cgo/testsanitizers/msan_test.go @@ -10,6 +10,19 @@ import ( ) func TestMSAN(t *testing.T) { + goos, err := goEnv("GOOS") + if err != nil { + t.Fatal(err) + } + goarch, err := goEnv("GOARCH") + if err != nil { + t.Fatal(err) + } + // The msan tests require support for the -msan option. + if !mSanSupported(goos, goarch) { + t.Skipf("skipping on %s/%s; -msan option is not supported.", goos, goarch) + } + t.Parallel() requireOvercommit(t) config := configure("memory") diff --git a/libgo/misc/cgo/testsanitizers/testdata/tsan9.go b/libgo/misc/cgo/testsanitizers/testdata/tsan9.go index f166d8b..06304be 100644 --- a/libgo/misc/cgo/testsanitizers/testdata/tsan9.go +++ b/libgo/misc/cgo/testsanitizers/testdata/tsan9.go @@ -44,7 +44,7 @@ void spin() { import "C" import ( - "io/ioutil" + "io" "runtime/pprof" "time" ) @@ -60,7 +60,7 @@ func goSpin() { } func main() { - pprof.StartCPUProfile(ioutil.Discard) + pprof.StartCPUProfile(io.Discard) go C.spin() goSpin() pprof.StopCPUProfile() diff --git a/libgo/misc/cgo/testshared/shared_test.go b/libgo/misc/cgo/testshared/shared_test.go index f52391c..e77f848 100644 --- a/libgo/misc/cgo/testshared/shared_test.go +++ b/libgo/misc/cgo/testshared/shared_test.go @@ -13,7 +13,6 @@ import ( "fmt" "go/build" "io" - "io/ioutil" "log" "os" "os/exec" @@ -90,7 +89,7 @@ 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) { - workDir, err := ioutil.TempDir("", "shared_test") + workDir, err := os.MkdirTemp("", "shared_test") if err != nil { return 0, err } @@ -177,7 +176,7 @@ func cloneTestdataModule(gopath string) (string, error) { if err := overlayDir(modRoot, "testdata"); err != nil { return "", err } - if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil { + if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil { return "", err } return modRoot, nil @@ -318,7 +317,7 @@ func TestShlibnameFiles(t *testing.T) { } for _, pkg := range pkgs { shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname") - contentsb, err := ioutil.ReadFile(shlibnamefile) + contentsb, err := os.ReadFile(shlibnamefile) if err != nil { t.Errorf("error reading shlibnamefile for %s: %v", pkg, err) continue @@ -791,7 +790,7 @@ func resetFileStamps() { // It also sets the time of the file, so that we can see if it is rewritten. func touch(t *testing.T, path string) (cleanup func()) { t.Helper() - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { t.Fatal(err) } @@ -837,14 +836,14 @@ func touch(t *testing.T, path string) (cleanup func()) { // user-writable. perm := fi.Mode().Perm() | 0200 - if err := ioutil.WriteFile(path, data, perm); err != nil { + if err := os.WriteFile(path, data, perm); err != nil { t.Fatal(err) } if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil { t.Fatal(err) } return func() { - if err := ioutil.WriteFile(path, old, perm); err != nil { + if err := os.WriteFile(path, old, perm); err != nil { t.Fatal(err) } } diff --git a/libgo/misc/cgo/testshared/testdata/depBase/asm.s b/libgo/misc/cgo/testshared/testdata/depBase/asm.s index a8acf77f0..0f1111f 100644 --- a/libgo/misc/cgo/testshared/testdata/depBase/asm.s +++ b/libgo/misc/cgo/testshared/testdata/depBase/asm.s @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !gccgo +// +build gc #include "textflag.h" diff --git a/libgo/misc/cgo/testshared/testdata/depBase/stubs.go b/libgo/misc/cgo/testshared/testdata/depBase/stubs.go index 04534f3..c779538 100644 --- a/libgo/misc/cgo/testshared/testdata/depBase/stubs.go +++ b/libgo/misc/cgo/testshared/testdata/depBase/stubs.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. -// +build !gccgo +// +build gc package depBase diff --git a/libgo/misc/cgo/testso/so_test.go b/libgo/misc/cgo/testso/so_test.go index 57f0fd3..6d14e32 100644 --- a/libgo/misc/cgo/testso/so_test.go +++ b/libgo/misc/cgo/testso/so_test.go @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package so_test import ( - "io/ioutil" "log" "os" "os/exec" @@ -37,7 +37,7 @@ func requireTestSOSupported(t *testing.T) { func TestSO(t *testing.T) { requireTestSOSupported(t) - GOPATH, err := ioutil.TempDir("", "cgosotest") + GOPATH, err := os.MkdirTemp("", "cgosotest") if err != nil { log.Fatal(err) } @@ -47,7 +47,7 @@ func TestSO(t *testing.T) { if err := overlayDir(modRoot, "testdata"); err != nil { log.Panic(err) } - if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { log.Panic(err) } @@ -80,6 +80,10 @@ func TestSO(t *testing.T) { case "windows": ext = "dll" args = append(args, "-DEXPORT_DLL") + // At least in mingw-clang it is not permitted to just name a .dll + // on the command line. You must name the corresponding import + // library instead, even though the dll is used when the executable is run. + args = append(args, "-Wl,-out-implib,libcgosotest.a") case "aix": ext = "so.1" } diff --git a/libgo/misc/cgo/testso/testdata/cgoso.go b/libgo/misc/cgo/testso/testdata/cgoso.go index bba5de3..b59b2a8 100644 --- a/libgo/misc/cgo/testso/testdata/cgoso.go +++ b/libgo/misc/cgo/testso/testdata/cgoso.go @@ -14,7 +14,7 @@ package cgosotest #cgo solaris LDFLAGS: -L. -lcgosotest #cgo netbsd LDFLAGS: -L. libcgosotest.so #cgo darwin LDFLAGS: -L. libcgosotest.dylib -#cgo windows LDFLAGS: -L. libcgosotest.dll +#cgo windows LDFLAGS: -L. libcgosotest.a #cgo aix LDFLAGS: -L. -l cgosotest void init(void); diff --git a/libgo/misc/cgo/testsovar/so_test.go b/libgo/misc/cgo/testsovar/so_test.go index 57f0fd3..6d14e32 100644 --- a/libgo/misc/cgo/testsovar/so_test.go +++ b/libgo/misc/cgo/testsovar/so_test.go @@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build cgo // +build cgo package so_test import ( - "io/ioutil" "log" "os" "os/exec" @@ -37,7 +37,7 @@ func requireTestSOSupported(t *testing.T) { func TestSO(t *testing.T) { requireTestSOSupported(t) - GOPATH, err := ioutil.TempDir("", "cgosotest") + GOPATH, err := os.MkdirTemp("", "cgosotest") if err != nil { log.Fatal(err) } @@ -47,7 +47,7 @@ func TestSO(t *testing.T) { if err := overlayDir(modRoot, "testdata"); err != nil { log.Panic(err) } - if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { + if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { log.Panic(err) } @@ -80,6 +80,10 @@ func TestSO(t *testing.T) { case "windows": ext = "dll" args = append(args, "-DEXPORT_DLL") + // At least in mingw-clang it is not permitted to just name a .dll + // on the command line. You must name the corresponding import + // library instead, even though the dll is used when the executable is run. + args = append(args, "-Wl,-out-implib,libcgosotest.a") case "aix": ext = "so.1" } diff --git a/libgo/misc/cgo/testsovar/testdata/cgoso.go b/libgo/misc/cgo/testsovar/testdata/cgoso.go index 9c7f95e..d9deb55 100644 --- a/libgo/misc/cgo/testsovar/testdata/cgoso.go +++ b/libgo/misc/cgo/testsovar/testdata/cgoso.go @@ -18,7 +18,7 @@ package cgosotest #cgo solaris LDFLAGS: -L. -lcgosotest #cgo netbsd LDFLAGS: -L. libcgosotest.so #cgo darwin LDFLAGS: -L. libcgosotest.dylib -#cgo windows LDFLAGS: -L. libcgosotest.dll +#cgo windows LDFLAGS: -L. libcgosotest.a #cgo aix LDFLAGS: -L. -l cgosotest #include "cgoso_c.h" |