diff options
author | Austin Clements <austin@google.com> | 2023-05-04 12:13:27 -0400 |
---|---|---|
committer | Austin Clements <austin@google.com> | 2023-05-12 11:59:56 +0000 |
commit | bf6c55a8b313752667b51194485fa206110d71f9 (patch) | |
tree | 8dd81bdb6e48bc77d7923ba985a91b6b7daa341e /misc | |
parent | a25688d406f2a4296d39b22a2b10aea7178eddc6 (diff) | |
download | go-bf6c55a8b313752667b51194485fa206110d71f9.tar.gz go-bf6c55a8b313752667b51194485fa206110d71f9.zip |
misc/cgo: move easy tests to cmd/cgo/internal
This moves most misc/cgo tests to cmd/cgo/internal. This is mostly a
trivial rename and updating dist/test.go for the new paths, plus
excluding these packages from regular dist test registration. A few
tests were sensitive to what path they ran in, so we update those.
This will let these tests access facilities in internal/testenv.
For #37486.
Change-Id: I3ed417c7c22d9b667f2767c0cb1f59118fcd4af6
Reviewed-on: https://go-review.googlesource.com/c/go/+/492720
Run-TryBot: Austin Clements <austin@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Diffstat (limited to 'misc')
247 files changed, 0 insertions, 14442 deletions
diff --git a/misc/cgo/errors/argposition_test.go b/misc/cgo/errors/argposition_test.go deleted file mode 100644 index dd26663df2..0000000000 --- a/misc/cgo/errors/argposition_test.go +++ /dev/null @@ -1,133 +0,0 @@ -// 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" - "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 := os.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/misc/cgo/errors/badsym_test.go b/misc/cgo/errors/badsym_test.go deleted file mode 100644 index bc3ba2b489..0000000000 --- a/misc/cgo/errors/badsym_test.go +++ /dev/null @@ -1,219 +0,0 @@ -// 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. - -package errorstest - -import ( - "bytes" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" - "unicode" -) - -// A manually modified object file could pass unexpected characters -// into the files generated by cgo. - -const magicInput = "abcdefghijklmnopqrstuvwxyz0123" -const magicReplace = "\n//go:cgo_ldflag \"-badflag\"\n//" - -const cSymbol = "BadSymbol" + magicInput + "Name" -const cDefSource = "int " + cSymbol + " = 1;" -const cRefSource = "extern int " + cSymbol + "; int F() { return " + cSymbol + "; }" - -// goSource is the source code for the trivial Go file we use. -// We will replace TMPDIR with the temporary directory name. -const goSource = ` -package main - -// #cgo LDFLAGS: TMPDIR/cbad.o TMPDIR/cbad.so -// extern int F(); -import "C" - -func main() { - println(C.F()) -} -` - -func TestBadSymbol(t *testing.T) { - dir := t.TempDir() - - mkdir := func(base string) string { - ret := filepath.Join(dir, base) - if err := os.Mkdir(ret, 0755); err != nil { - t.Fatal(err) - } - return ret - } - - cdir := mkdir("c") - godir := mkdir("go") - - makeFile := func(mdir, base, source string) string { - ret := filepath.Join(mdir, base) - if err := os.WriteFile(ret, []byte(source), 0644); err != nil { - t.Fatal(err) - } - return ret - } - - cDefFile := makeFile(cdir, "cdef.c", cDefSource) - cRefFile := makeFile(cdir, "cref.c", cRefSource) - - ccCmd := cCompilerCmd(t) - - cCompile := func(arg, base, src string) string { - out := filepath.Join(cdir, base) - run := append(ccCmd, arg, "-o", out, src) - output, err := exec.Command(run[0], run[1:]...).CombinedOutput() - if err != nil { - t.Log(run) - t.Logf("%s", output) - t.Fatal(err) - } - if err := os.Remove(src); err != nil { - t.Fatal(err) - } - return out - } - - // Build a shared library that defines a symbol whose name - // contains magicInput. - - cShared := cCompile("-shared", "c.so", cDefFile) - - // Build an object file that refers to the symbol whose name - // contains magicInput. - - cObj := cCompile("-c", "c.o", cRefFile) - - // Rewrite the shared library and the object file, replacing - // magicInput with magicReplace. This will have the effect of - // introducing a symbol whose name looks like a cgo command. - // The cgo tool will use that name when it generates the - // _cgo_import.go file, thus smuggling a magic //go:cgo_ldflag - // pragma into a Go file. We used to not check the pragmas in - // _cgo_import.go. - - rewrite := func(from, to string) { - obj, err := os.ReadFile(from) - if err != nil { - t.Fatal(err) - } - - if bytes.Count(obj, []byte(magicInput)) == 0 { - t.Fatalf("%s: did not find magic string", from) - } - - if len(magicInput) != len(magicReplace) { - t.Fatalf("internal test error: different magic lengths: %d != %d", len(magicInput), len(magicReplace)) - } - - obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace)) - - if err := os.WriteFile(to, obj, 0644); err != nil { - t.Fatal(err) - } - } - - cBadShared := filepath.Join(godir, "cbad.so") - rewrite(cShared, cBadShared) - - cBadObj := filepath.Join(godir, "cbad.o") - rewrite(cObj, cBadObj) - - goSourceBadObject := strings.ReplaceAll(goSource, "TMPDIR", godir) - makeFile(godir, "go.go", goSourceBadObject) - - makeFile(godir, "go.mod", "module badsym") - - // Try to build our little package. - cmd := exec.Command("go", "build", "-ldflags=-v") - cmd.Dir = godir - output, err := cmd.CombinedOutput() - - // The build should fail, but we want it to fail because we - // detected the error, not because we passed a bad flag to the - // C linker. - - if err == nil { - t.Errorf("go build succeeded unexpectedly") - } - - t.Logf("%s", output) - - for _, line := range bytes.Split(output, []byte("\n")) { - if bytes.Contains(line, []byte("dynamic symbol")) && bytes.Contains(line, []byte("contains unsupported character")) { - // This is the error from cgo. - continue - } - - // We passed -ldflags=-v to see the external linker invocation, - // which should not include -badflag. - if bytes.Contains(line, []byte("-badflag")) { - t.Error("output should not mention -badflag") - } - - // Also check for compiler errors, just in case. - // GCC says "unrecognized command line option". - // clang says "unknown argument". - if bytes.Contains(line, []byte("unrecognized")) || bytes.Contains(output, []byte("unknown")) { - t.Error("problem should have been caught before invoking C linker") - } - } -} - -func cCompilerCmd(t *testing.T) []string { - cc := []string{goEnv(t, "CC")} - - out := goEnv(t, "GOGCCFLAGS") - quote := '\000' - start := 0 - lastSpace := true - backslash := false - s := string(out) - for i, c := range s { - if quote == '\000' && unicode.IsSpace(c) { - if !lastSpace { - cc = append(cc, s[start:i]) - lastSpace = true - } - } else { - if lastSpace { - start = i - lastSpace = false - } - if quote == '\000' && !backslash && (c == '"' || c == '\'') { - quote = c - backslash = false - } else if !backslash && quote == c { - quote = '\000' - } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' { - backslash = true - } else { - backslash = false - } - } - } - if !lastSpace { - cc = append(cc, s[start:]) - } - - // Force reallocation (and avoid aliasing bugs) for tests that append to cc. - cc = cc[:len(cc):len(cc)] - - return cc -} - -func goEnv(t *testing.T, key string) string { - out, err := exec.Command("go", "env", key).CombinedOutput() - if err != nil { - t.Logf("go env %s\n", key) - t.Logf("%s", out) - t.Fatal(err) - } - return strings.TrimSpace(string(out)) -} diff --git a/misc/cgo/errors/errors_test.go b/misc/cgo/errors/errors_test.go deleted file mode 100644 index 9718b7f9fb..0000000000 --- a/misc/cgo/errors/errors_test.go +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright 2017 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 errorstest - -import ( - "bytes" - "fmt" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "strings" - "testing" -) - -func path(file string) string { - return filepath.Join("testdata", file) -} - -func check(t *testing.T, file string) { - t.Run(file, func(t *testing.T) { - t.Parallel() - - contents, err := os.ReadFile(path(file)) - if err != nil { - t.Fatal(err) - } - var errors []*regexp.Regexp - for i, line := range bytes.Split(contents, []byte("\n")) { - if bytes.HasSuffix(line, []byte("ERROR HERE")) { - re := regexp.MustCompile(regexp.QuoteMeta(fmt.Sprintf("%s:%d:", file, i+1))) - errors = append(errors, re) - continue - } - - _, frag, ok := bytes.Cut(line, []byte("ERROR HERE: ")) - if !ok { - continue - } - 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) - } - if len(errors) == 0 { - t.Fatalf("cannot find ERROR HERE") - } - expect(t, file, errors) - }) -} - -func expect(t *testing.T, file string, errors []*regexp.Regexp) { - dir, err := os.MkdirTemp("", filepath.Base(t.Name())) - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - - dst := filepath.Join(dir, strings.TrimSuffix(file, ".go")) - cmd := exec.Command("go", "build", "-gcflags=-L -e", "-o="+dst, path(file)) // TODO(gri) no need for -gcflags=-L if go tool is adjusted - out, err := cmd.CombinedOutput() - if err == nil { - t.Errorf("expected cgo to fail but it succeeded") - } - - lines := bytes.Split(out, []byte("\n")) - for _, re := range errors { - found := false - for _, line := range lines { - if re.Match(line) { - t.Logf("found match for %#q: %q", re, line) - found = true - break - } - } - if !found { - t.Errorf("expected error output to contain %#q", re) - } - } - - if t.Failed() { - t.Logf("actual output:\n%s", out) - } -} - -func sizeofLongDouble(t *testing.T) int { - cmd := exec.Command("go", "run", path("long_double_size.go")) - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out) - } - - i, err := strconv.Atoi(strings.TrimSpace(string(out))) - if err != nil { - t.Fatalf("long_double_size.go printed invalid size: %s", out) - } - return i -} - -func TestReportsTypeErrors(t *testing.T) { - for _, file := range []string{ - "err1.go", - "err2.go", - "issue11097a.go", - "issue11097b.go", - "issue18452.go", - "issue18889.go", - "issue28721.go", - "issue33061.go", - "issue50710.go", - } { - check(t, file) - } - - if sizeofLongDouble(t) > 8 { - for _, file := range []string{ - "err4.go", - "issue28069.go", - } { - check(t, file) - } - } -} - -func TestToleratesOptimizationFlag(t *testing.T) { - for _, cflags := range []string{ - "", - "-O", - } { - cflags := cflags - t.Run(cflags, func(t *testing.T) { - t.Parallel() - - cmd := exec.Command("go", "build", path("issue14669.go")) - cmd.Env = append(os.Environ(), "CGO_CFLAGS="+cflags) - out, err := cmd.CombinedOutput() - if err != nil { - t.Errorf("%#q: %v:\n%s", strings.Join(cmd.Args, " "), err, out) - } - }) - } -} - -func TestMallocCrashesOnNil(t *testing.T) { - t.Parallel() - - cmd := exec.Command("go", "run", path("malloc.go")) - out, err := cmd.CombinedOutput() - if err == nil { - t.Logf("%#q:\n%s", strings.Join(cmd.Args, " "), out) - t.Fatalf("succeeded unexpectedly") - } -} diff --git a/misc/cgo/errors/ptr_test.go b/misc/cgo/errors/ptr_test.go deleted file mode 100644 index 24851cbf35..0000000000 --- a/misc/cgo/errors/ptr_test.go +++ /dev/null @@ -1,656 +0,0 @@ -// 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. - -// Tests that cgo detects invalid pointer passing at runtime. - -package errorstest - -import ( - "bytes" - "flag" - "fmt" - "os" - "os/exec" - "path/filepath" - "strings" - "sync/atomic" - "testing" -) - -var tmp = flag.String("tmp", "", "use `dir` for temporary files and do not clean up") - -// ptrTest is the tests without the boilerplate. -type ptrTest struct { - name string // for reporting - c string // the cgo comment - c1 string // cgo comment forced into non-export cgo file - imports []string // a list of imports - support string // supporting functions - body string // the body of the main function - extra []extra // extra files - fail bool // whether the test should fail - expensive bool // whether the test requires the expensive check -} - -type extra struct { - name string - contents string -} - -var ptrTests = []ptrTest{ - { - // Passing a pointer to a struct that contains a Go pointer. - name: "ptr1", - c: `typedef struct s1 { int *p; } s1; void f1(s1 *ps) {}`, - body: `C.f1(&C.s1{new(C.int)})`, - fail: true, - }, - { - // Passing a pointer to a struct that contains a Go pointer. - name: "ptr2", - c: `typedef struct s2 { int *p; } s2; void f2(s2 *ps) {}`, - body: `p := &C.s2{new(C.int)}; C.f2(p)`, - fail: true, - }, - { - // Passing a pointer to an int field of a Go struct - // that (irrelevantly) contains a Go pointer. - name: "ok1", - c: `struct s3 { int i; int *p; }; void f3(int *p) {}`, - body: `p := &C.struct_s3{i: 0, p: new(C.int)}; C.f3(&p.i)`, - fail: false, - }, - { - // Passing a pointer to a pointer field of a Go struct. - name: "ptrfield", - c: `struct s4 { int i; int *p; }; void f4(int **p) {}`, - body: `p := &C.struct_s4{i: 0, p: new(C.int)}; C.f4(&p.p)`, - fail: true, - }, - { - // Passing a pointer to a pointer field of a Go - // struct, where the field does not contain a Go - // pointer, but another field (irrelevantly) does. - name: "ptrfieldok", - c: `struct s5 { int *p1; int *p2; }; void f5(int **p) {}`, - body: `p := &C.struct_s5{p1: nil, p2: new(C.int)}; C.f5(&p.p1)`, - fail: false, - }, - { - // Passing the address of a slice with no Go pointers. - name: "sliceok1", - c: `void f6(void **p) {}`, - imports: []string{"unsafe"}, - body: `s := []unsafe.Pointer{nil}; C.f6(&s[0])`, - fail: false, - }, - { - // Passing the address of a slice with a Go pointer. - name: "sliceptr1", - c: `void f7(void **p) {}`, - imports: []string{"unsafe"}, - body: `i := 0; s := []unsafe.Pointer{unsafe.Pointer(&i)}; C.f7(&s[0])`, - fail: true, - }, - { - // Passing the address of a slice with a Go pointer, - // where we are passing the address of an element that - // is not a Go pointer. - name: "sliceptr2", - c: `void f8(void **p) {}`, - imports: []string{"unsafe"}, - body: `i := 0; s := []unsafe.Pointer{nil, unsafe.Pointer(&i)}; C.f8(&s[0])`, - fail: true, - }, - { - // Passing the address of a slice that is an element - // in a struct only looks at the slice. - name: "sliceok2", - c: `void f9(void **p) {}`, - imports: []string{"unsafe"}, - support: `type S9 struct { p *int; s []unsafe.Pointer }`, - body: `i := 0; p := &S9{p:&i, s:[]unsafe.Pointer{nil}}; C.f9(&p.s[0])`, - fail: false, - }, - { - // Passing the address of a slice of an array that is - // an element in a struct, with a type conversion. - name: "sliceok3", - c: `void f10(void* p) {}`, - imports: []string{"unsafe"}, - support: `type S10 struct { p *int; a [4]byte }`, - body: `i := 0; p := &S10{p:&i}; s := p.a[:]; C.f10(unsafe.Pointer(&s[0]))`, - fail: false, - }, - { - // Passing the address of a slice of an array that is - // an element in a struct, with a type conversion. - name: "sliceok4", - c: `typedef void* PV11; void f11(PV11 p) {}`, - imports: []string{"unsafe"}, - support: `type S11 struct { p *int; a [4]byte }`, - body: `i := 0; p := &S11{p:&i}; C.f11(C.PV11(unsafe.Pointer(&p.a[0])))`, - fail: false, - }, - { - // Passing the address of a static variable with no - // pointers doesn't matter. - name: "varok", - c: `void f12(char** parg) {}`, - support: `var hello12 = [...]C.char{'h', 'e', 'l', 'l', 'o'}`, - body: `parg := [1]*C.char{&hello12[0]}; C.f12(&parg[0])`, - fail: false, - }, - { - // Passing the address of a static variable with - // pointers does matter. - name: "var1", - c: `void f13(char*** parg) {}`, - support: `var hello13 = [...]*C.char{new(C.char)}`, - body: `parg := [1]**C.char{&hello13[0]}; C.f13(&parg[0])`, - fail: true, - }, - { - // Storing a Go pointer into C memory should fail. - name: "barrier", - c: `#include <stdlib.h> - char **f14a() { return malloc(sizeof(char*)); } - void f14b(char **p) {}`, - body: `p := C.f14a(); *p = new(C.char); C.f14b(p)`, - fail: true, - expensive: true, - }, - { - // Storing a Go pointer into C memory by assigning a - // large value should fail. - name: "barrierstruct", - c: `#include <stdlib.h> - struct s15 { char *a[10]; }; - struct s15 *f15() { return malloc(sizeof(struct s15)); } - void f15b(struct s15 *p) {}`, - body: `p := C.f15(); p.a = [10]*C.char{new(C.char)}; C.f15b(p)`, - fail: true, - expensive: true, - }, - { - // Storing a Go pointer into C memory using a slice - // copy should fail. - name: "barrierslice", - c: `#include <stdlib.h> - struct s16 { char *a[10]; }; - struct s16 *f16() { return malloc(sizeof(struct s16)); } - void f16b(struct s16 *p) {}`, - body: `p := C.f16(); copy(p.a[:], []*C.char{new(C.char)}); C.f16b(p)`, - fail: true, - expensive: true, - }, - { - // A very large value uses a GC program, which is a - // different code path. - name: "barriergcprogarray", - c: `#include <stdlib.h> - struct s17 { char *a[32769]; }; - struct s17 *f17() { return malloc(sizeof(struct s17)); } - void f17b(struct s17 *p) {}`, - body: `p := C.f17(); p.a = [32769]*C.char{new(C.char)}; C.f17b(p)`, - fail: true, - expensive: true, - }, - { - // Similar case, with a source on the heap. - name: "barriergcprogarrayheap", - c: `#include <stdlib.h> - struct s18 { char *a[32769]; }; - struct s18 *f18() { return malloc(sizeof(struct s18)); } - void f18b(struct s18 *p) {} - void f18c(void *p) {}`, - imports: []string{"unsafe"}, - body: `p := C.f18(); n := &[32769]*C.char{new(C.char)}; p.a = *n; C.f18b(p); n[0] = nil; C.f18c(unsafe.Pointer(n))`, - fail: true, - expensive: true, - }, - { - // A GC program with a struct. - name: "barriergcprogstruct", - c: `#include <stdlib.h> - struct s19a { char *a[32769]; }; - struct s19b { struct s19a f; }; - struct s19b *f19() { return malloc(sizeof(struct s19b)); } - void f19b(struct s19b *p) {}`, - body: `p := C.f19(); p.f = C.struct_s19a{[32769]*C.char{new(C.char)}}; C.f19b(p)`, - fail: true, - expensive: true, - }, - { - // Similar case, with a source on the heap. - name: "barriergcprogstructheap", - c: `#include <stdlib.h> - struct s20a { char *a[32769]; }; - struct s20b { struct s20a f; }; - struct s20b *f20() { return malloc(sizeof(struct s20b)); } - void f20b(struct s20b *p) {} - void f20c(void *p) {}`, - imports: []string{"unsafe"}, - body: `p := C.f20(); n := &C.struct_s20a{[32769]*C.char{new(C.char)}}; p.f = *n; C.f20b(p); n.a[0] = nil; C.f20c(unsafe.Pointer(n))`, - fail: true, - expensive: true, - }, - { - // Exported functions may not return Go pointers. - name: "export1", - c: `extern unsigned char *GoFn21();`, - support: `//export GoFn21 - func GoFn21() *byte { return new(byte) }`, - body: `C.GoFn21()`, - fail: true, - }, - { - // Returning a C pointer is fine. - name: "exportok", - c: `#include <stdlib.h> - extern unsigned char *GoFn22();`, - support: `//export GoFn22 - func GoFn22() *byte { return (*byte)(C.malloc(1)) }`, - body: `C.GoFn22()`, - }, - { - // Passing a Go string is fine. - name: "passstring", - c: `#include <stddef.h> - typedef struct { const char *p; ptrdiff_t n; } gostring23; - gostring23 f23(gostring23 s) { return s; }`, - imports: []string{"unsafe"}, - body: `s := "a"; r := C.f23(*(*C.gostring23)(unsafe.Pointer(&s))); if *(*string)(unsafe.Pointer(&r)) != s { panic(r) }`, - }, - { - // Passing a slice of Go strings fails. - name: "passstringslice", - c: `void f24(void *p) {}`, - imports: []string{"strings", "unsafe"}, - support: `type S24 struct { a [1]string }`, - body: `s := S24{a:[1]string{strings.Repeat("a", 2)}}; C.f24(unsafe.Pointer(&s.a[0]))`, - fail: true, - }, - { - // Exported functions may not return strings. - name: "retstring", - c: `extern void f25();`, - imports: []string{"strings"}, - support: `//export GoStr25 - func GoStr25() string { return strings.Repeat("a", 2) }`, - body: `C.f25()`, - c1: `#include <stddef.h> - typedef struct { const char *p; ptrdiff_t n; } gostring25; - extern gostring25 GoStr25(); - void f25() { GoStr25(); }`, - fail: true, - }, - { - // Don't check non-pointer data. - // Uses unsafe code to get a pointer we shouldn't check. - // Although we use unsafe, the uintptr represents an integer - // that happens to have the same representation as a pointer; - // that is, we are testing something that is not unsafe. - name: "ptrdata1", - c: `#include <stdlib.h> - void f26(void* p) {}`, - imports: []string{"unsafe"}, - support: `type S26 struct { p *int; a [8*8]byte; u uintptr }`, - body: `i := 0; p := &S26{u:uintptr(unsafe.Pointer(&i))}; q := (*S26)(C.malloc(C.size_t(unsafe.Sizeof(*p)))); *q = *p; C.f26(unsafe.Pointer(q))`, - fail: false, - }, - { - // Like ptrdata1, but with a type that uses a GC program. - name: "ptrdata2", - c: `#include <stdlib.h> - void f27(void* p) {}`, - imports: []string{"unsafe"}, - support: `type S27 struct { p *int; a [32769*8]byte; q *int; u uintptr }`, - body: `i := 0; p := S27{u:uintptr(unsafe.Pointer(&i))}; q := (*S27)(C.malloc(C.size_t(unsafe.Sizeof(p)))); *q = p; C.f27(unsafe.Pointer(q))`, - fail: false, - }, - { - // Check deferred pointers when they are used, not - // when the defer statement is run. - name: "defer1", - c: `typedef struct s28 { int *p; } s28; void f28(s28 *ps) {}`, - body: `p := &C.s28{}; defer C.f28(p); p.p = new(C.int)`, - fail: true, - }, - { - // Check a pointer to a union if the union has any - // pointer fields. - name: "union1", - c: `typedef union { char **p; unsigned long i; } u29; void f29(u29 *pu) {}`, - imports: []string{"unsafe"}, - body: `var b C.char; p := &b; C.f29((*C.u29)(unsafe.Pointer(&p)))`, - fail: true, - }, - { - // Don't check a pointer to a union if the union does - // not have any pointer fields. - // Like ptrdata1 above, the uintptr represents an - // integer that happens to have the same - // representation as a pointer. - name: "union2", - c: `typedef union { unsigned long i; } u39; void f39(u39 *pu) {}`, - imports: []string{"unsafe"}, - body: `var b C.char; p := &b; C.f39((*C.u39)(unsafe.Pointer(&p)))`, - fail: false, - }, - { - // Test preemption while entering a cgo call. Issue #21306. - name: "preemptduringcall", - c: `void f30() {}`, - imports: []string{"runtime", "sync"}, - body: `var wg sync.WaitGroup; wg.Add(100); for i := 0; i < 100; i++ { go func(i int) { for j := 0; j < 100; j++ { C.f30(); runtime.GOMAXPROCS(i) }; wg.Done() }(i) }; wg.Wait()`, - fail: false, - }, - { - // Test poller deadline with cgocheck=2. Issue #23435. - name: "deadline", - c: `#define US31 10`, - imports: []string{"os", "time"}, - body: `r, _, _ := os.Pipe(); r.SetDeadline(time.Now().Add(C.US31 * time.Microsecond))`, - fail: false, - }, - { - // Test for double evaluation of channel receive. - name: "chanrecv", - c: `void f32(char** p) {}`, - imports: []string{"time"}, - body: `c := make(chan []*C.char, 2); c <- make([]*C.char, 1); go func() { time.Sleep(10 * time.Second); panic("received twice from chan") }(); C.f32(&(<-c)[0]);`, - fail: false, - }, - { - // Test that converting the address of a struct field - // to unsafe.Pointer still just checks that field. - // Issue #25941. - name: "structfield", - c: `void f33(void* p) {}`, - imports: []string{"unsafe"}, - support: `type S33 struct { p *int; a [8]byte; u uintptr }`, - body: `s := &S33{p: new(int)}; C.f33(unsafe.Pointer(&s.a))`, - fail: false, - }, - { - // Test that converting multiple struct field - // addresses to unsafe.Pointer still just checks those - // fields. Issue #25941. - name: "structfield2", - c: `void f34(void* p, int r, void* s) {}`, - imports: []string{"unsafe"}, - support: `type S34 struct { a [8]byte; p *int; b int64; }`, - body: `s := &S34{p: new(int)}; C.f34(unsafe.Pointer(&s.a), 32, unsafe.Pointer(&s.b))`, - fail: false, - }, - { - // Test that second argument to cgoCheckPointer is - // evaluated when a deferred function is deferred, not - // when it is run. - name: "defer2", - c: `void f35(char **pc) {}`, - support: `type S35a struct { s []*C.char }; type S35b struct { ps *S35a }`, - body: `p := &S35b{&S35a{[]*C.char{nil}}}; defer C.f35(&p.ps.s[0]); p.ps = nil`, - fail: false, - }, - { - // Test that indexing into a function call still - // examines only the slice being indexed. - name: "buffer", - c: `void f36(void *p) {}`, - imports: []string{"bytes", "unsafe"}, - body: `var b bytes.Buffer; b.WriteString("a"); C.f36(unsafe.Pointer(&b.Bytes()[0]))`, - fail: false, - }, - { - // Test that bgsweep releasing a finalizer is OK. - name: "finalizer", - c: `// Nothing to declare.`, - imports: []string{"os"}, - support: `func open37() { os.Open(os.Args[0]) }; var G37 [][]byte`, - body: `for i := 0; i < 10000; i++ { G37 = append(G37, make([]byte, 4096)); if i % 100 == 0 { G37 = nil; open37() } }`, - fail: false, - }, - { - // Test that converting generated struct to interface is OK. - name: "structof", - c: `// Nothing to declare.`, - imports: []string{"reflect"}, - support: `type MyInt38 int; func (i MyInt38) Get() int { return int(i) }; type Getter38 interface { Get() int }`, - body: `t := reflect.StructOf([]reflect.StructField{{Name: "MyInt38", Type: reflect.TypeOf(MyInt38(0)), Anonymous: true}}); v := reflect.New(t).Elem(); v.Interface().(Getter38).Get()`, - fail: false, - }, - { - // Test that a converted address of a struct field results - // in a check for just that field and not the whole struct. - name: "structfieldcast", - c: `struct S40i { int i; int* p; }; void f40(struct S40i* p) {}`, - support: `type S40 struct { p *int; a C.struct_S40i }`, - body: `s := &S40{p: new(int)}; C.f40((*C.struct_S40i)(&s.a))`, - fail: false, - }, -} - -func TestPointerChecks(t *testing.T) { - var gopath string - var dir string - if *tmp != "" { - gopath = *tmp - dir = "" - } else { - d, err := os.MkdirTemp("", filepath.Base(t.Name())) - if err != nil { - t.Fatal(err) - } - dir = d - gopath = d - } - - exe := buildPtrTests(t, gopath, false) - exe2 := buildPtrTests(t, gopath, true) - - // We (TestPointerChecks) return before the parallel subtest functions do, - // so we can't just defer os.RemoveAll(dir). Instead we have to wait for - // the parallel subtests to finish. This code looks racy but is not: - // the add +1 run in serial before testOne blocks. The -1 run in parallel - // after testOne finishes. - var pending int32 - for _, pt := range ptrTests { - pt := pt - t.Run(pt.name, func(t *testing.T) { - atomic.AddInt32(&pending, +1) - defer func() { - if atomic.AddInt32(&pending, -1) == 0 { - os.RemoveAll(dir) - } - }() - testOne(t, pt, exe, exe2) - }) - } -} - -func buildPtrTests(t *testing.T, gopath string, cgocheck2 bool) (exe string) { - - src := filepath.Join(gopath, "src", "ptrtest") - if err := os.MkdirAll(src, 0777); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil { - t.Fatal(err) - } - - // Prepare two cgo inputs: one for standard cgo and one for //export cgo. - // (The latter cannot have C definitions, only declarations.) - var cgo1, cgo2 bytes.Buffer - fmt.Fprintf(&cgo1, "package main\n\n/*\n") - fmt.Fprintf(&cgo2, "package main\n\n/*\n") - - // C code - for _, pt := range ptrTests { - cgo := &cgo1 - if strings.Contains(pt.support, "//export") { - cgo = &cgo2 - } - fmt.Fprintf(cgo, "%s\n", pt.c) - fmt.Fprintf(&cgo1, "%s\n", pt.c1) - } - fmt.Fprintf(&cgo1, "*/\nimport \"C\"\n\n") - fmt.Fprintf(&cgo2, "*/\nimport \"C\"\n\n") - - // Imports - did1 := make(map[string]bool) - did2 := make(map[string]bool) - did1["os"] = true // for ptrTestMain - fmt.Fprintf(&cgo1, "import \"os\"\n") - - for _, pt := range ptrTests { - did := did1 - cgo := &cgo1 - if strings.Contains(pt.support, "//export") { - did = did2 - cgo = &cgo2 - } - for _, imp := range pt.imports { - if !did[imp] { - did[imp] = true - fmt.Fprintf(cgo, "import %q\n", imp) - } - } - } - - // Func support and bodies. - for _, pt := range ptrTests { - cgo := &cgo1 - if strings.Contains(pt.support, "//export") { - cgo = &cgo2 - } - fmt.Fprintf(cgo, "%s\nfunc %s() {\n%s\n}\n", pt.support, pt.name, pt.body) - } - - // Func list and main dispatch. - fmt.Fprintf(&cgo1, "var funcs = map[string]func() {\n") - for _, pt := range ptrTests { - fmt.Fprintf(&cgo1, "\t%q: %s,\n", pt.name, pt.name) - } - fmt.Fprintf(&cgo1, "}\n\n") - fmt.Fprintf(&cgo1, "%s\n", ptrTestMain) - - if err := os.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil { - t.Fatal(err) - } - - exeName := "ptrtest.exe" - if cgocheck2 { - exeName = "ptrtest2.exe" - } - cmd := exec.Command("go", "build", "-o", exeName) - cmd.Dir = src - cmd.Env = append(os.Environ(), "GOPATH="+gopath) - if cgocheck2 { - found := false - for i, e := range cmd.Env { - if strings.HasPrefix(e, "GOEXPERIMENT=") { - cmd.Env[i] = e + ",cgocheck2" - found = true - } - } - if !found { - cmd.Env = append(cmd.Env, "GOEXPERIMENT=cgocheck2") - } - } - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("go build: %v\n%s", err, out) - } - - return filepath.Join(src, exeName) -} - -const ptrTestMain = ` -func main() { - for _, arg := range os.Args[1:] { - f := funcs[arg] - if f == nil { - panic("missing func "+arg) - } - f() - } -} -` - -var csem = make(chan bool, 16) - -func testOne(t *testing.T, pt ptrTest, exe, exe2 string) { - t.Parallel() - - // Run the tests in parallel, but don't run too many - // executions in parallel, to avoid overloading the system. - runcmd := func(cgocheck string) ([]byte, error) { - csem <- true - defer func() { <-csem }() - x := exe - if cgocheck == "2" { - x = exe2 - cgocheck = "1" - } - cmd := exec.Command(x, pt.name) - cmd.Env = append(os.Environ(), "GODEBUG=cgocheck="+cgocheck) - return cmd.CombinedOutput() - } - - if pt.expensive { - buf, err := runcmd("1") - if err != nil { - t.Logf("%s", buf) - if pt.fail { - t.Fatalf("test marked expensive, but failed when not expensive: %v", err) - } else { - t.Errorf("failed unexpectedly with GODEBUG=cgocheck=1: %v", err) - } - } - - } - - cgocheck := "" - if pt.expensive { - cgocheck = "2" - } - - buf, err := runcmd(cgocheck) - if pt.fail { - if err == nil { - t.Logf("%s", buf) - t.Fatalf("did not fail as expected") - } else if !bytes.Contains(buf, []byte("Go pointer")) { - t.Logf("%s", buf) - t.Fatalf("did not print expected error (failed with %v)", err) - } - } else { - if err != nil { - t.Logf("%s", buf) - t.Fatalf("failed unexpectedly: %v", err) - } - - if !pt.expensive { - // Make sure it passes with the expensive checks. - buf, err := runcmd("2") - if err != nil { - t.Logf("%s", buf) - t.Fatalf("failed unexpectedly with expensive checks: %v", err) - } - } - } - - if pt.fail { - buf, err := runcmd("0") - if err != nil { - t.Logf("%s", buf) - t.Fatalf("failed unexpectedly with GODEBUG=cgocheck=0: %v", err) - } - } -} diff --git a/misc/cgo/errors/testdata/err1.go b/misc/cgo/errors/testdata/err1.go deleted file mode 100644 index ced7443599..0000000000 --- a/misc/cgo/errors/testdata/err1.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -package main - -/* -#cgo LDFLAGS: -L/nonexist - -void test() { - xxx; // ERROR HERE -} - -// Issue 8442. Cgo output unhelpful error messages for -// invalid C preambles. -void issue8442foo(UNDEF*); // ERROR HERE -*/ -import "C" - -func main() { - C.test() -} diff --git a/misc/cgo/errors/testdata/err2.go b/misc/cgo/errors/testdata/err2.go deleted file mode 100644 index aa941584c3..0000000000 --- a/misc/cgo/errors/testdata/err2.go +++ /dev/null @@ -1,110 +0,0 @@ -// 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. - -package main - -/* -#include <stdio.h> - -typedef struct foo foo_t; -typedef struct bar bar_t; - -foo_t *foop; - -long double x = 0; - -static int transform(int x) { return x; } - -typedef void v; -void F(v** p) {} - -void fvi(void *p, int x) {} - -void fppi(int** p) {} - -int i; -void fi(int i) {} -*/ -import "C" -import ( - "unsafe" -) - -func main() { - s := "" - _ = s - C.malloc(s) // ERROR HERE - - x := (*C.bar_t)(nil) - C.foop = x // ERROR HERE - - // issue 13129: used to output error about C.unsignedshort with CC=clang - var x1 C.ushort - x1 = int(0) // ERROR HERE: C\.ushort - - // issue 13423 - _ = C.fopen() // ERROR HERE - - // issue 13467 - 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. - var ( - _ C.uchar = "uc" // ERROR HERE: C\.uchar - _ C.schar = "sc" // ERROR HERE: C\.schar - _ C.ushort = "us" // ERROR HERE: C\.ushort - _ C.uint = "ui" // ERROR HERE: C\.uint - _ C.ulong = "ul" // ERROR HERE: C\.ulong - _ C.longlong = "ll" // ERROR HERE: C\.longlong - _ C.ulonglong = "ull" // ERROR HERE: C\.ulonglong - _ C.complexfloat = "cf" // ERROR HERE: C\.complexfloat - _ C.complexdouble = "cd" // ERROR HERE: C\.complexdouble - ) - - // issue 13830 - // cgo converts C void* to Go unsafe.Pointer, so despite appearances C - // void** is Go *unsafe.Pointer. This test verifies that we detect the - // problem at build time. - { - type v [0]byte - - f := func(p **v) { - C.F((**C.v)(unsafe.Pointer(p))) // ERROR HERE - } - var p *v - f(&p) - } - - // issue 16116 - _ = C.fvi(1) // ERROR HERE - - // Issue 16591: Test that we detect an invalid call that was being - // hidden by a type conversion inserted by cgo checking. - { - type x *C.int - var p *x - C.fppi(p) // ERROR HERE - } - - // issue 26745 - _ = func(i int) int { - // typecheck reports at column 14 ('+'), but types2 reports at - // column 10 ('C'). - // TODO(mdempsky): Investigate why, and see if types2 can be - // updated to match typecheck behavior. - return C.i + 1 // ERROR HERE: \b(10|14)\b - } - _ = func(i int) { - // typecheck reports at column 7 ('('), but types2 reports at - // column 8 ('i'). The types2 position is more correct, but - // updating typecheck here is fundamentally challenging because of - // IR limitations. - C.fi(i) // ERROR HERE: \b(7|8)\b - } - - C.fi = C.fi // ERROR HERE - -} diff --git a/misc/cgo/errors/testdata/err4.go b/misc/cgo/errors/testdata/err4.go deleted file mode 100644 index 8e5f78e987..0000000000 --- a/misc/cgo/errors/testdata/err4.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 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 - -/* -long double x = 0; -*/ -import "C" - -func main() { - _ = C.x // ERROR HERE - _ = C.x -} diff --git a/misc/cgo/errors/testdata/issue11097a.go b/misc/cgo/errors/testdata/issue11097a.go deleted file mode 100644 index 028d10ce5c..0000000000 --- a/misc/cgo/errors/testdata/issue11097a.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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 main - -/* -//enum test { foo, bar }; -*/ -import "C" - -func main() { - var a = C.enum_test(1) // ERROR HERE - _ = a -} diff --git a/misc/cgo/errors/testdata/issue11097b.go b/misc/cgo/errors/testdata/issue11097b.go deleted file mode 100644 index b00f24fc10..0000000000 --- a/misc/cgo/errors/testdata/issue11097b.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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 main - -/* -//enum test { foo, bar }; -*/ -import "C" - -func main() { - p := new(C.enum_test) // ERROR HERE - _ = p -} diff --git a/misc/cgo/errors/testdata/issue14669.go b/misc/cgo/errors/testdata/issue14669.go deleted file mode 100644 index 04d2bcb631..0000000000 --- a/misc/cgo/errors/testdata/issue14669.go +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -// Issue 14669: test that fails when build with CGO_CFLAGS selecting -// optimization. - -package p - -/* -const int E = 1; - -typedef struct s { - int c; -} s; -*/ -import "C" - -func F() { - _ = C.s{ - c: C.E, - } -} diff --git a/misc/cgo/errors/testdata/issue18452.go b/misc/cgo/errors/testdata/issue18452.go deleted file mode 100644 index 0386d76892..0000000000 --- a/misc/cgo/errors/testdata/issue18452.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2017 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 18452: show pos info in undefined name errors - -package p - -import ( - "C" - "fmt" -) - -func a() { - fmt.Println("Hello, world!") - C.function_that_does_not_exist() // ERROR HERE - C.pi // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue18889.go b/misc/cgo/errors/testdata/issue18889.go deleted file mode 100644 index bba6b8f9bb..0000000000 --- a/misc/cgo/errors/testdata/issue18889.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "C" - -func main() { - _ = C.malloc // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue28069.go b/misc/cgo/errors/testdata/issue28069.go deleted file mode 100644 index e19a3b45bd..0000000000 --- a/misc/cgo/errors/testdata/issue28069.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -// Test that the error message for an unrepresentable typedef in a -// union appears on the right line. This test is only run if the size -// of long double is larger than 64. - -package main - -/* -typedef long double Float128; - -typedef struct SV { - union { - Float128 float128; - } value; -} SV; -*/ -import "C" - -type ts struct { - tv *C.SV // ERROR HERE -} - -func main() {} diff --git a/misc/cgo/errors/testdata/issue28721.go b/misc/cgo/errors/testdata/issue28721.go deleted file mode 100644 index 0eb2a9271c..0000000000 --- a/misc/cgo/errors/testdata/issue28721.go +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -// cgo should reject the use of mangled C names. - -package main - -/* -typedef struct a { - int i; -} a; -void fn(void) {} -*/ -import "C" - -type B _Ctype_struct_a // ERROR HERE - -var a _Ctype_struct_a // ERROR HERE - -type A struct { - a *_Ctype_struct_a // ERROR HERE -} - -var notExist _Ctype_NotExist // ERROR HERE - -func main() { - _Cfunc_fn() // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue33061.go b/misc/cgo/errors/testdata/issue33061.go deleted file mode 100644 index 77d5f7a7c9..0000000000 --- a/misc/cgo/errors/testdata/issue33061.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2019 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. - -// cgo shouldn't crash if there is an extra argument with a C reference. - -package main - -// void F(void* p) {}; -import "C" - -import "unsafe" - -func F() { - var i int - C.F(unsafe.Pointer(&i), C.int(0)) // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/issue42580.go b/misc/cgo/errors/testdata/issue42580.go deleted file mode 100644 index aba80dfeba..0000000000 --- a/misc/cgo/errors/testdata/issue42580.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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/misc/cgo/errors/testdata/issue50710.go b/misc/cgo/errors/testdata/issue50710.go deleted file mode 100644 index dffea22903..0000000000 --- a/misc/cgo/errors/testdata/issue50710.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2022 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 - -// size_t StrLen(_GoString_ s) { -// return _GoStringLen(s); -// } -import "C" - -func main() { - C.StrLen1() // ERROR HERE -} diff --git a/misc/cgo/errors/testdata/long_double_size.go b/misc/cgo/errors/testdata/long_double_size.go deleted file mode 100644 index 8b797f886a..0000000000 --- a/misc/cgo/errors/testdata/long_double_size.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 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 - -/* -const int sizeofLongDouble = sizeof(long double); -*/ -import "C" - -import "fmt" - -func main() { - fmt.Println(C.sizeofLongDouble) -} diff --git a/misc/cgo/errors/testdata/malloc.go b/misc/cgo/errors/testdata/malloc.go deleted file mode 100644 index 65da0208b9..0000000000 --- a/misc/cgo/errors/testdata/malloc.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -// Test that C.malloc does not return nil. - -package main - -// #include <stdlib.h> -import "C" - -import ( - "fmt" - "runtime" -) - -func main() { - var size C.size_t - size-- - - // The Dragonfly libc succeeds when asked to allocate - // 0xffffffffffffffff bytes, so pass a different value that - // causes it to fail. - if runtime.GOOS == "dragonfly" { - size = C.size_t(0x7fffffff << (32 * (^uintptr(0) >> 63))) - } - - p := C.malloc(size) - if p == nil { - fmt.Println("malloc: C.malloc returned nil") - // Just exit normally--the test script expects this - // program to crash, so exiting normally indicates failure. - } -} diff --git a/misc/cgo/fortran/fortran_test.go b/misc/cgo/fortran/fortran_test.go deleted file mode 100644 index 4604a4dce3..0000000000 --- a/misc/cgo/fortran/fortran_test.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2022 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 fortran - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "testing" -) - -func TestFortran(t *testing.T) { - // Find the FORTRAN compiler. - fc := os.Getenv("FC") - if fc == "" { - fc, _ = exec.LookPath("gfortran") - } - if fc == "" { - t.Skip("fortran compiler not found (try setting $FC)") - } - - var fcExtra []string - if strings.Contains(fc, "gfortran") { - // TODO: This duplicates but also diverges from logic from cmd/go - // itself. For example, cmd/go merely adds -lgfortran without the extra - // library path work. If this is what's necessary to run gfortran, we - // should reconcile the logic here and in cmd/go.. Maybe this should - // become a cmd/go script test to share that logic. - - // Add -m32 if we're targeting 386, in case this is a cross-compile. - if runtime.GOARCH == "386" { - fcExtra = append(fcExtra, "-m32") - } - - // Find libgfortran. If the FORTRAN compiler isn't bundled - // with the C linker, this may be in a path the C linker can't - // find on its own. (See #14544) - libExt := "so" - switch runtime.GOOS { - case "darwin": - libExt = "dylib" - case "aix": - libExt = "a" - } - libPath, err := exec.Command(fc, append([]string{"-print-file-name=libgfortran." + libExt}, fcExtra...)...).CombinedOutput() - if err != nil { - t.Errorf("error invoking %s: %s", fc, err) - } - libDir := filepath.Dir(string(libPath)) - cgoLDFlags := os.Getenv("CGO_LDFLAGS") - cgoLDFlags += " -L " + libDir - if runtime.GOOS != "aix" { - cgoLDFlags += " -Wl,-rpath," + libDir - } - t.Logf("CGO_LDFLAGS=%s", cgoLDFlags) - os.Setenv("CGO_LDFLAGS", cgoLDFlags) - - } - - // Do a test build that doesn't involve Go FORTRAN support. - fcArgs := append([]string{"helloworld/helloworld.f90", "-o", "/dev/null"}, fcExtra...) - t.Logf("%s %s", fc, fcArgs) - if err := exec.Command(fc, fcArgs...).Run(); err != nil { - t.Skipf("skipping Fortran test: could not build helloworld.f90 with %s: %s", fc, err) - } - - // 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") - } - if err != nil { - t.Errorf("%s\nOutput:\n%s", err, string(out)) - } -} diff --git a/misc/cgo/fortran/helloworld/helloworld.f90 b/misc/cgo/fortran/helloworld/helloworld.f90 deleted file mode 100644 index cbc34c16ef..0000000000 --- a/misc/cgo/fortran/helloworld/helloworld.f90 +++ /dev/null @@ -1,3 +0,0 @@ - program HelloWorldF90 - write(*,*) "Hello World!" - end program HelloWorldF90 diff --git a/misc/cgo/fortran/testdata/testprog/answer.f90 b/misc/cgo/fortran/testdata/testprog/answer.f90 deleted file mode 100644 index b3717ee27a..0000000000 --- a/misc/cgo/fortran/testdata/testprog/answer.f90 +++ /dev/null @@ -1,9 +0,0 @@ -! 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. - -function the_answer() result(j) bind(C) - use iso_c_binding, only: c_int - integer(c_int) :: j ! output - j = 42 -end function the_answer diff --git a/misc/cgo/fortran/testdata/testprog/fortran.go b/misc/cgo/fortran/testdata/testprog/fortran.go deleted file mode 100644 index d8004ceb6d..0000000000 --- a/misc/cgo/fortran/testdata/testprog/fortran.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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 main - -// int the_answer(); -import "C" -import "os" - -func TheAnswer() int { - return int(C.the_answer()) -} - -func main() { - if a := TheAnswer(); a != 42 { - println("Unexpected result for The Answer. Got:", a, " Want: 42") - os.Exit(1) - } - println("ok") -} diff --git a/misc/cgo/life/life_test.go b/misc/cgo/life/life_test.go deleted file mode 100644 index 98d25a197d..0000000000 --- a/misc/cgo/life/life_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2019 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 life_test - -import ( - "bytes" - "log" - "os" - "os/exec" - "path/filepath" - "testing" -) - -func TestMain(m *testing.M) { - log.SetFlags(log.Lshortfile) - os.Exit(testMain(m)) -} - -func testMain(m *testing.M) int { - GOPATH, err := os.MkdirTemp("", "cgolife") - if err != nil { - log.Panic(err) - } - defer os.RemoveAll(GOPATH) - os.Setenv("GOPATH", GOPATH) - - // Copy testdata into GOPATH/src/cgolife, along with a go.mod file - // declaring the same path. - modRoot := filepath.Join(GOPATH, "src", "cgolife") - if err := overlayDir(modRoot, "testdata"); err != nil { - log.Panic(err) - } - if err := os.Chdir(modRoot); err != nil { - log.Panic(err) - } - os.Setenv("PWD", modRoot) - if err := os.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil { - log.Panic(err) - } - - return m.Run() -} - -// TestTestRun runs a test case for cgo //export. -func TestTestRun(t *testing.T) { - if os.Getenv("GOOS") == "android" { - t.Skip("the go tool runs with CGO_ENABLED=0 on the android device") - } - - cmd := exec.Command("go", "run", "main.go") - got, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("%v: %s\n%s", cmd, err, got) - } - want, err := os.ReadFile("main.out") - if err != nil { - t.Fatal("reading golden output:", err) - } - if !bytes.Equal(got, want) { - t.Errorf("'%v' output does not match expected in main.out. Instead saw:\n%s", cmd, got) - } -} diff --git a/misc/cgo/life/overlaydir_test.go b/misc/cgo/life/overlaydir_test.go deleted file mode 100644 index 034c836248..0000000000 --- a/misc/cgo/life/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 life_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/life/testdata/c-life.c b/misc/cgo/life/testdata/c-life.c deleted file mode 100644 index f853163e2f..0000000000 --- a/misc/cgo/life/testdata/c-life.c +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2010 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 <assert.h> -#include "life.h" -#include "_cgo_export.h" - -const int MYCONST = 0; - -// Do the actual manipulation of the life board in C. This could be -// done easily in Go, we are just using C for demonstration -// purposes. -void -Step(int x, int y, int *a, int *n) -{ - struct GoStart_return r; - - // Use Go to start 4 goroutines each of which handles 1/4 of the - // board. - r = GoStart(0, x, y, 0, x / 2, 0, y / 2, a, n); - assert(r.r0 == 0 && r.r1 == 100); // test multiple returns - r = GoStart(1, x, y, x / 2, x, 0, y / 2, a, n); - assert(r.r0 == 1 && r.r1 == 101); // test multiple returns - GoStart(2, x, y, 0, x / 2, y / 2, y, a, n); - GoStart(3, x, y, x / 2, x, y / 2, y, a, n); - GoWait(0); - GoWait(1); - GoWait(2); - GoWait(3); -} - -// The actual computation. This is called in parallel. -void -DoStep(int xdim, int ydim, int xstart, int xend, int ystart, int yend, int *a, int *n) -{ - int x, y, c, i, j; - - for(x = xstart; x < xend; x++) { - for(y = ystart; y < yend; y++) { - c = 0; - for(i = -1; i <= 1; i++) { - for(j = -1; j <= 1; j++) { - if(x+i >= 0 && x+i < xdim && - y+j >= 0 && y+j < ydim && - (i != 0 || j != 0)) - c += a[(x+i)*xdim + (y+j)] != 0; - } - } - if(c == 3 || (c == 2 && a[x*xdim + y] != 0)) - n[x*xdim + y] = 1; - else - n[x*xdim + y] = 0; - } - } -} diff --git a/misc/cgo/life/testdata/life.go b/misc/cgo/life/testdata/life.go deleted file mode 100644 index 72311404df..0000000000 --- a/misc/cgo/life/testdata/life.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2010 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 cgolife - -// #include "life.h" -import "C" - -import "unsafe" - -func Run(gen, x, y int, a []int32) { - n := make([]int32, x*y) - for i := 0; i < gen; i++ { - C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0]))) - copy(a, n) - } -} - -// Keep the channels visible from Go. -var chans [4]chan bool - -// Double return value is just for testing. -// -//export GoStart -func GoStart(i, xdim, ydim, xstart, xend, ystart, yend C.int, a *C.int, n *C.int) (int, int) { - c := make(chan bool, int(C.MYCONST)) - go func() { - C.DoStep(xdim, ydim, xstart, xend, ystart, yend, a, n) - c <- true - }() - chans[i] = c - return int(i), int(i + 100) -} - -//export GoWait -func GoWait(i C.int) { - <-chans[i] - chans[i] = nil -} diff --git a/misc/cgo/life/testdata/life.h b/misc/cgo/life/testdata/life.h deleted file mode 100644 index 11d2b97226..0000000000 --- a/misc/cgo/life/testdata/life.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2010 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. - -extern void Step(int, int, int *, int *); -extern void DoStep(int, int, int, int, int, int, int *, int *); -extern const int MYCONST; diff --git a/misc/cgo/life/testdata/main.go b/misc/cgo/life/testdata/main.go deleted file mode 100644 index e9d19be487..0000000000 --- a/misc/cgo/life/testdata/main.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2010 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 test_run - -// Run the game of life in C using Go for parallelization. - -package main - -import ( - "flag" - "fmt" - - "cgolife" -) - -const MAXDIM = 100 - -var dim = flag.Int("dim", 16, "board dimensions") -var gen = flag.Int("gen", 10, "generations") - -func main() { - flag.Parse() - - var a [MAXDIM * MAXDIM]int32 - for i := 2; i < *dim; i += 8 { - for j := 2; j < *dim-3; j += 8 { - for y := 0; y < 3; y++ { - a[i**dim+j+y] = 1 - } - } - } - - cgolife.Run(*gen, *dim, *dim, a[:]) - - for i := 0; i < *dim; i++ { - for j := 0; j < *dim; j++ { - if a[i**dim+j] == 0 { - fmt.Print(" ") - } else { - fmt.Print("X") - } - } - fmt.Print("\n") - } -} diff --git a/misc/cgo/life/testdata/main.out b/misc/cgo/life/testdata/main.out deleted file mode 100644 index 26fc9c6e3f..0000000000 --- a/misc/cgo/life/testdata/main.out +++ /dev/null @@ -1,16 +0,0 @@ - - - XXX XXX - - - - - - - - XXX XXX - - - - - diff --git a/misc/cgo/stdio/overlaydir_test.go b/misc/cgo/stdio/overlaydir_test.go deleted file mode 100644 index 027ebf17c3..0000000000 --- a/misc/cgo/stdio/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 stdio_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/stdio/stdio_test.go b/misc/cgo/stdio/stdio_test.go deleted file mode 100644 index cd03443ec2..0000000000 --- a/misc/cgo/stdio/stdio_test.go +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019 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 stdio_test - -import ( - "bytes" - "log" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" -) - -func TestMain(m *testing.M) { - log.SetFlags(log.Lshortfile) - os.Exit(testMain(m)) -} - -func testMain(m *testing.M) int { - GOPATH, err := os.MkdirTemp("", "cgostdio") - if err != nil { - log.Panic(err) - } - defer os.RemoveAll(GOPATH) - os.Setenv("GOPATH", GOPATH) - - // Copy testdata into GOPATH/src/cgostdio, along with a go.mod file - // declaring the same path. - modRoot := filepath.Join(GOPATH, "src", "cgostdio") - if err := overlayDir(modRoot, "testdata"); err != nil { - log.Panic(err) - } - if err := os.Chdir(modRoot); err != nil { - log.Panic(err) - } - os.Setenv("PWD", modRoot) - if err := os.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil { - log.Panic(err) - } - - return m.Run() -} - -// TestTestRun runs a cgo test that doesn't depend on non-standard libraries. -func TestTestRun(t *testing.T) { - if os.Getenv("GOOS") == "android" { - t.Skip("subpackage stdio is not available on android") - } - - for _, file := range [...]string{ - "chain.go", - "fib.go", - "hello.go", - } { - file := file - wantFile := strings.Replace(file, ".go", ".out", 1) - t.Run(file, func(t *testing.T) { - cmd := exec.Command("go", "run", file) - got, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("%v: %s\n%s", cmd, err, got) - } - got = bytes.ReplaceAll(got, []byte("\r\n"), []byte("\n")) - want, err := os.ReadFile(wantFile) - if err != nil { - t.Fatal("reading golden output:", err) - } - if !bytes.Equal(got, want) { - t.Errorf("'%v' output does not match expected in %s. Instead saw:\n%s", cmd, wantFile, got) - } - }) - } -} diff --git a/misc/cgo/stdio/testdata/chain.go b/misc/cgo/stdio/testdata/chain.go deleted file mode 100644 index c7163f5ae0..0000000000 --- a/misc/cgo/stdio/testdata/chain.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2009 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 test_run - -// Pass numbers along a chain of threads. - -package main - -import ( - "runtime" - "strconv" - - "cgostdio/stdio" -) - -const N = 10 -const R = 5 - -func link(left chan<- int, right <-chan int) { - // Keep the links in dedicated operating system - // threads, so that this program tests coordination - // between pthreads and not just goroutines. - runtime.LockOSThread() - for { - v := <-right - stdio.Stdout.WriteString(strconv.Itoa(v) + "\n") - left <- 1 + v - } -} - -func main() { - leftmost := make(chan int) - var left chan int - right := leftmost - for i := 0; i < N; i++ { - left, right = right, make(chan int) - go link(left, right) - } - for i := 0; i < R; i++ { - right <- 0 - x := <-leftmost - stdio.Stdout.WriteString(strconv.Itoa(x) + "\n") - } -} diff --git a/misc/cgo/stdio/testdata/chain.out b/misc/cgo/stdio/testdata/chain.out deleted file mode 100644 index 963cf9b667..0000000000 --- a/misc/cgo/stdio/testdata/chain.out +++ /dev/null @@ -1,55 +0,0 @@ -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 diff --git a/misc/cgo/stdio/testdata/fib.go b/misc/cgo/stdio/testdata/fib.go deleted file mode 100644 index 9617368335..0000000000 --- a/misc/cgo/stdio/testdata/fib.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2009 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 test_run - -// Compute Fibonacci numbers with two goroutines -// that pass integers back and forth. No actual -// concurrency, just threads and synchronization -// and foreign code on multiple pthreads. - -package main - -import ( - "runtime" - "strconv" - - "cgostdio/stdio" -) - -func fibber(c, out chan int64, i int64) { - // Keep the fibbers in dedicated operating system - // threads, so that this program tests coordination - // between pthreads and not just goroutines. - runtime.LockOSThread() - - if i == 0 { - c <- i - } - for { - j := <-c - stdio.Stdout.WriteString(strconv.FormatInt(j, 10) + "\n") - out <- j - <-out - i += j - c <- i - } -} - -func main() { - c := make(chan int64) - out := make(chan int64) - go fibber(c, out, 0) - go fibber(c, out, 1) - <-out - for i := 0; i < 90; i++ { - out <- 1 - <-out - } -} diff --git a/misc/cgo/stdio/testdata/fib.out b/misc/cgo/stdio/testdata/fib.out deleted file mode 100644 index 17ff503356..0000000000 --- a/misc/cgo/stdio/testdata/fib.out +++ /dev/null @@ -1,91 +0,0 @@ -0 -1 -1 -2 -3 -5 -8 -13 -21 -34 -55 -89 -144 -233 -377 -610 -987 -1597 -2584 -4181 -6765 -10946 -17711 -28657 -46368 -75025 -121393 -196418 -317811 -514229 -832040 -1346269 -2178309 -3524578 -5702887 -9227465 -14930352 -24157817 -39088169 -63245986 -102334155 -165580141 -267914296 -433494437 -701408733 -1134903170 -1836311903 -2971215073 -4807526976 -7778742049 -12586269025 -20365011074 -32951280099 -53316291173 -86267571272 -139583862445 -225851433717 -365435296162 -591286729879 -956722026041 -1548008755920 -2504730781961 -4052739537881 -6557470319842 -10610209857723 -17167680177565 -27777890035288 -44945570212853 -72723460248141 -117669030460994 -190392490709135 -308061521170129 -498454011879264 -806515533049393 -1304969544928657 -2111485077978050 -3416454622906707 -5527939700884757 -8944394323791464 -14472334024676221 -23416728348467685 -37889062373143906 -61305790721611591 -99194853094755497 -160500643816367088 -259695496911122585 -420196140727489673 -679891637638612258 -1100087778366101931 -1779979416004714189 -2880067194370816120 diff --git a/misc/cgo/stdio/testdata/hello.go b/misc/cgo/stdio/testdata/hello.go deleted file mode 100644 index c0b52bf6c5..0000000000 --- a/misc/cgo/stdio/testdata/hello.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2009 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 test_run - -package main - -import "cgostdio/stdio" - -func main() { - stdio.Stdout.WriteString(stdio.Greeting + "\n") -} diff --git a/misc/cgo/stdio/testdata/hello.out b/misc/cgo/stdio/testdata/hello.out deleted file mode 100644 index 4b5fa63702..0000000000 --- a/misc/cgo/stdio/testdata/hello.out +++ /dev/null @@ -1 +0,0 @@ -hello, world diff --git a/misc/cgo/stdio/testdata/stdio/file.go b/misc/cgo/stdio/testdata/stdio/file.go deleted file mode 100644 index 2aa282eed3..0000000000 --- a/misc/cgo/stdio/testdata/stdio/file.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2009 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. - -/* -A trivial example of wrapping a C library in Go. -For a more complex example and explanation, -see ../gmp/gmp.go. -*/ - -package stdio - -/* -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <errno.h> - -char* greeting = "hello, world"; -*/ -import "C" -import "unsafe" - -type File C.FILE - -// Test reference to library symbol. -// Stdout and stderr are too special to be a reliable test. -//var = C.environ - -func (f *File) WriteString(s string) { - p := C.CString(s) - C.fputs(p, (*C.FILE)(f)) - C.free(unsafe.Pointer(p)) - f.Flush() -} - -func (f *File) Flush() { - C.fflush((*C.FILE)(f)) -} - -var Greeting = C.GoString(C.greeting) -var Gbytes = C.GoBytes(unsafe.Pointer(C.greeting), C.int(len(Greeting))) diff --git a/misc/cgo/stdio/testdata/stdio/stdio.go b/misc/cgo/stdio/testdata/stdio/stdio.go deleted file mode 100644 index 08286d4898..0000000000 --- a/misc/cgo/stdio/testdata/stdio/stdio.go +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2009 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 stdio - -/* -#include <stdio.h> - -// on mingw, stderr and stdout are defined as &_iob[FILENO] -// on netbsd, they are defined as &__sF[FILENO] -// and cgo doesn't recognize them, so write a function to get them, -// instead of depending on internals of libc implementation. -FILE *getStdout(void) { return stdout; } -FILE *getStderr(void) { return stderr; } -*/ -import "C" - -var Stdout = (*File)(C.getStdout()) -var Stderr = (*File)(C.getStderr()) diff --git a/misc/cgo/testcarchive/carchive_test.go b/misc/cgo/testcarchive/carchive_test.go deleted file mode 100644 index 8a39c24a6d..0000000000 --- a/misc/cgo/testcarchive/carchive_test.go +++ /dev/null @@ -1,1249 +0,0 @@ -// 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 carchive_test - -import ( - "bufio" - "bytes" - "debug/elf" - "flag" - "fmt" - "io" - "log" - "os" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "strconv" - "strings" - "sync" - "syscall" - "testing" - "time" - "unicode" -) - -// Program to run. -var bin []string - -// C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)). -var cc []string - -// ".exe" on Windows. -var exeSuffix string - -var GOOS, GOARCH, GOPATH string -var libgodir string - -var testWork bool // If true, preserve temporary directories. - -func TestMain(m *testing.M) { - flag.BoolVar(&testWork, "testwork", false, "if true, log and preserve the test's temporary working directory") - flag.Parse() - if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { - fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n") - os.Exit(0) - } - if runtime.GOOS == "linux" { - if _, err := os.Stat("/etc/alpine-release"); err == nil { - fmt.Printf("SKIP - skipping failing test on alpine - go.dev/issue/19938\n") - os.Exit(0) - } - } - - log.SetFlags(log.Lshortfile) - os.Exit(testMain(m)) -} - -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 = os.MkdirTemp("", "carchive_test") - if err != nil { - log.Panic(err) - } - if testWork { - log.Println(GOPATH) - } else { - defer os.RemoveAll(GOPATH) - } - os.Setenv("GOPATH", GOPATH) - - // Copy testdata into GOPATH/src/testarchive, along with a go.mod file - // declaring the same path. - modRoot := filepath.Join(GOPATH, "src", "testcarchive") - if err := overlayDir(modRoot, "testdata"); err != nil { - log.Panic(err) - } - if err := os.Chdir(modRoot); err != nil { - log.Panic(err) - } - os.Setenv("PWD", modRoot) - if err := os.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil { - log.Panic(err) - } - - GOOS = goEnv("GOOS") - GOARCH = goEnv("GOARCH") - bin = cmdToRun("./testp") - - ccOut := goEnv("CC") - cc = []string{string(ccOut)} - - out := goEnv("GOGCCFLAGS") - quote := '\000' - start := 0 - lastSpace := true - backslash := false - s := string(out) - for i, c := range s { - if quote == '\000' && unicode.IsSpace(c) { - if !lastSpace { - cc = append(cc, s[start:i]) - lastSpace = true - } - } else { - if lastSpace { - start = i - lastSpace = false - } - if quote == '\000' && !backslash && (c == '"' || c == '\'') { - quote = c - backslash = false - } else if !backslash && quote == c { - quote = '\000' - } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' { - backslash = true - } else { - backslash = false - } - } - } - if !lastSpace { - cc = append(cc, s[start:]) - } - - if GOOS == "aix" { - // -Wl,-bnoobjreorder is mandatory to keep the same layout - // in .text section. - cc = append(cc, "-Wl,-bnoobjreorder") - } - if GOOS == "ios" { - // Linking runtime/cgo on ios requires the CoreFoundation framework because - // x_cgo_init uses CoreFoundation APIs to switch directory to the app root. - // - // TODO(#58225): This special case probably should not be needed. - // runtime/cgo is a very low-level package, and should not provide - // high-level behaviors like changing the current working directory at init. - cc = append(cc, "-framework", "CoreFoundation") - } - libbase := GOOS + "_" + GOARCH - if runtime.Compiler == "gccgo" { - libbase = "gccgo_" + libgodir + "_fPIC" - } else { - switch GOOS { - case "darwin", "ios": - if GOARCH == "arm64" { - libbase += "_shared" - } - case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris", "illumos": - libbase += "_shared" - } - } - libgodir = filepath.Join(GOPATH, "pkg", libbase, "testcarchive") - cc = append(cc, "-I", libgodir) - - // Force reallocation (and avoid aliasing bugs) for parallel tests that append to cc. - cc = cc[:len(cc):len(cc)] - - if GOOS == "windows" { - exeSuffix = ".exe" - } - - return m.Run() -} - -func goEnv(key string) string { - out, err := exec.Command("go", "env", key).Output() - if err != nil { - if ee, ok := err.(*exec.ExitError); ok { - fmt.Fprintf(os.Stderr, "%s", ee.Stderr) - } - log.Panicf("go env %s failed:\n%s\n", key, err) - } - return strings.TrimSpace(string(out)) -} - -func cmdToRun(name string) []string { - execScript := "go_" + goEnv("GOOS") + "_" + goEnv("GOARCH") + "_exec" - executor, err := exec.LookPath(execScript) - if err != nil { - return []string{name} - } - return []string{executor, name} -} - -// genHeader writes a C header file for the C-exported declarations found in .go -// source files in dir. -// -// TODO(golang.org/issue/35715): This should be simpler. -func genHeader(t *testing.T, header, dir string) { - t.Helper() - - // 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 := os.MkdirTemp(GOPATH, "_obj") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(objDir) - - files, err := filepath.Glob(filepath.Join(dir, "*.go")) - if err != nil { - t.Fatal(err) - } - - cmd := exec.Command("go", "tool", "cgo", - "-objdir", objDir, - "-exportheader", header) - cmd.Args = append(cmd.Args, files...) - t.Log(cmd.Args) - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } -} - -func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) { - t.Helper() - cmd := exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Env = append(cmd.Environ(), "GO111MODULE=off") // 'go install' only works in GOPATH mode - t.Log(buildcmd) - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - if !testWork { - defer func() { - os.Remove(libgoa) - os.Remove(libgoh) - }() - } - - ccArgs := append(cc, "-o", exe, "main.c") - if GOOS == "windows" { - ccArgs = append(ccArgs, "main_windows.c", libgoa, "-lntdll", "-lws2_32", "-lwinmm") - } else { - ccArgs = append(ccArgs, "main_unix.c", libgoa) - } - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - t.Log(ccArgs) - if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - if !testWork { - defer os.Remove(exe) - } - - binArgs := append(cmdToRun(exe), "arg1", "arg2") - cmd = exec.Command(binArgs[0], binArgs[1:]...) - if runtime.Compiler == "gccgo" { - cmd.Env = append(cmd.Environ(), "GCCGO=1") - } - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - checkLineComments(t, libgoh) -} - -var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`) - -// checkLineComments checks that the export header generated by -// -buildmode=c-archive doesn't have any absolute paths in the #line -// comments. We don't want those paths because they are unhelpful for -// the user and make the files change based on details of the location -// of GOPATH. -func checkLineComments(t *testing.T, hdrname string) { - hdr, err := os.ReadFile(hdrname) - if err != nil { - if !os.IsNotExist(err) { - t.Error(err) - } - return - } - if line := badLineRegexp.Find(hdr); line != nil { - t.Errorf("bad #line directive with absolute path in %s: %q", hdrname, line) - } -} - -// checkArchive verifies that the created library looks OK. -// We just check a couple of things now, we can add more checks as needed. -func checkArchive(t *testing.T, arname string) { - t.Helper() - - switch GOOS { - case "aix", "darwin", "ios", "windows": - // We don't have any checks for non-ELF libraries yet. - if _, err := os.Stat(arname); err != nil { - t.Errorf("archive %s does not exist: %v", arname, err) - } - default: - checkELFArchive(t, arname) - } -} - -// checkELFArchive checks an ELF archive. -func checkELFArchive(t *testing.T, arname string) { - t.Helper() - - f, err := os.Open(arname) - if err != nil { - t.Errorf("archive %s does not exist: %v", arname, err) - return - } - defer f.Close() - - // TODO(iant): put these in a shared package? But where? - const ( - magic = "!<arch>\n" - fmag = "`\n" - - namelen = 16 - datelen = 12 - uidlen = 6 - gidlen = 6 - modelen = 8 - sizelen = 10 - fmaglen = 2 - hdrlen = namelen + datelen + uidlen + gidlen + modelen + sizelen + fmaglen - ) - - type arhdr struct { - name string - date string - uid string - gid string - mode string - size string - fmag string - } - - var magbuf [len(magic)]byte - if _, err := io.ReadFull(f, magbuf[:]); err != nil { - t.Errorf("%s: archive too short", arname) - return - } - if string(magbuf[:]) != magic { - t.Errorf("%s: incorrect archive magic string %q", arname, magbuf) - } - - off := int64(len(magic)) - for { - if off&1 != 0 { - var b [1]byte - if _, err := f.Read(b[:]); err != nil { - if err == io.EOF { - break - } - t.Errorf("%s: error skipping alignment byte at %d: %v", arname, off, err) - } - off++ - } - - var hdrbuf [hdrlen]byte - if _, err := io.ReadFull(f, hdrbuf[:]); err != nil { - if err == io.EOF { - break - } - t.Errorf("%s: error reading archive header at %d: %v", arname, off, err) - return - } - - var hdr arhdr - hdrslice := hdrbuf[:] - set := func(len int, ps *string) { - *ps = string(bytes.TrimSpace(hdrslice[:len])) - hdrslice = hdrslice[len:] - } - set(namelen, &hdr.name) - set(datelen, &hdr.date) - set(uidlen, &hdr.uid) - set(gidlen, &hdr.gid) - set(modelen, &hdr.mode) - set(sizelen, &hdr.size) - hdr.fmag = string(hdrslice[:fmaglen]) - hdrslice = hdrslice[fmaglen:] - if len(hdrslice) != 0 { - t.Fatalf("internal error: len(hdrslice) == %d", len(hdrslice)) - } - - if hdr.fmag != fmag { - t.Errorf("%s: invalid fmagic value %q at %d", arname, hdr.fmag, off) - return - } - - size, err := strconv.ParseInt(hdr.size, 10, 64) - if err != nil { - t.Errorf("%s: error parsing size %q at %d: %v", arname, hdr.size, off, err) - return - } - - off += hdrlen - - switch hdr.name { - case "__.SYMDEF", "/", "/SYM64/": - // The archive symbol map. - case "//", "ARFILENAMES/": - // The extended name table. - default: - // This should be an ELF object. - checkELFArchiveObject(t, arname, off, io.NewSectionReader(f, off, size)) - } - - off += size - if _, err := f.Seek(off, io.SeekStart); err != nil { - t.Errorf("%s: failed to seek to %d: %v", arname, off, err) - } - } -} - -// checkELFArchiveObject checks an object in an ELF archive. -func checkELFArchiveObject(t *testing.T, arname string, off int64, obj io.ReaderAt) { - t.Helper() - - ef, err := elf.NewFile(obj) - if err != nil { - t.Errorf("%s: failed to open ELF file at %d: %v", arname, off, err) - return - } - defer ef.Close() - - // Verify section types. - for _, sec := range ef.Sections { - want := elf.SHT_NULL - switch sec.Name { - case ".text", ".data": - want = elf.SHT_PROGBITS - case ".bss": - want = elf.SHT_NOBITS - case ".symtab": - want = elf.SHT_SYMTAB - case ".strtab": - want = elf.SHT_STRTAB - case ".init_array": - want = elf.SHT_INIT_ARRAY - case ".fini_array": - want = elf.SHT_FINI_ARRAY - case ".preinit_array": - want = elf.SHT_PREINIT_ARRAY - } - if want != elf.SHT_NULL && sec.Type != want { - t.Errorf("%s: incorrect section type in elf file at %d for section %q: got %v want %v", arname, off, sec.Name, sec.Type, want) - } - } -} - -func TestInstall(t *testing.T) { - if !testWork { - defer os.RemoveAll(filepath.Join(GOPATH, "pkg")) - } - - libgoa := "libgo.a" - if runtime.Compiler == "gccgo" { - libgoa = "liblibgo.a" - } - - // Generate the p.h header file. - // - // 'go install -i -buildmode=c-archive ./libgo' would do that too, but that - // would also attempt to install transitive standard-library dependencies to - // GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may - // be running this test in a GOROOT owned by root.) - genHeader(t, "p.h", "./p") - - testInstall(t, "./testp1"+exeSuffix, - filepath.Join(libgodir, libgoa), - filepath.Join(libgodir, "libgo.h"), - "go", "install", "-buildmode=c-archive", "./libgo") - - // Test building libgo other than installing it. - // Header files are now present. - testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h", - "go", "build", "-buildmode=c-archive", filepath.Join(".", "libgo", "libgo.go")) - - testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h", - "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "./libgo") -} - -func TestEarlySignalHandler(t *testing.T) { - switch GOOS { - case "darwin", "ios": - switch GOARCH { - case "arm64": - t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH) - } - case "windows": - t.Skip("skipping signal test on Windows") - } - - if !testWork { - defer func() { - os.Remove("libgo2.a") - os.Remove("libgo2.h") - os.Remove("testp" + exeSuffix) - os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2") - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - checkLineComments(t, "libgo2.h") - checkArchive(t, "libgo2.a") - - ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - darwin := "0" - if runtime.GOOS == "darwin" { - darwin = "1" - } - cmd = exec.Command(bin[0], append(bin[1:], darwin)...) - - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } -} - -func TestSignalForwarding(t *testing.T) { - checkSignalForwardingTest(t) - buildSignalForwardingTest(t) - - cmd := exec.Command(bin[0], append(bin[1:], "1")...) - - out, err := cmd.CombinedOutput() - t.Logf("%v\n%s", cmd.Args, out) - expectSignal(t, err, syscall.SIGSEGV, 0) - - // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384. - if runtime.GOOS != "darwin" && runtime.GOOS != "ios" { - // Test SIGPIPE forwarding - cmd = exec.Command(bin[0], append(bin[1:], "3")...) - - out, err = cmd.CombinedOutput() - if len(out) > 0 { - t.Logf("%s", out) - } - expectSignal(t, err, syscall.SIGPIPE, 0) - } -} - -func TestSignalForwardingExternal(t *testing.T) { - if GOOS == "freebsd" || GOOS == "aix" { - t.Skipf("skipping on %s/%s; signal always goes to the Go runtime", GOOS, GOARCH) - } else if GOOS == "darwin" && GOARCH == "amd64" { - t.Skipf("skipping on %s/%s: runtime does not permit SI_USER SIGSEGV", GOOS, GOARCH) - } - checkSignalForwardingTest(t) - buildSignalForwardingTest(t) - - // We want to send the process a signal and see if it dies. - // Normally the signal goes to the C thread, the Go signal - // handler picks it up, sees that it is running in a C thread, - // and the program dies. Unfortunately, occasionally the - // signal is delivered to a Go thread, which winds up - // discarding it because it was sent by another program and - // there is no Go handler for it. To avoid this, run the - // program several times in the hopes that it will eventually - // fail. - const tries = 20 - for i := 0; i < tries; i++ { - err := runSignalForwardingTest(t, "2") - if err == nil { - continue - } - - // If the signal is delivered to a C thread, as expected, - // the Go signal handler will disable itself and re-raise - // the signal, causing the program to die with SIGSEGV. - // - // It is also possible that the signal will be - // delivered to a Go thread, such as a GC thread. - // Currently when the Go runtime sees that a SIGSEGV was - // sent from a different program, it first tries to send - // the signal to the os/signal API. If nothing is looking - // for (or explicitly ignoring) SIGSEGV, then it crashes. - // Because the Go runtime is invoked via a c-archive, - // it treats this as GOTRACEBACK=crash, meaning that it - // dumps a stack trace for all goroutines, which it does - // by raising SIGQUIT. The effect is that we will see the - // program die with SIGQUIT in that case, not SIGSEGV. - if expectSignal(t, err, syscall.SIGSEGV, syscall.SIGQUIT) { - return - } - } - - t.Errorf("program succeeded unexpectedly %d times", tries) -} - -func TestSignalForwardingGo(t *testing.T) { - // This test fails on darwin-amd64 because of the special - // handling of user-generated SIGSEGV signals in fixsigcode in - // runtime/signal_darwin_amd64.go. - if runtime.GOOS == "darwin" && runtime.GOARCH == "amd64" { - t.Skip("not supported on darwin-amd64") - } - - checkSignalForwardingTest(t) - buildSignalForwardingTest(t) - err := runSignalForwardingTest(t, "4") - - // Occasionally the signal will be delivered to a C thread, - // and the program will crash with SIGSEGV. - expectSignal(t, err, syscall.SIGQUIT, syscall.SIGSEGV) -} - -// checkSignalForwardingTest calls t.Skip if the SignalForwarding test -// doesn't work on this platform. -func checkSignalForwardingTest(t *testing.T) { - switch GOOS { - case "darwin", "ios": - switch GOARCH { - case "arm64": - t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH) - } - case "windows": - t.Skip("skipping signal test on Windows") - } -} - -// buildSignalForwardingTest builds the executable used by the various -// signal forwarding tests. -func buildSignalForwardingTest(t *testing.T) { - if !testWork { - t.Cleanup(func() { - os.Remove("libgo2.a") - os.Remove("libgo2.h") - os.Remove("testp" + exeSuffix) - os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }) - } - - t.Log("go build -buildmode=c-archive -o libgo2.a ./libgo2") - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2") - out, err := cmd.CombinedOutput() - if len(out) > 0 { - t.Logf("%s", out) - } - if err != nil { - t.Fatal(err) - } - - checkLineComments(t, "libgo2.h") - checkArchive(t, "libgo2.a") - - ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - t.Log(ccArgs) - out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() - if len(out) > 0 { - t.Logf("%s", out) - } - if err != nil { - t.Fatal(err) - } -} - -func runSignalForwardingTest(t *testing.T, arg string) error { - t.Logf("%v %s", bin, arg) - cmd := exec.Command(bin[0], append(bin[1:], arg)...) - - var out strings.Builder - cmd.Stdout = &out - - stderr, err := cmd.StderrPipe() - if err != nil { - t.Fatal(err) - } - defer stderr.Close() - - r := bufio.NewReader(stderr) - - err = cmd.Start() - if err != nil { - t.Fatal(err) - } - - // Wait for trigger to ensure that process is started. - ok, err := r.ReadString('\n') - - // Verify trigger. - if err != nil || ok != "OK\n" { - t.Fatal("Did not receive OK signal") - } - - var wg sync.WaitGroup - wg.Add(1) - var errsb strings.Builder - go func() { - defer wg.Done() - io.Copy(&errsb, r) - }() - - // Give the program a chance to enter the function. - // If the program doesn't get there the test will still - // pass, although it doesn't quite test what we intended. - // This is fine as long as the program normally makes it. - time.Sleep(time.Millisecond) - - cmd.Process.Signal(syscall.SIGSEGV) - - err = cmd.Wait() - - s := out.String() - if len(s) > 0 { - t.Log(s) - } - wg.Wait() - s = errsb.String() - if len(s) > 0 { - t.Log(s) - } - - return err -} - -// expectSignal checks that err, the exit status of a test program, -// shows a failure due to a specific signal or two. Returns whether we -// found an expected signal. -func expectSignal(t *testing.T, err error, sig1, sig2 syscall.Signal) bool { - t.Helper() - if err == nil { - t.Error("test program succeeded unexpectedly") - } else if ee, ok := err.(*exec.ExitError); !ok { - t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err) - } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok { - t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys()) - } else if !ws.Signaled() || (ws.Signal() != sig1 && ws.Signal() != sig2) { - if sig2 == 0 { - t.Errorf("got %q; expected signal %q", ee, sig1) - } else { - t.Errorf("got %q; expected signal %q or %q", ee, sig1, sig2) - } - } else { - return true - } - return false -} - -func TestOsSignal(t *testing.T) { - switch GOOS { - case "windows": - t.Skip("skipping signal test on Windows") - } - - if !testWork { - defer func() { - os.Remove("libgo3.a") - os.Remove("libgo3.h") - os.Remove("testp" + exeSuffix) - os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "./libgo3") - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - checkLineComments(t, "libgo3.h") - checkArchive(t, "libgo3.a") - - ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } -} - -func TestSigaltstack(t *testing.T) { - switch GOOS { - case "windows": - t.Skip("skipping signal test on Windows") - } - - if !testWork { - defer func() { - os.Remove("libgo4.a") - os.Remove("libgo4.h") - os.Remove("testp" + exeSuffix) - os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "./libgo4") - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - checkLineComments(t, "libgo4.h") - checkArchive(t, "libgo4.a") - - ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } -} - -const testar = `#!/usr/bin/env bash -while [[ $1 == -* ]] >/dev/null; do - shift -done -echo "testar" > $1 -echo "testar" > PWD/testar.ran -` - -func TestExtar(t *testing.T) { - switch GOOS { - case "windows": - t.Skip("skipping signal test on Windows") - } - if runtime.Compiler == "gccgo" { - t.Skip("skipping -extar test when using gccgo") - } - if runtime.GOOS == "ios" { - t.Skip("shell scripts are not executable on iOS hosts") - } - - if !testWork { - defer func() { - os.Remove("libgo4.a") - os.Remove("libgo4.h") - os.Remove("testar") - os.Remove("testar.ran") - os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }() - } - - os.Remove("testar") - dir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - s := strings.Replace(testar, "PWD", dir, 1) - if err := os.WriteFile("testar", []byte(s), 0777); err != nil { - t.Fatal(err) - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "./libgo4") - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - checkLineComments(t, "libgo4.h") - - if _, err := os.Stat("testar.ran"); err != nil { - if os.IsNotExist(err) { - t.Error("testar does not exist after go build") - } else { - t.Errorf("error checking testar: %v", err) - } - } -} - -func TestPIE(t *testing.T) { - switch GOOS { - case "windows", "darwin", "ios", "plan9": - t.Skipf("skipping PIE test on %s", GOOS) - } - - libgoa := "libgo.a" - if runtime.Compiler == "gccgo" { - libgoa = "liblibgo.a" - } - - if !testWork { - defer func() { - os.Remove("testp" + exeSuffix) - os.Remove(libgoa) - os.RemoveAll(filepath.Join(GOPATH, "pkg")) - }() - } - - // Generate the p.h header file. - // - // 'go install -i -buildmode=c-archive ./libgo' would do that too, but that - // would also attempt to install transitive standard-library dependencies to - // GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may - // be running this test in a GOROOT owned by root.) - genHeader(t, "p.h", "./p") - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "./libgo") - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", libgoa) - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - binArgs := append(bin, "arg1", "arg2") - cmd = exec.Command(binArgs[0], binArgs[1:]...) - if runtime.Compiler == "gccgo" { - cmd.Env = append(os.Environ(), "GCCGO=1") - } - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - if GOOS != "aix" { - f, err := elf.Open("testp" + exeSuffix) - if err != nil { - t.Fatal("elf.Open failed: ", err) - } - defer f.Close() - if hasDynTag(t, f, elf.DT_TEXTREL) { - t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix) - } - } -} - -func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool { - ds := f.SectionByType(elf.SHT_DYNAMIC) - if ds == nil { - t.Error("no SHT_DYNAMIC section") - return false - } - d, err := ds.Data() - if err != nil { - t.Errorf("can't read SHT_DYNAMIC contents: %v", err) - return false - } - for len(d) > 0 { - var t elf.DynTag - switch f.Class { - case elf.ELFCLASS32: - t = elf.DynTag(f.ByteOrder.Uint32(d[:4])) - d = d[8:] - case elf.ELFCLASS64: - t = elf.DynTag(f.ByteOrder.Uint64(d[:8])) - d = d[16:] - } - if t == tag { - return true - } - } - return false -} - -func TestSIGPROF(t *testing.T) { - switch GOOS { - case "windows", "plan9": - t.Skipf("skipping SIGPROF test on %s", GOOS) - case "darwin", "ios": - t.Skipf("skipping SIGPROF test on %s; see https://golang.org/issue/19320", GOOS) - } - - t.Parallel() - - if !testWork { - defer func() { - os.Remove("testp6" + exeSuffix) - os.Remove("libgo6.a") - os.Remove("libgo6.h") - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "./libgo6") - out, err := cmd.CombinedOutput() - t.Logf("%v\n%s", cmd.Args, out) - if err != nil { - t.Fatal(err) - } - checkLineComments(t, "libgo6.h") - checkArchive(t, "libgo6.a") - - ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", ccArgs, out) - if err != nil { - t.Fatal(err) - } - - argv := cmdToRun("./testp6") - cmd = exec.Command(argv[0], argv[1:]...) - out, err = cmd.CombinedOutput() - t.Logf("%v\n%s", argv, out) - if err != nil { - t.Fatal(err) - } -} - -// TestCompileWithoutShared tests that if we compile code without the -// -shared option, we can put it into an archive. When we use the go -// 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 Linux. -func TestCompileWithoutShared(t *testing.T) { - // For simplicity, reuse the signal forwarding test. - checkSignalForwardingTest(t) - - if !testWork { - defer func() { - os.Remove("libgo2.a") - os.Remove("libgo2.h") - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "./libgo2") - out, err := cmd.CombinedOutput() - t.Logf("%v\n%s", cmd.Args, out) - if err != nil { - t.Fatal(err) - } - checkLineComments(t, "libgo2.h") - checkArchive(t, "libgo2.a") - - exe := "./testnoshared" + exeSuffix - - // In some cases, -no-pie is needed here, but not accepted everywhere. First try - // if -no-pie is accepted. See #22126. - ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", ccArgs, out) - - // If -no-pie unrecognized, try -nopie if this is possibly clang - if err != nil && bytes.Contains(out, []byte("unknown")) && !strings.Contains(cc[0], "gcc") { - ccArgs = append(cc, "-o", exe, "-nopie", "main5.c", "libgo2.a") - out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", ccArgs, out) - } - - // Don't use either -no-pie or -nopie - if err != nil && bytes.Contains(out, []byte("unrecognized")) { - ccArgs = append(cc, "-o", exe, "main5.c", "libgo2.a") - out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", ccArgs, out) - } - if err != nil { - t.Fatal(err) - } - if !testWork { - defer os.Remove(exe) - } - - binArgs := append(cmdToRun(exe), "1") - out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", binArgs, out) - expectSignal(t, err, syscall.SIGSEGV, 0) - - // SIGPIPE is never forwarded on darwin. See golang.org/issue/33384. - if runtime.GOOS != "darwin" && runtime.GOOS != "ios" { - binArgs := append(cmdToRun(exe), "3") - out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", binArgs, out) - expectSignal(t, err, syscall.SIGPIPE, 0) - } -} - -// Test that installing a second time recreates the header file. -func TestCachedInstall(t *testing.T) { - if !testWork { - defer os.RemoveAll(filepath.Join(GOPATH, "pkg")) - } - - h := filepath.Join(libgodir, "libgo.h") - - buildcmd := []string{"go", "install", "-buildmode=c-archive", "./libgo"} - - cmd := exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Env = append(cmd.Environ(), "GO111MODULE=off") // 'go install' only works in GOPATH mode - t.Log(buildcmd) - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - if _, err := os.Stat(h); err != nil { - t.Errorf("libgo.h not installed: %v", err) - } - - if err := os.Remove(h); err != nil { - t.Fatal(err) - } - - cmd = exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Env = append(cmd.Environ(), "GO111MODULE=off") - t.Log(buildcmd) - if out, err := cmd.CombinedOutput(); err != nil { - t.Logf("%s", out) - t.Fatal(err) - } - - if _, err := os.Stat(h); err != nil { - t.Errorf("libgo.h not installed in second run: %v", err) - } -} - -// Issue 35294. -func TestManyCalls(t *testing.T) { - t.Parallel() - - if !testWork { - defer func() { - os.Remove("testp7" + exeSuffix) - os.Remove("libgo7.a") - os.Remove("libgo7.h") - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo7.a", "./libgo7") - out, err := cmd.CombinedOutput() - t.Logf("%v\n%s", cmd.Args, out) - if err != nil { - t.Fatal(err) - } - checkLineComments(t, "libgo7.h") - checkArchive(t, "libgo7.a") - - ccArgs := append(cc, "-o", "testp7"+exeSuffix, "main7.c", "libgo7.a") - if runtime.Compiler == "gccgo" { - ccArgs = append(ccArgs, "-lgo") - } - out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", ccArgs, out) - if err != nil { - t.Fatal(err) - } - - argv := cmdToRun("./testp7") - cmd = exec.Command(argv[0], argv[1:]...) - sb := new(strings.Builder) - cmd.Stdout = sb - cmd.Stderr = sb - if err := cmd.Start(); err != nil { - t.Fatal(err) - } - - timer := time.AfterFunc(time.Minute, - func() { - t.Error("test program timed out") - cmd.Process.Kill() - }, - ) - defer timer.Stop() - - err = cmd.Wait() - t.Logf("%v\n%s", cmd.Args, sb) - if err != nil { - t.Error(err) - } -} - -// Issue 49288. -func TestPreemption(t *testing.T) { - if runtime.Compiler == "gccgo" { - t.Skip("skipping asynchronous preemption test with gccgo") - } - - t.Parallel() - - if !testWork { - defer func() { - os.Remove("testp8" + exeSuffix) - os.Remove("libgo8.a") - os.Remove("libgo8.h") - }() - } - - cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo8.a", "./libgo8") - out, err := cmd.CombinedOutput() - t.Logf("%v\n%s", cmd.Args, out) - if err != nil { - t.Fatal(err) - } - checkLineComments(t, "libgo8.h") - checkArchive(t, "libgo8.a") - - ccArgs := append(cc, "-o", "testp8"+exeSuffix, "main8.c", "libgo8.a") - out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() - t.Logf("%v\n%s", ccArgs, out) - if err != nil { - t.Fatal(err) - } - - argv := cmdToRun("./testp8") - cmd = exec.Command(argv[0], argv[1:]...) - sb := new(strings.Builder) - cmd.Stdout = sb - cmd.Stderr = sb - if err := cmd.Start(); err != nil { - t.Fatal(err) - } - - timer := time.AfterFunc(time.Minute, - func() { - t.Error("test program timed out") - cmd.Process.Kill() - }, - ) - defer timer.Stop() - - err = cmd.Wait() - t.Logf("%v\n%s", cmd.Args, sb) - if err != nil { - t.Error(err) - } -} diff --git a/misc/cgo/testcarchive/overlaydir_test.go b/misc/cgo/testcarchive/overlaydir_test.go deleted file mode 100644 index 67974c5ed8..0000000000 --- a/misc/cgo/testcarchive/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 carchive_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/testcarchive/testdata/libgo/libgo.go b/misc/cgo/testcarchive/testdata/libgo/libgo.go deleted file mode 100644 index 37b30c1463..0000000000 --- a/misc/cgo/testcarchive/testdata/libgo/libgo.go +++ /dev/null @@ -1,53 +0,0 @@ -// 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 main - -import ( - "fmt" - "os" - "syscall" - "time" - - _ "testcarchive/p" -) - -import "C" - -var initCh = make(chan int, 1) -var ranMain bool - -func init() { - // emulate an exceedingly slow package initialization function - time.Sleep(100 * time.Millisecond) - initCh <- 42 -} - -func main() { ranMain = true } - -//export DidInitRun -func DidInitRun() bool { - select { - case x := <-initCh: - if x != 42 { - // Just in case initCh was not correctly made. - println("want init value of 42, got: ", x) - syscall.Exit(2) - } - return true - default: - return false - } -} - -//export DidMainRun -func DidMainRun() bool { return ranMain } - -//export CheckArgs -func CheckArgs() { - if len(os.Args) != 3 || os.Args[1] != "arg1" || os.Args[2] != "arg2" { - fmt.Printf("CheckArgs: want [_, arg1, arg2], got: %v\n", os.Args) - os.Exit(2) - } -} diff --git a/misc/cgo/testcarchive/testdata/libgo2/libgo2.go b/misc/cgo/testcarchive/testdata/libgo2/libgo2.go deleted file mode 100644 index b2e7731a45..0000000000 --- a/misc/cgo/testcarchive/testdata/libgo2/libgo2.go +++ /dev/null @@ -1,91 +0,0 @@ -// 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 main - -/* -#include <signal.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> - -// Raise SIGPIPE. -static void CRaiseSIGPIPE() { - int fds[2]; - - if (pipe(fds) == -1) { - perror("pipe"); - exit(EXIT_FAILURE); - } - // Close the reader end - close(fds[0]); - // Write to the writer end to provoke a SIGPIPE - if (write(fds[1], "some data", 9) != -1) { - fprintf(stderr, "write to a closed pipe succeeded\n"); - exit(EXIT_FAILURE); - } - close(fds[1]); -} -*/ -import "C" - -import ( - "fmt" - "os" - "runtime" -) - -// RunGoroutines starts some goroutines that don't do anything. -// The idea is to get some threads going, so that a signal will be delivered -// to a thread started by Go. -// -//export RunGoroutines -func RunGoroutines() { - for i := 0; i < 4; i++ { - go func() { - runtime.LockOSThread() - select {} - }() - } -} - -// Block blocks the current thread while running Go code. -// -//export Block -func Block() { - select {} -} - -var P *byte - -// TestSEGV makes sure that an invalid address turns into a run-time Go panic. -// -//export TestSEGV -func TestSEGV() { - defer func() { - if recover() == nil { - fmt.Fprintln(os.Stderr, "no panic from segv") - os.Exit(1) - } - }() - *P = 0 - fmt.Fprintln(os.Stderr, "continued after segv") - os.Exit(1) -} - -// Noop ensures that the Go runtime is initialized. -// -//export Noop -func Noop() { -} - -// Raise SIGPIPE. -// -//export GoRaiseSIGPIPE -func GoRaiseSIGPIPE() { - C.CRaiseSIGPIPE() -} - -func main() { -} diff --git a/misc/cgo/testcarchive/testdata/libgo3/libgo3.go b/misc/cgo/testcarchive/testdata/libgo3/libgo3.go deleted file mode 100644 index 136695b09b..0000000000 --- a/misc/cgo/testcarchive/testdata/libgo3/libgo3.go +++ /dev/null @@ -1,60 +0,0 @@ -// 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 main - -import "C" - -import ( - "os" - "os/signal" - "syscall" - "time" -) - -// The channel used to read SIGIO signals. -var sigioChan chan os.Signal - -// CatchSIGIO starts catching SIGIO signals. -// -//export CatchSIGIO -func CatchSIGIO() { - sigioChan = make(chan os.Signal, 1) - signal.Notify(sigioChan, syscall.SIGIO) -} - -// ResetSIGIO stops catching SIGIO signals. -// -//export ResetSIGIO -func ResetSIGIO() { - signal.Reset(syscall.SIGIO) -} - -// SawSIGIO reports whether we saw a SIGIO. -// -//export SawSIGIO -func SawSIGIO() C.int { - select { - case <-sigioChan: - return 1 - case <-time.After(5 * time.Second): - return 0 - } -} - -// ProvokeSIGPIPE provokes a kernel-initiated SIGPIPE. -// -//export ProvokeSIGPIPE -func ProvokeSIGPIPE() { - r, w, err := os.Pipe() - if err != nil { - panic(err) - } - r.Close() - defer w.Close() - w.Write([]byte("some data")) -} - -func main() { -} diff --git a/misc/cgo/testcarchive/testdata/libgo4/libgo4.go b/misc/cgo/testcarchive/testdata/libgo4/libgo4.go deleted file mode 100644 index c81d3af4ea..0000000000 --- a/misc/cgo/testcarchive/testdata/libgo4/libgo4.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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 main - -/* -#include <signal.h> -#include <pthread.h> - -// Raise SIGIO. -static void CRaiseSIGIO(pthread_t* p) { - pthread_kill(*p, SIGIO); -} -*/ -import "C" - -import ( - "os" - "os/signal" - "sync/atomic" - "syscall" -) - -var sigioCount int32 - -// Catch SIGIO. -// -//export GoCatchSIGIO -func GoCatchSIGIO() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGIO) - go func() { - for range c { - atomic.AddInt32(&sigioCount, 1) - } - }() -} - -// Raise SIGIO. -// -//export GoRaiseSIGIO -func GoRaiseSIGIO(p *C.pthread_t) { - C.CRaiseSIGIO(p) -} - -// Return the number of SIGIO signals seen. -// -//export SIGIOCount -func SIGIOCount() C.int { - return C.int(atomic.LoadInt32(&sigioCount)) -} - -func main() { -} diff --git a/misc/cgo/testcarchive/testdata/libgo6/sigprof.go b/misc/cgo/testcarchive/testdata/libgo6/sigprof.go deleted file mode 100644 index 31527c59af..0000000000 --- a/misc/cgo/testcarchive/testdata/libgo6/sigprof.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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 main - -import ( - "io" - "runtime/pprof" -) - -import "C" - -//export go_start_profile -func go_start_profile() { - pprof.StartCPUProfile(io.Discard) -} - -//export go_stop_profile -func go_stop_profile() { - pprof.StopCPUProfile() -} - -func main() { -} diff --git a/misc/cgo/testcarchive/testdata/libgo7/sink.go b/misc/cgo/testcarchive/testdata/libgo7/sink.go deleted file mode 100644 index d61638b38e..0000000000 --- a/misc/cgo/testcarchive/testdata/libgo7/sink.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2019 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 - -import "C" - -var sink []byte - -//export GoFunction7 -func GoFunction7() { - sink = make([]byte, 4096) -} - -func main() { -} diff --git a/misc/cgo/testcarchive/testdata/libgo8/a.go b/misc/cgo/testcarchive/testdata/libgo8/a.go deleted file mode 100644 index 718418ecb8..0000000000 --- a/misc/cgo/testcarchive/testdata/libgo8/a.go +++ /dev/null @@ -1,36 +0,0 @@ -// 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. - -package main - -import "C" - -import ( - "os" - "runtime" - "sync/atomic" -) - -var started int32 - -// Start a goroutine that loops forever. -func init() { - runtime.GOMAXPROCS(1) - go func() { - for { - atomic.StoreInt32(&started, 1) - } - }() -} - -//export GoFunction8 -func GoFunction8() { - for atomic.LoadInt32(&started) == 0 { - runtime.Gosched() - } - os.Exit(0) -} - -func main() { -} diff --git a/misc/cgo/testcarchive/testdata/main.c b/misc/cgo/testcarchive/testdata/main.c deleted file mode 100644 index 163b5398e5..0000000000 --- a/misc/cgo/testcarchive/testdata/main.c +++ /dev/null @@ -1,48 +0,0 @@ -// 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. - -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include "p.h" -#include "libgo.h" - -extern int install_handler(); -extern int check_handler(); - -int main(void) { - int32_t res; - - int r1 = install_handler(); - if (r1!=0) { - return r1; - } - - if (!DidInitRun()) { - fprintf(stderr, "ERROR: buildmode=c-archive init should run\n"); - return 2; - } - - if (DidMainRun()) { - fprintf(stderr, "ERROR: buildmode=c-archive should not run main\n"); - return 2; - } - - int r2 = check_handler(); - if (r2!=0) { - return r2; - } - - res = FromPkg(); - if (res != 1024) { - fprintf(stderr, "ERROR: FromPkg()=%d, want 1024\n", res); - return 2; - } - - CheckArgs(); - - fprintf(stderr, "PASS\n"); - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/main2.c b/misc/cgo/testcarchive/testdata/main2.c deleted file mode 100644 index da35673421..0000000000 --- a/misc/cgo/testcarchive/testdata/main2.c +++ /dev/null @@ -1,239 +0,0 @@ -// 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. - -// Test installing a signal handler before the Go code starts. -// This is a lot like misc/cgo/testcshared/main4.c. - -#include <setjmp.h> -#include <signal.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <sched.h> -#include <time.h> -#include <errno.h> - -#include "libgo2.h" - -static void die(const char* msg) { - perror(msg); - exit(EXIT_FAILURE); -} - -static volatile sig_atomic_t sigioSeen; -static volatile sig_atomic_t sigpipeSeen; - -// Use up some stack space. -static void recur(int i, char *p) { - char a[1024]; - - *p = '\0'; - if (i > 0) { - recur(i - 1, a); - } -} - -static void pipeHandler(int signo, siginfo_t* info, void* ctxt) { - sigpipeSeen = 1; -} - -// Signal handler that uses up more stack space than a goroutine will have. -static void ioHandler(int signo, siginfo_t* info, void* ctxt) { - char a[1024]; - - recur(4, a); - sigioSeen = 1; -} - -static jmp_buf jmp; -static char* nullPointer; - -// An arbitrary function which requires proper stack alignment; see -// http://golang.org/issue/17641. -static void callWithVarargs(void* dummy, ...) { - va_list args; - va_start(args, dummy); - va_end(args); -} - -// Signal handler for SIGSEGV on a C thread. -static void segvHandler(int signo, siginfo_t* info, void* ctxt) { - sigset_t mask; - int i; - - // Call an arbitrary function that requires the stack to be properly aligned. - callWithVarargs("dummy arg", 3.1415); - - if (sigemptyset(&mask) < 0) { - die("sigemptyset"); - } - if (sigaddset(&mask, SIGSEGV) < 0) { - die("sigaddset"); - } - i = sigprocmask(SIG_UNBLOCK, &mask, NULL); - if (i != 0) { - fprintf(stderr, "sigprocmask: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - // Don't try this at home. - longjmp(jmp, signo); - - // We should never get here. - abort(); -} - -// Set up the signal handlers in a high priority constructor, -// so that they are installed before the Go code starts. - -static void init(void) __attribute__ ((constructor (200))); - -static void init() { - struct sigaction sa; - - memset(&sa, 0, sizeof sa); - sa.sa_sigaction = ioHandler; - if (sigemptyset(&sa.sa_mask) < 0) { - die("sigemptyset"); - } - sa.sa_flags = SA_SIGINFO; - if (sigaction(SIGIO, &sa, NULL) < 0) { - die("sigaction"); - } - - sa.sa_sigaction = segvHandler; - if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) { - die("sigaction"); - } - - sa.sa_sigaction = pipeHandler; - if (sigaction(SIGPIPE, &sa, NULL) < 0) { - die("sigaction"); - } -} - -int main(int argc, char** argv) { - int verbose; - sigset_t mask; - int i; - struct timespec ts; - int darwin; - - darwin = atoi(argv[1]); - - verbose = argc > 2; - - setvbuf(stdout, NULL, _IONBF, 0); - - // Call setsid so that we can use kill(0, SIGIO) below. - // Don't check the return value so that this works both from - // a job control shell and from a shell script. - setsid(); - - if (verbose) { - printf("calling RunGoroutines\n"); - } - - RunGoroutines(); - - // Block SIGIO in this thread to make it more likely that it - // will be delivered to a goroutine. - - if (verbose) { - printf("calling pthread_sigmask\n"); - } - - if (sigemptyset(&mask) < 0) { - die("sigemptyset"); - } - if (sigaddset(&mask, SIGIO) < 0) { - die("sigaddset"); - } - i = pthread_sigmask(SIG_BLOCK, &mask, NULL); - if (i != 0) { - fprintf(stderr, "pthread_sigmask: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling kill\n"); - } - - if (kill(0, SIGIO) < 0) { - die("kill"); - } - - if (verbose) { - printf("waiting for sigioSeen\n"); - } - - // Wait until the signal has been delivered. - i = 0; - while (!sigioSeen) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for SIGIO\n"); - exit(EXIT_FAILURE); - } - } - - if (verbose) { - printf("provoking SIGPIPE\n"); - } - - // SIGPIPE is never forwarded on Darwin, see golang.org/issue/33384. - if (!darwin) { - GoRaiseSIGPIPE(); - - if (verbose) { - printf("waiting for sigpipeSeen\n"); - } - - // Wait until the signal has been delivered. - i = 0; - while (!sigpipeSeen) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for SIGPIPE\n"); - exit(EXIT_FAILURE); - } - } - } - - if (verbose) { - printf("calling setjmp\n"); - } - - // Test that a SIGSEGV on this thread is delivered to us. - if (setjmp(jmp) == 0) { - if (verbose) { - printf("triggering SIGSEGV\n"); - } - - *nullPointer = '\0'; - - fprintf(stderr, "continued after address error\n"); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling TestSEGV\n"); - } - - TestSEGV(); - - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/main3.c b/misc/cgo/testcarchive/testdata/main3.c deleted file mode 100644 index 4d11d9ce4c..0000000000 --- a/misc/cgo/testcarchive/testdata/main3.c +++ /dev/null @@ -1,210 +0,0 @@ -// 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. - -// Test os/signal.Notify and os/signal.Reset. -// This is a lot like misc/cgo/testcshared/main5.c. - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <sched.h> -#include <unistd.h> -#include <pthread.h> - -#include "libgo3.h" - -static void die(const char* msg) { - perror(msg); - exit(EXIT_FAILURE); -} - -static volatile sig_atomic_t sigioSeen; - -static void ioHandler(int signo, siginfo_t* info, void* ctxt) { - sigioSeen = 1; -} - -// Set up the SIGPIPE signal handler in a high priority constructor, so -// that it is installed before the Go code starts. - -static void pipeHandler(int signo, siginfo_t* info, void* ctxt) { - const char *s = "unexpected SIGPIPE\n"; - write(2, s, strlen(s)); - exit(EXIT_FAILURE); -} - -static void init(void) __attribute__ ((constructor (200))); - -static void init() { - struct sigaction sa; - - memset(&sa, 0, sizeof sa); - sa.sa_sigaction = pipeHandler; - if (sigemptyset(&sa.sa_mask) < 0) { - die("sigemptyset"); - } - sa.sa_flags = SA_SIGINFO; - if (sigaction(SIGPIPE, &sa, NULL) < 0) { - die("sigaction"); - } -} - -static void *provokeSIGPIPE(void *arg) { - ProvokeSIGPIPE(); - return NULL; -} - -int main(int argc, char** argv) { - int verbose; - struct sigaction sa; - int i; - struct timespec ts; - int res; - pthread_t tid; - - verbose = argc > 2; - setvbuf(stdout, NULL, _IONBF, 0); - - if (verbose) { - printf("raising SIGPIPE\n"); - } - - // Test that the Go runtime handles SIGPIPE, even if we installed - // a non-default SIGPIPE handler before the runtime initializes. - ProvokeSIGPIPE(); - - // Test that SIGPIPE on a non-main thread is also handled by Go. - res = pthread_create(&tid, NULL, provokeSIGPIPE, NULL); - if (res != 0) { - fprintf(stderr, "pthread_create: %s\n", strerror(res)); - exit(EXIT_FAILURE); - } - - res = pthread_join(tid, NULL); - if (res != 0) { - fprintf(stderr, "pthread_join: %s\n", strerror(res)); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling sigaction\n"); - } - - memset(&sa, 0, sizeof sa); - sa.sa_sigaction = ioHandler; - if (sigemptyset(&sa.sa_mask) < 0) { - die("sigemptyset"); - } - sa.sa_flags = SA_SIGINFO; - if (sigaction(SIGIO, &sa, NULL) < 0) { - die("sigaction"); - } - - // At this point there should not be a Go signal handler - // installed for SIGIO. - - if (verbose) { - printf("raising SIGIO\n"); - } - - if (raise(SIGIO) < 0) { - die("raise"); - } - - if (verbose) { - printf("waiting for sigioSeen\n"); - } - - // Wait until the signal has been delivered. - i = 0; - while (!sigioSeen) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for signal\n"); - exit(EXIT_FAILURE); - } - } - - sigioSeen = 0; - - // Tell the Go code to catch SIGIO. - - if (verbose) { - printf("calling CatchSIGIO\n"); - } - - CatchSIGIO(); - - if (verbose) { - printf("raising SIGIO\n"); - } - - if (raise(SIGIO) < 0) { - die("raise"); - } - - if (verbose) { - printf("calling SawSIGIO\n"); - } - - if (!SawSIGIO()) { - fprintf(stderr, "Go handler did not see SIGIO\n"); - exit(EXIT_FAILURE); - } - - if (sigioSeen != 0) { - fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n"); - exit(EXIT_FAILURE); - } - - // Tell the Go code to stop catching SIGIO. - - if (verbose) { - printf("calling ResetSIGIO\n"); - } - - ResetSIGIO(); - - if (verbose) { - printf("raising SIGIO\n"); - } - - if (raise(SIGIO) < 0) { - die("raise"); - } - - if (verbose) { - printf("calling SawSIGIO\n"); - } - - if (SawSIGIO()) { - fprintf(stderr, "Go handler saw SIGIO after Reset\n"); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("waiting for sigioSeen\n"); - } - - // Wait until the signal has been delivered. - i = 0; - while (!sigioSeen) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for signal\n"); - exit(EXIT_FAILURE); - } - } - - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/main4.c b/misc/cgo/testcarchive/testdata/main4.c deleted file mode 100644 index 04f774008f..0000000000 --- a/misc/cgo/testcarchive/testdata/main4.c +++ /dev/null @@ -1,204 +0,0 @@ -// 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. - -// Test a C thread that calls sigaltstack and then calls Go code. - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <sched.h> -#include <pthread.h> - -#include "libgo4.h" - -#ifdef _AIX -// On AIX, CSIGSTKSZ is too small to handle Go sighandler. -#define CSIGSTKSZ 0x4000 -#else -#define CSIGSTKSZ SIGSTKSZ -#endif - -static void die(const char* msg) { - perror(msg); - exit(EXIT_FAILURE); -} - -static int ok = 1; - -static void ioHandler(int signo, siginfo_t* info, void* ctxt) { -} - -// Set up the SIGIO signal handler in a high priority constructor, so -// that it is installed before the Go code starts. - -static void init(void) __attribute__ ((constructor (200))); - -static void init() { - struct sigaction sa; - - memset(&sa, 0, sizeof sa); - sa.sa_sigaction = ioHandler; - if (sigemptyset(&sa.sa_mask) < 0) { - die("sigemptyset"); - } - sa.sa_flags = SA_SIGINFO | SA_ONSTACK; - if (sigaction(SIGIO, &sa, NULL) < 0) { - die("sigaction"); - } -} - -// Test raising SIGIO on a C thread with an alternate signal stack -// when there is a Go signal handler for SIGIO. -static void* thread1(void* arg __attribute__ ((unused))) { - stack_t ss; - int i; - stack_t nss; - struct timespec ts; - - // Set up an alternate signal stack for this thread. - memset(&ss, 0, sizeof ss); - ss.ss_sp = malloc(CSIGSTKSZ); - if (ss.ss_sp == NULL) { - die("malloc"); - } - ss.ss_flags = 0; - ss.ss_size = CSIGSTKSZ; - if (sigaltstack(&ss, NULL) < 0) { - die("sigaltstack"); - } - - // Send ourselves a SIGIO. This will be caught by the Go - // signal handler which should forward to the C signal - // handler. - i = pthread_kill(pthread_self(), SIGIO); - if (i != 0) { - fprintf(stderr, "pthread_kill: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - // Wait until the signal has been delivered. - i = 0; - while (SIGIOCount() == 0) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for signal\n"); - exit(EXIT_FAILURE); - } - } - - // We should still be on the same signal stack. - if (sigaltstack(NULL, &nss) < 0) { - die("sigaltstack check"); - } - if ((nss.ss_flags & SS_DISABLE) != 0) { - fprintf(stderr, "sigaltstack disabled on return from Go\n"); - ok = 0; - } else if (nss.ss_sp != ss.ss_sp) { - fprintf(stderr, "sigaltstack changed on return from Go\n"); - ok = 0; - } - - return NULL; -} - -// Test calling a Go function to raise SIGIO on a C thread with an -// alternate signal stack when there is a Go signal handler for SIGIO. -static void* thread2(void* arg __attribute__ ((unused))) { - stack_t ss; - int i; - int oldcount; - pthread_t tid; - struct timespec ts; - stack_t nss; - - // Set up an alternate signal stack for this thread. - memset(&ss, 0, sizeof ss); - ss.ss_sp = malloc(CSIGSTKSZ); - if (ss.ss_sp == NULL) { - die("malloc"); - } - ss.ss_flags = 0; - ss.ss_size = CSIGSTKSZ; - if (sigaltstack(&ss, NULL) < 0) { - die("sigaltstack"); - } - - oldcount = SIGIOCount(); - - // Call a Go function that will call a C function to send us a - // SIGIO. - tid = pthread_self(); - GoRaiseSIGIO(&tid); - - // Wait until the signal has been delivered. - i = 0; - while (SIGIOCount() == oldcount) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for signal\n"); - exit(EXIT_FAILURE); - } - } - - // We should still be on the same signal stack. - if (sigaltstack(NULL, &nss) < 0) { - die("sigaltstack check"); - } - if ((nss.ss_flags & SS_DISABLE) != 0) { - fprintf(stderr, "sigaltstack disabled on return from Go\n"); - ok = 0; - } else if (nss.ss_sp != ss.ss_sp) { - fprintf(stderr, "sigaltstack changed on return from Go\n"); - ok = 0; - } - - return NULL; -} - -int main(int argc, char **argv) { - pthread_t tid; - int i; - - // Tell the Go library to start looking for SIGIO. - GoCatchSIGIO(); - - i = pthread_create(&tid, NULL, thread1, NULL); - if (i != 0) { - fprintf(stderr, "pthread_create: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - i = pthread_join(tid, NULL); - if (i != 0) { - fprintf(stderr, "pthread_join: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - i = pthread_create(&tid, NULL, thread2, NULL); - if (i != 0) { - fprintf(stderr, "pthread_create: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - i = pthread_join(tid, NULL); - if (i != 0) { - fprintf(stderr, "pthread_join: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - if (!ok) { - exit(EXIT_FAILURE); - } - - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/main5.c b/misc/cgo/testcarchive/testdata/main5.c deleted file mode 100644 index c64c246fde..0000000000 --- a/misc/cgo/testcarchive/testdata/main5.c +++ /dev/null @@ -1,105 +0,0 @@ -// 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. - -// Test for verifying that the Go runtime properly forwards -// signals when non-Go signals are raised. - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/time.h> -#include <sys/select.h> - -#include "libgo2.h" - -int *nilp; - -int main(int argc, char** argv) { - int verbose; - int test; - - if (argc < 2) { - printf("Missing argument\n"); - return 1; - } - - test = atoi(argv[1]); - - verbose = (argc > 2); - - Noop(); - - switch (test) { - case 1: { - if (verbose) { - printf("attempting segfault\n"); - } - - *nilp = 0; - break; - } - - case 2: { - struct timeval tv; - - if (verbose) { - printf("attempting external signal test\n"); - } - - fprintf(stderr, "OK\n"); - fflush(stderr); - - // The program should be interrupted before - // this sleep finishes. We use select rather - // than sleep because in older versions of - // glibc the sleep function does some signal - // fiddling to handle SIGCHLD. If this - // program is fiddling signals just when the - // test program sends the signal, the signal - // may be delivered to a Go thread which will - // break this test. - tv.tv_sec = 60; - tv.tv_usec = 0; - select(0, NULL, NULL, NULL, &tv); - - break; - } - case 3: { - if (verbose) { - printf("attempting SIGPIPE\n"); - } - - int fd[2]; - if (pipe(fd) != 0) { - printf("pipe(2) failed\n"); - return 0; - } - // Close the reading end. - close(fd[0]); - // Expect that write(2) fails (EPIPE) - if (write(fd[1], "some data", 9) != -1) { - printf("write(2) unexpectedly succeeded\n"); - return 0; - } - printf("did not receive SIGPIPE\n"); - return 0; - } - case 4: { - fprintf(stderr, "OK\n"); - fflush(stderr); - - if (verbose) { - printf("calling Block\n"); - } - Block(); - } - default: - printf("Unknown test: %d\n", test); - return 0; - } - - printf("FAIL\n"); - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/main6.c b/misc/cgo/testcarchive/testdata/main6.c deleted file mode 100644 index 2745eb9dc5..0000000000 --- a/misc/cgo/testcarchive/testdata/main6.c +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -// Test that using the Go profiler in a C program does not crash. - -#include <stddef.h> -#include <sys/time.h> - -#include "libgo6.h" - -int main(int argc, char **argv) { - struct timeval tvstart, tvnow; - int diff; - - gettimeofday(&tvstart, NULL); - - go_start_profile(); - - // Busy wait so we have something to profile. - // If we just sleep the profiling signal will never fire. - while (1) { - gettimeofday(&tvnow, NULL); - diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec); - - // Profile frequency is 100Hz so we should definitely - // get a signal in 50 milliseconds. - if (diff > 50 * 1000) - break; - } - - go_stop_profile(); - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/main7.c b/misc/cgo/testcarchive/testdata/main7.c deleted file mode 100644 index 2c6d98daa8..0000000000 --- a/misc/cgo/testcarchive/testdata/main7.c +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2019 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. - -// Test that lots of calls don't deadlock. - -#include <stdio.h> - -#include "libgo7.h" - -int main() { - int i; - - for (i = 0; i < 100000; i++) { - GoFunction7(); - } - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/main8.c b/misc/cgo/testcarchive/testdata/main8.c deleted file mode 100644 index 95fb7a349e..0000000000 --- a/misc/cgo/testcarchive/testdata/main8.c +++ /dev/null @@ -1,16 +0,0 @@ -// 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. - -// Test preemption. - -#include <stdlib.h> - -#include "libgo8.h" - -int main() { - GoFunction8(); - - // That should have exited the program. - abort(); -} diff --git a/misc/cgo/testcarchive/testdata/main_unix.c b/misc/cgo/testcarchive/testdata/main_unix.c deleted file mode 100644 index bd00f9d233..0000000000 --- a/misc/cgo/testcarchive/testdata/main_unix.c +++ /dev/null @@ -1,59 +0,0 @@ -// 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. - -#include <signal.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -struct sigaction sa; -struct sigaction osa; - -static void (*oldHandler)(int, siginfo_t*, void*); - -static void handler(int signo, siginfo_t* info, void* ctxt) { - if (oldHandler) { - oldHandler(signo, info, ctxt); - } -} - -int install_handler() { - // Install our own signal handler. - memset(&sa, 0, sizeof sa); - sa.sa_sigaction = handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_ONSTACK | SA_SIGINFO; - memset(&osa, 0, sizeof osa); - sigemptyset(&osa.sa_mask); - if (sigaction(SIGSEGV, &sa, &osa) < 0) { - perror("sigaction"); - return 2; - } - if (osa.sa_handler == SIG_DFL) { - fprintf(stderr, "Go runtime did not install signal handler\n"); - return 2; - } - // gccgo does not set SA_ONSTACK for SIGSEGV. - if (getenv("GCCGO") == NULL && (osa.sa_flags&SA_ONSTACK) == 0) { - fprintf(stderr, "Go runtime did not install signal handler\n"); - return 2; - } - oldHandler = osa.sa_sigaction; - - return 0; -} - -int check_handler() { - if (sigaction(SIGSEGV, NULL, &sa) < 0) { - perror("sigaction check"); - return 2; - } - if (sa.sa_sigaction != handler) { - fprintf(stderr, "ERROR: wrong signal handler: %p != %p\n", sa.sa_sigaction, handler); - return 2; - } - return 0; -} - diff --git a/misc/cgo/testcarchive/testdata/main_windows.c b/misc/cgo/testcarchive/testdata/main_windows.c deleted file mode 100644 index eded8af1a2..0000000000 --- a/misc/cgo/testcarchive/testdata/main_windows.c +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -/* - * Dummy implementations for Windows, because Windows doesn't - * support Unix-style signal handling. - */ - -int install_handler() { - return 0; -} - - -int check_handler() { - return 0; -} diff --git a/misc/cgo/testcarchive/testdata/p/p.go b/misc/cgo/testcarchive/testdata/p/p.go deleted file mode 100644 index 82b445c121..0000000000 --- a/misc/cgo/testcarchive/testdata/p/p.go +++ /dev/null @@ -1,10 +0,0 @@ -// 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 p - -import "C" - -//export FromPkg -func FromPkg() int32 { return 1024 } diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go deleted file mode 100644 index 2b57249817..0000000000 --- a/misc/cgo/testcshared/cshared_test.go +++ /dev/null @@ -1,914 +0,0 @@ -// Copyright 2017 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 cshared_test - -import ( - "bufio" - "bytes" - "debug/elf" - "debug/pe" - "encoding/binary" - "flag" - "fmt" - "log" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "sync" - "testing" - "unicode" -) - -// C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)). -var cc []string - -// ".exe" on Windows. -var exeSuffix string - -var GOOS, GOARCH, GOROOT string -var installdir, androiddir string -var libgoname string - -func TestMain(m *testing.M) { - os.Exit(testMain(m)) -} - -func testMain(m *testing.M) int { - log.SetFlags(log.Lshortfile) - flag.Parse() - if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { - fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n") - os.Exit(0) - } - if runtime.GOOS == "linux" { - if _, err := os.Stat("/etc/alpine-release"); err == nil { - fmt.Printf("SKIP - skipping failing test on alpine - go.dev/issue/19938\n") - os.Exit(0) - } - } - - GOOS = goEnv("GOOS") - GOARCH = goEnv("GOARCH") - GOROOT = goEnv("GOROOT") - - if _, err := os.Stat(GOROOT); os.IsNotExist(err) { - log.Fatalf("Unable able to find GOROOT at '%s'", GOROOT) - } - - androiddir = fmt.Sprintf("/data/local/tmp/testcshared-%d", os.Getpid()) - if runtime.GOOS != GOOS && GOOS == "android" { - args := append(adbCmd(), "exec-out", "mkdir", "-p", androiddir) - cmd := exec.Command(args[0], args[1:]...) - out, err := cmd.CombinedOutput() - if err != nil { - log.Fatalf("setupAndroid failed: %v\n%s\n", err, out) - } - defer cleanupAndroid() - } - - cc = []string{goEnv("CC")} - - out := goEnv("GOGCCFLAGS") - quote := '\000' - start := 0 - lastSpace := true - backslash := false - s := string(out) - for i, c := range s { - if quote == '\000' && unicode.IsSpace(c) { - if !lastSpace { - cc = append(cc, s[start:i]) - lastSpace = true - } - } else { - if lastSpace { - start = i - lastSpace = false - } - if quote == '\000' && !backslash && (c == '"' || c == '\'') { - quote = c - backslash = false - } else if !backslash && quote == c { - quote = '\000' - } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' { - backslash = true - } else { - backslash = false - } - } - } - if !lastSpace { - cc = append(cc, s[start:]) - } - - switch GOOS { - case "darwin", "ios": - // For Darwin/ARM. - // TODO(crawshaw): can we do better? - cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...) - case "android": - cc = append(cc, "-pie") - } - libgodir := GOOS + "_" + GOARCH - switch GOOS { - case "darwin", "ios": - if GOARCH == "arm64" { - libgodir += "_shared" - } - case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris", "illumos": - libgodir += "_shared" - } - cc = append(cc, "-I", filepath.Join("pkg", libgodir)) - - // Force reallocation (and avoid aliasing bugs) for parallel tests that append to cc. - cc = cc[:len(cc):len(cc)] - - if GOOS == "windows" { - exeSuffix = ".exe" - } - - // Copy testdata into GOPATH/src/testcshared, along with a go.mod file - // declaring the same path. - - GOPATH, err := os.MkdirTemp("", "cshared_test") - if err != nil { - log.Panic(err) - } - defer os.RemoveAll(GOPATH) - os.Setenv("GOPATH", GOPATH) - - modRoot := filepath.Join(GOPATH, "src", "testcshared") - if err := overlayDir(modRoot, "testdata"); err != nil { - log.Panic(err) - } - if err := os.Chdir(modRoot); err != nil { - log.Panic(err) - } - os.Setenv("PWD", modRoot) - if err := os.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil { - log.Panic(err) - } - - defer func() { - if installdir != "" { - err := os.RemoveAll(installdir) - if err != nil { - log.Panic(err) - } - } - }() - - return m.Run() -} - -func goEnv(key string) string { - out, err := exec.Command("go", "env", key).Output() - if err != nil { - log.Printf("go env %s failed:\n%s", key, err) - log.Panicf("%s", err.(*exec.ExitError).Stderr) - } - return strings.TrimSpace(string(out)) -} - -func cmdToRun(name string) string { - return "./" + name + exeSuffix -} - -func adbCmd() []string { - cmd := []string{"adb"} - if flags := os.Getenv("GOANDROID_ADB_FLAGS"); flags != "" { - cmd = append(cmd, strings.Split(flags, " ")...) - } - return cmd -} - -func adbPush(t *testing.T, filename string) { - if runtime.GOOS == GOOS || GOOS != "android" { - return - } - args := append(adbCmd(), "push", filename, fmt.Sprintf("%s/%s", androiddir, filename)) - cmd := exec.Command(args[0], args[1:]...) - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("adb command failed: %v\n%s\n", err, out) - } -} - -func adbRun(t *testing.T, env []string, adbargs ...string) string { - if GOOS != "android" { - t.Fatalf("trying to run adb command when operating system is not android.") - } - args := append(adbCmd(), "exec-out") - // Propagate LD_LIBRARY_PATH to the adb shell invocation. - for _, e := range env { - if strings.Contains(e, "LD_LIBRARY_PATH=") { - adbargs = append([]string{e}, adbargs...) - break - } - } - shellcmd := fmt.Sprintf("cd %s; %s", androiddir, strings.Join(adbargs, " ")) - args = append(args, shellcmd) - cmd := exec.Command(args[0], args[1:]...) - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("adb command failed: %v\n%s\n", err, out) - } - return strings.Replace(string(out), "\r", "", -1) -} - -func run(t *testing.T, extraEnv []string, args ...string) string { - t.Helper() - cmd := exec.Command(args[0], args[1:]...) - if len(extraEnv) > 0 { - cmd.Env = append(os.Environ(), extraEnv...) - } - - if GOOS != "windows" { - // TestUnexportedSymbols relies on file descriptor 30 - // being closed when the program starts, so enforce - // that in all cases. (The first three descriptors are - // stdin/stdout/stderr, so we just need to make sure - // that cmd.ExtraFiles[27] exists and is nil.) - cmd.ExtraFiles = make([]*os.File, 28) - } - - out, err := cmd.CombinedOutput() - 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) -} - -func runExe(t *testing.T, extraEnv []string, args ...string) string { - t.Helper() - if runtime.GOOS != GOOS && GOOS == "android" { - return adbRun(t, append(os.Environ(), extraEnv...), args...) - } - return run(t, extraEnv, args...) -} - -func runCC(t *testing.T, args ...string) string { - t.Helper() - // This function is run in parallel, so append to a copy of cc - // rather than cc itself. - return run(t, nil, append(append([]string(nil), cc...), args...)...) -} - -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 := os.MkdirTemp("", "testcshared_obj") - if err != nil { - return err - } - defer os.RemoveAll(objDir) - - // Generate a C header file for p, which is a non-main dependency - // of main package libgo. - // - // TODO(golang.org/issue/35715): This should be simpler. - args := []string{"go", "tool", "cgo", - "-objdir", objDir, - "-exportheader", "p.h", - filepath.Join(".", "p", "p.go")} - 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) - } - - // Generate a C header file for libgo itself. - installdir, err = os.MkdirTemp("", "testcshared") - if err != nil { - return err - } - libgoname = "libgo.a" - - args = []string{"go", "build", "-buildmode=c-shared", "-o", filepath.Join(installdir, libgoname), "./libgo"} - 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) - } - - args = []string{"go", "build", "-buildmode=c-shared", - "-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) - } - dlltoolpath := strings.TrimSpace(string(out)) - if filepath.Ext(dlltoolpath) == "" { - // Some compilers report slash-separated paths without extensions - // instead of ordinary Windows paths. - // Try to find the canonical name for the path. - if lp, err := exec.LookPath(dlltoolpath); err == nil { - dlltoolpath = lp - } - } - - args := []string{dlltoolpath, "-D", args[6], "-l", libgoname, "-d", "libgo.def"} - - if filepath.Ext(dlltoolpath) == "" { - // 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. - // TODO(thanm): remove this workaround once we can upgrade - // the compilers on the windows-arm64 builder. - 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 prefix, _, _ := strings.Cut(name, "-"); prefix { - 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)) - cmd = exec.Command(args[0], args[1:]...) - out, err = cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("adb command failed: %v\n%s\n", err, out) - } - } - - return nil -} - -var ( - headersOnce sync.Once - headersErr error -) - -func createHeadersOnce(t *testing.T) { - headersOnce.Do(func() { - headersErr = createHeaders() - }) - if headersErr != nil { - t.Helper() - t.Fatal(headersErr) - } -} - -func cleanupAndroid() { - if GOOS != "android" { - return - } - args := append(adbCmd(), "exec-out", "rm", "-rf", androiddir) - cmd := exec.Command(args[0], args[1:]...) - out, err := cmd.CombinedOutput() - if err != nil { - log.Panicf("cleanupAndroid failed: %v\n%s\n", err, out) - } -} - -// test0: exported symbols in shared lib are accessible. -func TestExportedSymbols(t *testing.T) { - t.Parallel() - - cmd := "testp0" - bin := cmdToRun(cmd) - - createHeadersOnce(t) - - runCC(t, "-I", installdir, "-o", cmd, "main0.c", libgoname) - adbPush(t, cmd) - - defer os.Remove(bin) - - out := runExe(t, []string{"LD_LIBRARY_PATH=."}, bin) - if strings.TrimSpace(out) != "PASS" { - t.Error(out) - } -} - -func checkNumberOfExportedFunctionsWindows(t *testing.T, exportAllSymbols bool) { - const prog = ` -package main - -import "C" - -//export GoFunc -func GoFunc() { - println(42) -} - -//export GoFunc2 -func GoFunc2() { - println(24) -} - -func main() { -} -` - - tmpdir := t.TempDir() - - srcfile := filepath.Join(tmpdir, "test.go") - objfile := filepath.Join(tmpdir, "test.dll") - if err := os.WriteFile(srcfile, []byte(prog), 0666); err != nil { - t.Fatal(err) - } - argv := []string{"build", "-buildmode=c-shared"} - if exportAllSymbols { - argv = append(argv, "-ldflags", "-extldflags=-Wl,--export-all-symbols") - } - argv = append(argv, "-o", objfile, srcfile) - out, err := exec.Command("go", argv...).CombinedOutput() - if err != nil { - t.Fatalf("build failure: %s\n%s\n", err, string(out)) - } - - f, err := pe.Open(objfile) - if err != nil { - t.Fatalf("pe.Open failed: %v", err) - } - defer f.Close() - section := f.Section(".edata") - if section == nil { - t.Skip(".edata section is not present") - } - - // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go - type IMAGE_EXPORT_DIRECTORY struct { - _ [2]uint32 - _ [2]uint16 - _ [2]uint32 - NumberOfFunctions uint32 - NumberOfNames uint32 - _ [3]uint32 - } - var e IMAGE_EXPORT_DIRECTORY - if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil { - t.Fatalf("binary.Read failed: %v", err) - } - - // Only the two exported functions and _cgo_dummy_export should be exported - expectedNumber := uint32(3) - - if exportAllSymbols { - if e.NumberOfFunctions <= expectedNumber { - t.Fatalf("missing exported functions: %v", e.NumberOfFunctions) - } - if e.NumberOfNames <= expectedNumber { - t.Fatalf("missing exported names: %v", e.NumberOfNames) - } - } else { - if e.NumberOfFunctions != expectedNumber { - t.Fatalf("got %d exported functions; want %d", e.NumberOfFunctions, expectedNumber) - } - if e.NumberOfNames != expectedNumber { - t.Fatalf("got %d exported names; want %d", e.NumberOfNames, expectedNumber) - } - } -} - -func TestNumberOfExportedFunctions(t *testing.T) { - if GOOS != "windows" { - t.Skip("skipping windows only test") - } - t.Parallel() - - t.Run("OnlyExported", func(t *testing.T) { - checkNumberOfExportedFunctionsWindows(t, false) - }) - t.Run("All", func(t *testing.T) { - checkNumberOfExportedFunctionsWindows(t, true) - }) -} - -// test1: shared library can be dynamically loaded and exported symbols are accessible. -func TestExportedSymbolsWithDynamicLoad(t *testing.T) { - t.Parallel() - - if GOOS == "windows" { - t.Logf("Skipping on %s", GOOS) - return - } - - cmd := "testp1" - bin := cmdToRun(cmd) - - createHeadersOnce(t) - - if GOOS != "freebsd" { - runCC(t, "-o", cmd, "main1.c", "-ldl") - } else { - runCC(t, "-o", cmd, "main1.c") - } - adbPush(t, cmd) - - defer os.Remove(bin) - - out := runExe(t, nil, bin, "./"+libgoname) - if strings.TrimSpace(out) != "PASS" { - t.Error(out) - } -} - -// test2: tests libgo2 which does not export any functions. -func TestUnexportedSymbols(t *testing.T) { - t.Parallel() - - if GOOS == "windows" { - t.Logf("Skipping on %s", GOOS) - return - } - - cmd := "testp2" - bin := cmdToRun(cmd) - libname := "libgo2.a" - - run(t, - nil, - "go", "build", - "-buildmode=c-shared", - "-installsuffix", "testcshared", - "-o", libname, "./libgo2", - ) - adbPush(t, libname) - - linkFlags := "-Wl,--no-as-needed" - if GOOS == "darwin" || GOOS == "ios" { - linkFlags = "" - } - - runCC(t, "-o", cmd, "main2.c", linkFlags, libname) - adbPush(t, cmd) - - defer os.Remove(libname) - defer os.Remove(bin) - - out := runExe(t, []string{"LD_LIBRARY_PATH=."}, bin) - - if strings.TrimSpace(out) != "PASS" { - t.Error(out) - } -} - -// test3: tests main.main is exported on android. -func TestMainExportedOnAndroid(t *testing.T) { - t.Parallel() - - switch GOOS { - case "android": - break - default: - t.Logf("Skipping on %s", GOOS) - return - } - - cmd := "testp3" - bin := cmdToRun(cmd) - - createHeadersOnce(t) - - runCC(t, "-o", cmd, "main3.c", "-ldl") - adbPush(t, cmd) - - defer os.Remove(bin) - - out := runExe(t, nil, bin, "./"+libgoname) - if strings.TrimSpace(out) != "PASS" { - t.Error(out) - } -} - -func testSignalHandlers(t *testing.T, pkgname, cfile, cmd string) { - libname := pkgname + ".a" - run(t, - nil, - "go", "build", - "-buildmode=c-shared", - "-installsuffix", "testcshared", - "-o", libname, pkgname, - ) - adbPush(t, libname) - if GOOS != "freebsd" { - runCC(t, "-pthread", "-o", cmd, cfile, "-ldl") - } else { - runCC(t, "-pthread", "-o", cmd, cfile) - } - adbPush(t, cmd) - - bin := cmdToRun(cmd) - - defer os.Remove(libname) - defer os.Remove(bin) - defer os.Remove(pkgname + ".h") - - out := runExe(t, nil, bin, "./"+libname) - if strings.TrimSpace(out) != "PASS" { - t.Error(run(t, nil, bin, libname, "verbose")) - } -} - -// test4: test signal handlers -func TestSignalHandlers(t *testing.T) { - t.Parallel() - if GOOS == "windows" { - t.Logf("Skipping on %s", GOOS) - return - } - testSignalHandlers(t, "./libgo4", "main4.c", "testp4") -} - -// test5: test signal handlers with os/signal.Notify -func TestSignalHandlersWithNotify(t *testing.T) { - t.Parallel() - if GOOS == "windows" { - t.Logf("Skipping on %s", GOOS) - return - } - testSignalHandlers(t, "./libgo5", "main5.c", "testp5") -} - -func TestPIE(t *testing.T) { - t.Parallel() - - switch GOOS { - case "linux", "android": - break - default: - t.Logf("Skipping on %s", GOOS) - return - } - - createHeadersOnce(t) - - f, err := elf.Open(libgoname) - if err != nil { - t.Fatalf("elf.Open failed: %v", err) - } - defer f.Close() - - ds := f.SectionByType(elf.SHT_DYNAMIC) - if ds == nil { - t.Fatalf("no SHT_DYNAMIC section") - } - d, err := ds.Data() - if err != nil { - t.Fatalf("can't read SHT_DYNAMIC contents: %v", err) - } - for len(d) > 0 { - var tag elf.DynTag - switch f.Class { - case elf.ELFCLASS32: - tag = elf.DynTag(f.ByteOrder.Uint32(d[:4])) - d = d[8:] - case elf.ELFCLASS64: - tag = elf.DynTag(f.ByteOrder.Uint64(d[:8])) - d = d[16:] - } - if tag == elf.DT_TEXTREL { - t.Fatalf("%s has DT_TEXTREL flag", libgoname) - } - } -} - -// Test that installing a second time recreates the header file. -func TestCachedInstall(t *testing.T) { - tmpdir, err := os.MkdirTemp("", "cshared") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - - copyFile(t, filepath.Join(tmpdir, "src", "testcshared", "go.mod"), "go.mod") - copyFile(t, filepath.Join(tmpdir, "src", "testcshared", "libgo", "libgo.go"), filepath.Join("libgo", "libgo.go")) - copyFile(t, filepath.Join(tmpdir, "src", "testcshared", "p", "p.go"), filepath.Join("p", "p.go")) - - buildcmd := []string{"go", "install", "-x", "-buildmode=c-shared", "-installsuffix", "testcshared", "./libgo"} - - cmd := exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Dir = filepath.Join(tmpdir, "src", "testcshared") - env := append(cmd.Environ(), - "GOPATH="+tmpdir, - "GOBIN="+filepath.Join(tmpdir, "bin"), - "GO111MODULE=off", // 'go install' only works in GOPATH mode - ) - cmd.Env = env - t.Log(buildcmd) - out, err := cmd.CombinedOutput() - t.Logf("%s", out) - if err != nil { - t.Fatal(err) - } - - var libgoh, ph string - - walker := func(path string, info os.FileInfo, err error) error { - if err != nil { - t.Fatal(err) - } - var ps *string - switch filepath.Base(path) { - case "libgo.h": - ps = &libgoh - case "p.h": - ps = &ph - } - if ps != nil { - if *ps != "" { - t.Fatalf("%s found again", *ps) - } - *ps = path - } - return nil - } - - if err := filepath.Walk(tmpdir, walker); err != nil { - t.Fatal(err) - } - - if libgoh == "" { - t.Fatal("libgo.h not installed") - } - - if err := os.Remove(libgoh); err != nil { - t.Fatal(err) - } - - cmd = exec.Command(buildcmd[0], buildcmd[1:]...) - cmd.Dir = filepath.Join(tmpdir, "src", "testcshared") - cmd.Env = env - t.Log(buildcmd) - out, err = cmd.CombinedOutput() - t.Logf("%s", out) - if err != nil { - t.Fatal(err) - } - - if _, err := os.Stat(libgoh); err != nil { - t.Errorf("libgo.h not installed in second run: %v", err) - } -} - -// copyFile copies src to dst. -func copyFile(t *testing.T, dst, src string) { - t.Helper() - 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 := os.WriteFile(dst, data, 0666); err != nil { - t.Fatal(err) - } -} - -func TestGo2C2Go(t *testing.T) { - switch GOOS { - case "darwin", "ios", "windows": - // Non-ELF shared libraries don't support the multiple - // copies of the runtime package implied by this test. - t.Skipf("linking c-shared into Go programs not supported on %s; issue 29061, 49457", GOOS) - case "android": - t.Skip("test fails on android; issue 29087") - } - - t.Parallel() - - tmpdir, err := os.MkdirTemp("", "cshared-TestGo2C2Go") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - - lib := filepath.Join(tmpdir, "libtestgo2c2go.a") - 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 != "" { - cgoCflags += " " - } - cgoCflags += "-I" + tmpdir - - cgoLdflags := os.Getenv("CGO_LDFLAGS") - if cgoLdflags != "" { - cgoLdflags += " " - } - cgoLdflags += "-L" + tmpdir + " -ltestgo2c2go" - - goenv := []string{"CGO_CFLAGS=" + cgoCflags, "CGO_LDFLAGS=" + cgoLdflags} - - ldLibPath := os.Getenv("LD_LIBRARY_PATH") - if ldLibPath != "" { - ldLibPath += ":" - } - ldLibPath += tmpdir - - runenv := []string{"LD_LIBRARY_PATH=" + ldLibPath} - - bin := filepath.Join(tmpdir, "m1") + exeSuffix - run(t, goenv, "go", "build", "-o", bin, "./go2c2go/m1") - runExe(t, runenv, bin) - - bin = filepath.Join(tmpdir, "m2") + exeSuffix - run(t, goenv, "go", "build", "-o", bin, "./go2c2go/m2") - runExe(t, runenv, bin) -} - -func TestIssue36233(t *testing.T) { - t.Parallel() - - // Test that the export header uses GoComplex64 and GoComplex128 - // for complex types. - - tmpdir, err := os.MkdirTemp("", "cshared-TestIssue36233") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(tmpdir) - - const exportHeader = "issue36233.h" - - run(t, nil, "go", "tool", "cgo", "-exportheader", exportHeader, "-objdir", tmpdir, "./issue36233/issue36233.go") - data, err := os.ReadFile(exportHeader) - if err != nil { - t.Fatal(err) - } - - funcs := []struct{ name, signature string }{ - {"exportComplex64", "GoComplex64 exportComplex64(GoComplex64 v)"}, - {"exportComplex128", "GoComplex128 exportComplex128(GoComplex128 v)"}, - {"exportComplexfloat", "GoComplex64 exportComplexfloat(GoComplex64 v)"}, - {"exportComplexdouble", "GoComplex128 exportComplexdouble(GoComplex128 v)"}, - } - - scanner := bufio.NewScanner(bytes.NewReader(data)) - var found int - for scanner.Scan() { - b := scanner.Bytes() - for _, fn := range funcs { - if bytes.Contains(b, []byte(fn.name)) { - found++ - if !bytes.Contains(b, []byte(fn.signature)) { - t.Errorf("function signature mismatch; got %q, want %q", b, fn.signature) - } - } - } - } - if err = scanner.Err(); err != nil { - t.Errorf("scanner encountered error: %v", err) - } - if found != len(funcs) { - t.Error("missing functions") - } -} diff --git a/misc/cgo/testcshared/overlaydir_test.go b/misc/cgo/testcshared/overlaydir_test.go deleted file mode 100644 index 85d6b44eef..0000000000 --- a/misc/cgo/testcshared/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 cshared_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/testcshared/testdata/go2c2go/go/shlib.go b/misc/cgo/testcshared/testdata/go2c2go/go/shlib.go deleted file mode 100644 index 76a5323ad2..0000000000 --- a/misc/cgo/testcshared/testdata/go2c2go/go/shlib.go +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -package main - -import "C" - -//export GoFunc -func GoFunc() int { return 1 } - -func main() {} diff --git a/misc/cgo/testcshared/testdata/go2c2go/m1/c.c b/misc/cgo/testcshared/testdata/go2c2go/m1/c.c deleted file mode 100644 index 0e8fac4cf3..0000000000 --- a/misc/cgo/testcshared/testdata/go2c2go/m1/c.c +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -#include "libtestgo2c2go.h" - -int CFunc(void) { - return (GoFunc() << 8) + 2; -} diff --git a/misc/cgo/testcshared/testdata/go2c2go/m1/main.go b/misc/cgo/testcshared/testdata/go2c2go/m1/main.go deleted file mode 100644 index 17ba1eb0a7..0000000000 --- a/misc/cgo/testcshared/testdata/go2c2go/m1/main.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -package main - -// extern int CFunc(void); -import "C" - -import ( - "fmt" - "os" -) - -func main() { - got := C.CFunc() - const want = (1 << 8) | 2 - if got != want { - fmt.Printf("got %#x, want %#x\n", got, want) - os.Exit(1) - } -} diff --git a/misc/cgo/testcshared/testdata/go2c2go/m2/main.go b/misc/cgo/testcshared/testdata/go2c2go/m2/main.go deleted file mode 100644 index 91bf308057..0000000000 --- a/misc/cgo/testcshared/testdata/go2c2go/m2/main.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -package main - -// #include "libtestgo2c2go.h" -import "C" - -import ( - "fmt" - "os" -) - -func main() { - got := C.GoFunc() - const want = 1 - if got != want { - fmt.Printf("got %#x, want %#x\n", got, want) - os.Exit(1) - } -} diff --git a/misc/cgo/testcshared/testdata/issue36233/issue36233.go b/misc/cgo/testcshared/testdata/issue36233/issue36233.go deleted file mode 100644 index 433bf5ce55..0000000000 --- a/misc/cgo/testcshared/testdata/issue36233/issue36233.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2022 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 - -// #include <complex.h> -import "C" - -//export exportComplex64 -func exportComplex64(v complex64) complex64 { - return v -} - -//export exportComplex128 -func exportComplex128(v complex128) complex128 { - return v -} - -//export exportComplexfloat -func exportComplexfloat(v C.complexfloat) C.complexfloat { - return v -} - -//export exportComplexdouble -func exportComplexdouble(v C.complexdouble) C.complexdouble { - return v -} - -func main() {} diff --git a/misc/cgo/testcshared/testdata/libgo/libgo.go b/misc/cgo/testcshared/testdata/libgo/libgo.go deleted file mode 100644 index 063441766a..0000000000 --- a/misc/cgo/testcshared/testdata/libgo/libgo.go +++ /dev/null @@ -1,46 +0,0 @@ -// 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 main - -import ( - "syscall" - _ "testcshared/p" - "time" -) - -import "C" - -var initCh = make(chan int, 1) -var ranMain bool - -func init() { - // emulate an exceedingly slow package initialization function - time.Sleep(100 * time.Millisecond) - initCh <- 42 -} - -func main() { - ranMain = true -} - -//export DidInitRun -func DidInitRun() bool { - select { - case x := <-initCh: - if x != 42 { - // Just in case initCh was not correctly made. - println("want init value of 42, got: ", x) - syscall.Exit(2) - } - return true - default: - return false - } -} - -//export DidMainRun -func DidMainRun() bool { - return ranMain -} diff --git a/misc/cgo/testcshared/testdata/libgo2/dup2.go b/misc/cgo/testcshared/testdata/libgo2/dup2.go deleted file mode 100644 index d50e0c42ab..0000000000 --- a/misc/cgo/testcshared/testdata/libgo2/dup2.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -//go:build darwin || dragonfly || freebsd || (linux && !arm64 && !loong64 && !riscv64) || netbsd || openbsd - -package main - -import "syscall" - -func dup2(oldfd, newfd int) error { - return syscall.Dup2(oldfd, newfd) -} diff --git a/misc/cgo/testcshared/testdata/libgo2/dup3.go b/misc/cgo/testcshared/testdata/libgo2/dup3.go deleted file mode 100644 index ec4b5a73ec..0000000000 --- a/misc/cgo/testcshared/testdata/libgo2/dup3.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -//go:build (linux && arm64) || (linux && loong64) || (linux && riscv64) - -package main - -import "syscall" - -func dup2(oldfd, newfd int) error { - return syscall.Dup3(oldfd, newfd, 0) -} diff --git a/misc/cgo/testcshared/testdata/libgo2/libgo2.go b/misc/cgo/testcshared/testdata/libgo2/libgo2.go deleted file mode 100644 index 5f6cfd0039..0000000000 --- a/misc/cgo/testcshared/testdata/libgo2/libgo2.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris - -package main - -// Test a shared library created by -buildmode=c-shared that does not -// export anything. - -import ( - "fmt" - "os" - "syscall" -) - -// To test this we want to communicate between the main program and -// the shared library without using any exported symbols. The init -// function creates a pipe and Dups the read end to a known number -// that the C code can also use. - -const ( - fd = 30 -) - -func init() { - var p [2]int - if e := syscall.Pipe(p[0:]); e != nil { - fmt.Fprintf(os.Stderr, "pipe: %v\n", e) - os.Exit(2) - } - - if e := dup2(p[0], fd); e != nil { - fmt.Fprintf(os.Stderr, "dup2: %v\n", e) - os.Exit(2) - } - - const str = "PASS" - if n, e := syscall.Write(p[1], []byte(str)); e != nil || n != len(str) { - fmt.Fprintf(os.Stderr, "write: %d %v\n", n, e) - os.Exit(2) - } - - if e := syscall.Close(p[1]); e != nil { - fmt.Fprintf(os.Stderr, "close: %v\n", e) - os.Exit(2) - } -} - -func main() { -} diff --git a/misc/cgo/testcshared/testdata/libgo4/libgo4.go b/misc/cgo/testcshared/testdata/libgo4/libgo4.go deleted file mode 100644 index 9c30c8585a..0000000000 --- a/misc/cgo/testcshared/testdata/libgo4/libgo4.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 main - -import "C" - -import ( - "fmt" - "os" - "runtime" -) - -// RunGoroutines starts some goroutines that don't do anything. -// The idea is to get some threads going, so that a signal will be delivered -// to a thread started by Go. -// -//export RunGoroutines -func RunGoroutines() { - for i := 0; i < 4; i++ { - go func() { - runtime.LockOSThread() - select {} - }() - } -} - -var P *byte - -// TestSEGV makes sure that an invalid address turns into a run-time Go panic. -// -//export TestSEGV -func TestSEGV() { - defer func() { - if recover() == nil { - fmt.Fprintln(os.Stderr, "no panic from segv") - os.Exit(1) - } - }() - *P = 0 - fmt.Fprintln(os.Stderr, "continued after segv") - os.Exit(1) -} - -func main() { -} diff --git a/misc/cgo/testcshared/testdata/libgo5/libgo5.go b/misc/cgo/testcshared/testdata/libgo5/libgo5.go deleted file mode 100644 index 4ca44e5894..0000000000 --- a/misc/cgo/testcshared/testdata/libgo5/libgo5.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 main - -import "C" - -import ( - "os" - "os/signal" - "syscall" - "time" -) - -// The channel used to read SIGIO signals. -var sigioChan chan os.Signal - -// CatchSIGIO starts catching SIGIO signals. -// -//export CatchSIGIO -func CatchSIGIO() { - sigioChan = make(chan os.Signal, 1) - signal.Notify(sigioChan, syscall.SIGIO) -} - -// ResetSIGIO stops catching SIGIO signals. -// -//export ResetSIGIO -func ResetSIGIO() { - signal.Reset(syscall.SIGIO) -} - -// SawSIGIO returns whether we saw a SIGIO within a brief pause. -// -//export SawSIGIO -func SawSIGIO() C.int { - select { - case <-sigioChan: - return 1 - case <-time.After(100 * time.Millisecond): - return 0 - } -} - -func main() { -} diff --git a/misc/cgo/testcshared/testdata/main0.c b/misc/cgo/testcshared/testdata/main0.c deleted file mode 100644 index 39ef7e3051..0000000000 --- a/misc/cgo/testcshared/testdata/main0.c +++ /dev/null @@ -1,42 +0,0 @@ -// 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. - -#include <stdint.h> -#include <stdio.h> - -#include "p.h" -#include "libgo.h" - -// Tests libgo.so to export the following functions. -// int8_t DidInitRun(); -// int8_t DidMainRun(); -// int32_t FromPkg(); -// uint32_t Divu(uint32_t, uint32_t); -int main(void) { - int8_t ran_init = DidInitRun(); - if (!ran_init) { - fprintf(stderr, "ERROR: DidInitRun returned unexpected results: %d\n", - ran_init); - return 1; - } - int8_t ran_main = DidMainRun(); - if (ran_main) { - fprintf(stderr, "ERROR: DidMainRun returned unexpected results: %d\n", - ran_main); - return 1; - } - int32_t from_pkg = FromPkg(); - if (from_pkg != 1024) { - fprintf(stderr, "ERROR: FromPkg=%d, want %d\n", from_pkg, 1024); - return 1; - } - uint32_t divu = Divu(2264, 31); - if (divu != 73) { - fprintf(stderr, "ERROR: Divu(2264, 31)=%d, want %d\n", divu, 73); - return 1; - } - // test.bash looks for "PASS" to ensure this program has reached the end. - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcshared/testdata/main1.c b/misc/cgo/testcshared/testdata/main1.c deleted file mode 100644 index 420dd1ea97..0000000000 --- a/misc/cgo/testcshared/testdata/main1.c +++ /dev/null @@ -1,69 +0,0 @@ -// 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. - -#include <stdint.h> -#include <stdio.h> -#include <dlfcn.h> - -int check_int8(void* handle, const char* fname, int8_t want) { - int8_t (*fn)(); - fn = (int8_t (*)())dlsym(handle, fname); - if (!fn) { - fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror()); - return 1; - } - signed char ret = fn(); - if (ret != want) { - fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want); - return 1; - } - return 0; -} - -int check_int32(void* handle, const char* fname, int32_t want) { - int32_t (*fn)(); - fn = (int32_t (*)())dlsym(handle, fname); - if (!fn) { - fprintf(stderr, "ERROR: missing %s: %s\n", fname, dlerror()); - return 1; - } - int32_t ret = fn(); - if (ret != want) { - fprintf(stderr, "ERROR: %s=%d, want %d\n", fname, ret, want); - return 1; - } - return 0; -} - -// Tests libgo.so to export the following functions. -// int8_t DidInitRun() // returns true -// int8_t DidMainRun() // returns true -// int32_t FromPkg() // returns 1024 -int main(int argc, char** argv) { - void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL); - if (!handle) { - fprintf(stderr, "ERROR: failed to open the shared library: %s\n", - dlerror()); - return 2; - } - - int ret = 0; - ret = check_int8(handle, "DidInitRun", 1); - if (ret != 0) { - return ret; - } - - ret = check_int8(handle, "DidMainRun", 0); - if (ret != 0) { - return ret; - } - - ret = check_int32(handle, "FromPkg", 1024); - if (ret != 0) { - return ret; - } - // test.bash looks for "PASS" to ensure this program has reached the end. - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcshared/testdata/main2.c b/misc/cgo/testcshared/testdata/main2.c deleted file mode 100644 index f89bcca474..0000000000 --- a/misc/cgo/testcshared/testdata/main2.c +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#define fd (30) - -// Tests libgo2.so, which does not export any functions. -// Read a string from the file descriptor and print it. -int main(void) { - int i; - ssize_t n; - char buf[20]; - struct timespec ts; - - // The descriptor will be initialized in a thread, so we have to - // give a chance to get opened. - for (i = 0; i < 200; i++) { - n = read(fd, buf, sizeof buf); - if (n >= 0) - break; - if (errno != EBADF && errno != EINVAL) { - fprintf(stderr, "BUG: read: %s\n", strerror(errno)); - return 2; - } - - // An EBADF error means that the shared library has not opened the - // descriptor yet. - ts.tv_sec = 0; - ts.tv_nsec = 10000000; - nanosleep(&ts, NULL); - } - - if (n < 0) { - fprintf(stderr, "BUG: failed to read any data from pipe\n"); - return 2; - } - - if (n == 0) { - fprintf(stderr, "BUG: unexpected EOF\n"); - return 2; - } - - if (n == sizeof buf) { - n--; - } - buf[n] = '\0'; - printf("%s\n", buf); - return 0; -} diff --git a/misc/cgo/testcshared/testdata/main3.c b/misc/cgo/testcshared/testdata/main3.c deleted file mode 100644 index 49cc0558a0..0000000000 --- a/misc/cgo/testcshared/testdata/main3.c +++ /dev/null @@ -1,29 +0,0 @@ -// 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. - -#include <stdint.h> -#include <stdio.h> -#include <dlfcn.h> - -// Tests "main.main" is exported on android/arm, -// which golang.org/x/mobile/app depends on. -int main(int argc, char** argv) { - void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL); - if (!handle) { - fprintf(stderr, "ERROR: failed to open the shared library: %s\n", - dlerror()); - return 2; - } - - uintptr_t main_fn = (uintptr_t)dlsym(handle, "main.main"); - if (!main_fn) { - fprintf(stderr, "ERROR: missing main.main: %s\n", dlerror()); - return 2; - } - - // TODO(hyangah): check that main.main can run. - - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcshared/testdata/main4.c b/misc/cgo/testcshared/testdata/main4.c deleted file mode 100644 index 355cdefb01..0000000000 --- a/misc/cgo/testcshared/testdata/main4.c +++ /dev/null @@ -1,215 +0,0 @@ -// 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. - -// Test that a signal handler that uses up stack space does not crash -// if the signal is delivered to a thread running a goroutine. -// This is a lot like misc/cgo/testcarchive/main2.c. - -#include <setjmp.h> -#include <signal.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <unistd.h> -#include <sched.h> -#include <time.h> -#include <dlfcn.h> - -static void die(const char* msg) { - perror(msg); - exit(EXIT_FAILURE); -} - -static volatile sig_atomic_t sigioSeen; - -// Use up some stack space. -static void recur(int i, char *p) { - char a[1024]; - - *p = '\0'; - if (i > 0) { - recur(i - 1, a); - } -} - -// Signal handler that uses up more stack space than a goroutine will have. -static void ioHandler(int signo, siginfo_t* info, void* ctxt) { - char a[1024]; - - recur(4, a); - sigioSeen = 1; -} - -static jmp_buf jmp; -static char* nullPointer; - -// Signal handler for SIGSEGV on a C thread. -static void segvHandler(int signo, siginfo_t* info, void* ctxt) { - sigset_t mask; - int i; - - if (sigemptyset(&mask) < 0) { - die("sigemptyset"); - } - if (sigaddset(&mask, SIGSEGV) < 0) { - die("sigaddset"); - } - i = sigprocmask(SIG_UNBLOCK, &mask, NULL); - if (i != 0) { - fprintf(stderr, "sigprocmask: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - // Don't try this at home. - longjmp(jmp, signo); - - // We should never get here. - abort(); -} - -int main(int argc, char** argv) { - int verbose; - struct sigaction sa; - void* handle; - void (*fn)(void); - sigset_t mask; - int i; - struct timespec ts; - - verbose = argc > 2; - setvbuf(stdout, NULL, _IONBF, 0); - - // Call setsid so that we can use kill(0, SIGIO) below. - // Don't check the return value so that this works both from - // a job control shell and from a shell script. - setsid(); - - if (verbose) { - printf("calling sigaction\n"); - } - - memset(&sa, 0, sizeof sa); - sa.sa_sigaction = ioHandler; - if (sigemptyset(&sa.sa_mask) < 0) { - die("sigemptyset"); - } - sa.sa_flags = SA_SIGINFO; - if (sigaction(SIGIO, &sa, NULL) < 0) { - die("sigaction"); - } - - sa.sa_sigaction = segvHandler; - if (sigaction(SIGSEGV, &sa, NULL) < 0 || sigaction(SIGBUS, &sa, NULL) < 0) { - die("sigaction"); - } - - if (verbose) { - printf("calling dlopen\n"); - } - - handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL); - if (handle == NULL) { - fprintf(stderr, "%s\n", dlerror()); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling dlsym\n"); - } - - // Start some goroutines. - fn = (void(*)(void))dlsym(handle, "RunGoroutines"); - if (fn == NULL) { - fprintf(stderr, "%s\n", dlerror()); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling RunGoroutines\n"); - } - - fn(); - - // Block SIGIO in this thread to make it more likely that it - // will be delivered to a goroutine. - - if (verbose) { - printf("calling pthread_sigmask\n"); - } - - if (sigemptyset(&mask) < 0) { - die("sigemptyset"); - } - if (sigaddset(&mask, SIGIO) < 0) { - die("sigaddset"); - } - i = pthread_sigmask(SIG_BLOCK, &mask, NULL); - if (i != 0) { - fprintf(stderr, "pthread_sigmask: %s\n", strerror(i)); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling kill\n"); - } - - if (kill(0, SIGIO) < 0) { - die("kill"); - } - - if (verbose) { - printf("waiting for sigioSeen\n"); - } - - // Wait until the signal has been delivered. - i = 0; - while (!sigioSeen) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for signal\n"); - exit(EXIT_FAILURE); - } - } - - if (verbose) { - printf("calling setjmp\n"); - } - - // Test that a SIGSEGV on this thread is delivered to us. - if (setjmp(jmp) == 0) { - if (verbose) { - printf("triggering SIGSEGV\n"); - } - - *nullPointer = '\0'; - - fprintf(stderr, "continued after address error\n"); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling dlsym\n"); - } - - // Make sure that a SIGSEGV in Go causes a run-time panic. - fn = (void (*)(void))dlsym(handle, "TestSEGV"); - if (fn == NULL) { - fprintf(stderr, "%s\n", dlerror()); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling TestSEGV\n"); - } - - fn(); - - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcshared/testdata/main5.c b/misc/cgo/testcshared/testdata/main5.c deleted file mode 100644 index 1bc99101d7..0000000000 --- a/misc/cgo/testcshared/testdata/main5.c +++ /dev/null @@ -1,199 +0,0 @@ -// 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. - -// Test that a signal handler works in non-Go code when using -// os/signal.Notify. -// This is a lot like misc/cgo/testcarchive/main3.c. - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <sched.h> -#include <dlfcn.h> - -static void die(const char* msg) { - perror(msg); - exit(EXIT_FAILURE); -} - -static volatile sig_atomic_t sigioSeen; - -static void ioHandler(int signo, siginfo_t* info, void* ctxt) { - sigioSeen = 1; -} - -int main(int argc, char** argv) { - int verbose; - struct sigaction sa; - void* handle; - void (*fn1)(void); - int (*sawSIGIO)(void); - int i; - struct timespec ts; - - verbose = argc > 2; - setvbuf(stdout, NULL, _IONBF, 0); - - if (verbose) { - printf("calling sigaction\n"); - } - - memset(&sa, 0, sizeof sa); - sa.sa_sigaction = ioHandler; - if (sigemptyset(&sa.sa_mask) < 0) { - die("sigemptyset"); - } - sa.sa_flags = SA_SIGINFO; - if (sigaction(SIGIO, &sa, NULL) < 0) { - die("sigaction"); - } - - if (verbose) { - printf("calling dlopen\n"); - } - - handle = dlopen(argv[1], RTLD_NOW | RTLD_GLOBAL); - if (handle == NULL) { - fprintf(stderr, "%s\n", dlerror()); - exit(EXIT_FAILURE); - } - - // At this point there should not be a Go signal handler - // installed for SIGIO. - - if (verbose) { - printf("raising SIGIO\n"); - } - - if (raise(SIGIO) < 0) { - die("raise"); - } - - if (verbose) { - printf("waiting for sigioSeen\n"); - } - - // Wait until the signal has been delivered. - i = 0; - while (!sigioSeen) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for signal\n"); - exit(EXIT_FAILURE); - } - } - - sigioSeen = 0; - - // Tell the Go code to catch SIGIO. - - if (verbose) { - printf("calling dlsym\n"); - } - - fn1 = (void(*)(void))dlsym(handle, "CatchSIGIO"); - if (fn1 == NULL) { - fprintf(stderr, "%s\n", dlerror()); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling CatchSIGIO\n"); - } - - fn1(); - - if (verbose) { - printf("raising SIGIO\n"); - } - - if (raise(SIGIO) < 0) { - die("raise"); - } - - if (verbose) { - printf("calling dlsym\n"); - } - - // Check that the Go code saw SIGIO. - sawSIGIO = (int (*)(void))dlsym(handle, "SawSIGIO"); - if (sawSIGIO == NULL) { - fprintf(stderr, "%s\n", dlerror()); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling SawSIGIO\n"); - } - - if (!sawSIGIO()) { - fprintf(stderr, "Go handler did not see SIGIO\n"); - exit(EXIT_FAILURE); - } - - if (sigioSeen != 0) { - fprintf(stderr, "C handler saw SIGIO when only Go handler should have\n"); - exit(EXIT_FAILURE); - } - - // Tell the Go code to stop catching SIGIO. - - if (verbose) { - printf("calling dlsym\n"); - } - - fn1 = (void(*)(void))dlsym(handle, "ResetSIGIO"); - if (fn1 == NULL) { - fprintf(stderr, "%s\n", dlerror()); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("calling ResetSIGIO\n"); - } - - fn1(); - - if (verbose) { - printf("raising SIGIO\n"); - } - - if (raise(SIGIO) < 0) { - die("raise"); - } - - if (verbose) { - printf("calling SawSIGIO\n"); - } - - if (sawSIGIO()) { - fprintf(stderr, "Go handler saw SIGIO after Reset\n"); - exit(EXIT_FAILURE); - } - - if (verbose) { - printf("waiting for sigioSeen\n"); - } - - // Wait until the signal has been delivered. - i = 0; - while (!sigioSeen) { - ts.tv_sec = 0; - ts.tv_nsec = 1000000; - nanosleep(&ts, NULL); - i++; - if (i > 5000) { - fprintf(stderr, "looping too long waiting for signal\n"); - exit(EXIT_FAILURE); - } - } - - printf("PASS\n"); - return 0; -} diff --git a/misc/cgo/testcshared/testdata/p/p.go b/misc/cgo/testcshared/testdata/p/p.go deleted file mode 100644 index 0f02cf3ce6..0000000000 --- a/misc/cgo/testcshared/testdata/p/p.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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 p - -import "C" - -//export FromPkg -func FromPkg() int32 { return 1024 } - -//export Divu -func Divu(a, b uint32) uint32 { return a / b } diff --git a/misc/cgo/testgodefs/testdata/anonunion.go b/misc/cgo/testgodefs/testdata/anonunion.go deleted file mode 100644 index 2c86c5c29e..0000000000 --- a/misc/cgo/testgodefs/testdata/anonunion.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -//go:build ignore - -package main - -// This file tests that when cgo -godefs sees a struct with a field -// that is an anonymous union, the first field in the union is -// promoted to become a field of the struct. See issue 6677 for -// background. - -/* -typedef struct { - union { - long l; - int c; - }; -} t; -*/ -import "C" - -// Input for cgo -godefs. - -type T C.t diff --git a/misc/cgo/testgodefs/testdata/bitfields.go b/misc/cgo/testgodefs/testdata/bitfields.go deleted file mode 100644 index 431ffc0696..0000000000 --- a/misc/cgo/testgodefs/testdata/bitfields.go +++ /dev/null @@ -1,31 +0,0 @@ -// 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. - -//go:build ignore - -package main - -// This file tests that we don't generate an incorrect field location -// for a bitfield that appears aligned. - -/* -struct bitfields { - unsigned int B1 : 5; - unsigned int B2 : 1; - unsigned int B3 : 1; - unsigned int B4 : 1; - unsigned int Short1 : 16; // misaligned on 8 bit boundary - unsigned int B5 : 1; - unsigned int B6 : 1; - unsigned int B7 : 1; - unsigned int B8 : 1; - unsigned int B9 : 1; - unsigned int B10 : 3; - unsigned int Short2 : 16; // alignment is OK - unsigned int Short3 : 16; // alignment is OK -}; -*/ -import "C" - -type bitfields C.struct_bitfields diff --git a/misc/cgo/testgodefs/testdata/fieldtypedef.go b/misc/cgo/testgodefs/testdata/fieldtypedef.go deleted file mode 100644 index b0c507477f..0000000000 --- a/misc/cgo/testgodefs/testdata/fieldtypedef.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserve d. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build ignore - -package main - -/* -struct S1 { int f1; }; -struct S2 { struct S1 s1; }; -typedef struct S1 S1Type; -typedef struct S2 S2Type; -*/ -import "C" - -type S1 C.S1Type -type S2 C.S2Type diff --git a/misc/cgo/testgodefs/testdata/issue37479.go b/misc/cgo/testgodefs/testdata/issue37479.go deleted file mode 100644 index d54531045f..0000000000 --- a/misc/cgo/testgodefs/testdata/issue37479.go +++ /dev/null @@ -1,33 +0,0 @@ -// 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. - -//go:build ignore - -package main - -/* -typedef struct A A; - -typedef struct { - struct A *next; - struct A **prev; -} N; - -struct A -{ - N n; -}; - -typedef struct B -{ - A* a; -} B; -*/ -import "C" - -type N C.N - -type A C.A - -type B C.B diff --git a/misc/cgo/testgodefs/testdata/issue37621.go b/misc/cgo/testgodefs/testdata/issue37621.go deleted file mode 100644 index 655e8ae465..0000000000 --- a/misc/cgo/testgodefs/testdata/issue37621.go +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -//go:build ignore - -package main - -/* -struct tt { - long long a; - long long b; -}; - -struct s { - struct tt ts[3]; -}; -*/ -import "C" - -type TT C.struct_tt - -type S C.struct_s diff --git a/misc/cgo/testgodefs/testdata/issue38649.go b/misc/cgo/testgodefs/testdata/issue38649.go deleted file mode 100644 index 78b5f78edd..0000000000 --- a/misc/cgo/testgodefs/testdata/issue38649.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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. - -//go:build ignore - -package main - -/* -struct Issue38649 { int x; }; -#define issue38649 struct Issue38649 -*/ -import "C" - -type issue38649 C.issue38649 diff --git a/misc/cgo/testgodefs/testdata/issue39534.go b/misc/cgo/testgodefs/testdata/issue39534.go deleted file mode 100644 index af730e98d9..0000000000 --- a/misc/cgo/testgodefs/testdata/issue39534.go +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -//go:build ignore - -package main - -// enum { ENUMVAL = 0x1 }; -import "C" - -const ENUMVAL = C.ENUMVAL diff --git a/misc/cgo/testgodefs/testdata/issue48396.go b/misc/cgo/testgodefs/testdata/issue48396.go deleted file mode 100644 index 81dd2feb80..0000000000 --- a/misc/cgo/testgodefs/testdata/issue48396.go +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -//go:build ignore - -package main - -/* -// from <linux/kcm.h> -struct issue48396 { - int fd; - int bpf_fd; -}; -*/ -import "C" - -type Issue48396 C.struct_issue48396 diff --git a/misc/cgo/testgodefs/testdata/issue8478.go b/misc/cgo/testgodefs/testdata/issue8478.go deleted file mode 100644 index f4ef164bda..0000000000 --- a/misc/cgo/testgodefs/testdata/issue8478.go +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -//go:build ignore - -package main - -// Issue 8478. Test that void* is consistently mapped to *byte. - -/* -typedef struct { - void *p; - void **q; - void ***r; -} s; -*/ -import "C" - -type Issue8478 C.s diff --git a/misc/cgo/testgodefs/testdata/main.go b/misc/cgo/testgodefs/testdata/main.go deleted file mode 100644 index 5c670f3d32..0000000000 --- a/misc/cgo/testgodefs/testdata/main.go +++ /dev/null @@ -1,57 +0,0 @@ -// 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 main - -import ( - "fmt" - "os" - "reflect" -) - -// Test that the struct field in anonunion.go was promoted. -var v1 T -var v2 = v1.L - -// Test that P, Q, and R all point to byte. -var v3 = Issue8478{P: (*byte)(nil), Q: (**byte)(nil), R: (***byte)(nil)} - -// Test that N, A and B are fully defined -var v4 = N{} -var v5 = A{} -var v6 = B{} - -// Test that S is fully defined -var v7 = S{} - -// Test that #define'd type is fully defined -var _ = issue38649{X: 0} - -// Test that prefixes do not cause duplicate field names. -var _ = Issue48396{Fd: 1, Bpf_fd: 2} - -func main() { - pass := true - - // The Go translation of bitfields should not have any of the - // bitfield types. The order in which bitfields are laid out - // in memory is implementation defined, so we can't easily - // know how a bitfield should correspond to a Go type, even if - // it appears to be aligned correctly. - bitfieldType := reflect.TypeOf(bitfields{}) - check := func(name string) { - _, ok := bitfieldType.FieldByName(name) - if ok { - fmt.Fprintf(os.Stderr, "found unexpected bitfields field %s\n", name) - pass = false - } - } - check("Short1") - check("Short2") - check("Short3") - - if !pass { - os.Exit(1) - } -} diff --git a/misc/cgo/testgodefs/testgodefs_test.go b/misc/cgo/testgodefs/testgodefs_test.go deleted file mode 100644 index d03769ea87..0000000000 --- a/misc/cgo/testgodefs/testgodefs_test.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2019 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 testgodefs - -import ( - "bytes" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "testing" -) - -// We are testing cgo -godefs, which translates Go files that use -// import "C" into Go files with Go definitions of types defined in the -// import "C" block. Add more tests here. -var filePrefixes = []string{ - "anonunion", - "bitfields", - "issue8478", - "fieldtypedef", - "issue37479", - "issue37621", - "issue38649", - "issue39534", - "issue48396", -} - -func TestGoDefs(t *testing.T) { - testdata, err := filepath.Abs("testdata") - if err != nil { - t.Fatal(err) - } - - gopath, err := os.MkdirTemp("", "testgodefs-gopath") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(gopath) - - dir := filepath.Join(gopath, "src", "testgodefs") - if err := os.MkdirAll(dir, 0755); err != nil { - t.Fatal(err) - } - - for _, fp := range filePrefixes { - cmd := exec.Command("go", "tool", "cgo", - "-godefs", - "-srcdir", testdata, - "-objdir", dir, - fp+".go") - cmd.Stderr = new(bytes.Buffer) - - out, err := cmd.Output() - if err != nil { - t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) - } - - fn := fp + "_defs.go" - if err := os.WriteFile(filepath.Join(dir, fn), out, 0644); err != nil { - t.Fatal(err) - } - - // Verify that command line arguments are not rewritten in the generated comment, - // see go.dev/issue/52063 - hasGeneratedByComment := false - for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") { - cgoExe := "cgo" - if runtime.GOOS == "windows" { - cgoExe = "cgo.exe" - } - if !strings.HasPrefix(line, "// "+cgoExe+" -godefs") { - continue - } - if want := "// " + cgoExe + " " + strings.Join(cmd.Args[3:], " "); line != want { - t.Errorf("%s: got generated comment %q, want %q", fn, line, want) - } - hasGeneratedByComment = true - break - } - - if !hasGeneratedByComment { - t.Errorf("%s: comment with generating cgo -godefs command not found", fn) - } - } - - main, err := os.ReadFile(filepath.Join("testdata", "main.go")) - if err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil { - t.Fatal(err) - } - - if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil { - t.Fatal(err) - } - - // Use 'go run' to build and run the resulting binary in a single step, - // instead of invoking 'go build' and the resulting binary separately, so that - // this test can pass on mobile builders, which do not copy artifacts back - // from remote invocations. - cmd := exec.Command("go", "run", ".") - cmd.Env = append(os.Environ(), "GOPATH="+gopath) - cmd.Dir = dir - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("%s [%s]: %v\n%s", strings.Join(cmd.Args, " "), dir, err, out) - } -} diff --git a/misc/cgo/testplugin/altpath/testdata/common/common.go b/misc/cgo/testplugin/altpath/testdata/common/common.go deleted file mode 100644 index 505ba02b1f..0000000000 --- a/misc/cgo/testplugin/altpath/testdata/common/common.go +++ /dev/null @@ -1,11 +0,0 @@ -// 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 common - -var X int - -func init() { - X = 4 -} diff --git a/misc/cgo/testplugin/altpath/testdata/plugin-mismatch/main.go b/misc/cgo/testplugin/altpath/testdata/plugin-mismatch/main.go deleted file mode 100644 index bfb4ba45aa..0000000000 --- a/misc/cgo/testplugin/altpath/testdata/plugin-mismatch/main.go +++ /dev/null @@ -1,17 +0,0 @@ -// 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 main - -// // No C code required. -import "C" - -// The common package imported here does not match the common package -// imported by plugin1. A program that attempts to load plugin1 and -// plugin-mismatch should produce an error. -import "testplugin/common" - -func ReadCommonX() int { - return common.X -} diff --git a/misc/cgo/testplugin/overlaydir_test.go b/misc/cgo/testplugin/overlaydir_test.go deleted file mode 100644 index e2c32d83ce..0000000000 --- a/misc/cgo/testplugin/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 plugin_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/testplugin/plugin_test.go b/misc/cgo/testplugin/plugin_test.go deleted file mode 100644 index 8960694351..0000000000 --- a/misc/cgo/testplugin/plugin_test.go +++ /dev/null @@ -1,354 +0,0 @@ -// Copyright 2019 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 plugin_test - -import ( - "bytes" - "context" - "flag" - "fmt" - "log" - "os" - "os/exec" - "path/filepath" - "strings" - "testing" - "time" -) - -var gcflags string = os.Getenv("GO_GCFLAGS") -var goroot string - -func TestMain(m *testing.M) { - flag.Parse() - if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" { - fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n") - os.Exit(0) - } - log.SetFlags(log.Lshortfile) - 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 { - cwd, err := os.Getwd() - if err != nil { - log.Fatal(err) - } - goroot = filepath.Join(cwd, "../../..") - - // Copy testdata into GOPATH/src/testplugin, along with a go.mod file - // declaring the same path. - - 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") - for srcRoot, dstRoot := range map[string]string{ - "testdata": modRoot, - filepath.Join("altpath", "testdata"): altRoot, - } { - if err := overlayDir(dstRoot, srcRoot); err != nil { - log.Panic(err) - } - 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") - - os.Setenv("GOPATH", GOPATH) - if err := os.Chdir(modRoot); err != nil { - log.Panic(err) - } else { - prettyPrintf("cd %s\n", modRoot) - } - os.Setenv("PWD", modRoot) - - os.Setenv("LD_LIBRARY_PATH", modRoot) - - goCmd(nil, "build", "-buildmode=plugin", "./plugin1") - goCmd(nil, "build", "-buildmode=plugin", "./plugin2") - so, err := os.ReadFile("plugin2.so") - if err != nil { - log.Panic(err) - } - 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") - goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed2.so", "./unnamed2/main.go") - goCmd(nil, "build", "-o", "host.exe", "./host") - - return m.Run() -} - -func goCmd(t *testing.T, op string, args ...string) string { - if t != nil { - t.Helper() - } - var flags []string - if op != "tool" { - flags = []string{"-gcflags", gcflags} - } - return run(t, filepath.Join(goroot, "bin", "go"), append(append([]string{op}, flags...), 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 { - if t == nil { - log.Panicf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) - } else { - t.Helper() - t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) - } - } - - return string(bytes.TrimSpace(out)) -} - -func TestDWARFSections(t *testing.T) { - // test that DWARF sections are emitted for plugins and programs importing "plugin" - goCmd(t, "run", "./checkdwarf/main.go", "plugin2.so", "plugin2.UnexportedNameReuse") - goCmd(t, "run", "./checkdwarf/main.go", "./host.exe", "main.main") -} - -func TestBuildID(t *testing.T) { - // check that plugin has build ID. - b := goCmd(t, "tool", "buildid", "plugin1.so") - if len(b) == 0 { - t.Errorf("build id not found") - } -} - -func TestRunHost(t *testing.T) { - run(t, "./host.exe") -} - -func TestUniqueTypesAndItabs(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "./iface_a") - goCmd(t, "build", "-buildmode=plugin", "./iface_b") - goCmd(t, "build", "-o", "iface.exe", "./iface") - run(t, "./iface.exe") -} - -func TestIssue18676(t *testing.T) { - // make sure we don't add the same itab twice. - // The buggy code hangs forever, so use a timeout to check for that. - goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./issue18676/plugin.go") - goCmd(t, "build", "-o", "issue18676.exe", "./issue18676/main.go") - - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - cmd := exec.CommandContext(ctx, "./issue18676.exe") - out, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out) - } -} - -func TestIssue19534(t *testing.T) { - // Test that we can load a plugin built in a path with non-alpha characters. - goCmd(t, "build", "-buildmode=plugin", "-gcflags=-p=issue.19534", "-ldflags=-pluginpath=issue.19534", "-o", "plugin.so", "./issue19534/plugin.go") - goCmd(t, "build", "-o", "issue19534.exe", "./issue19534/main.go") - run(t, "./issue19534.exe") -} - -func TestIssue18584(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./issue18584/plugin.go") - goCmd(t, "build", "-o", "issue18584.exe", "./issue18584/main.go") - run(t, "./issue18584.exe") -} - -func TestIssue19418(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-ldflags=-X main.Val=linkstr", "-o", "plugin.so", "./issue19418/plugin.go") - goCmd(t, "build", "-o", "issue19418.exe", "./issue19418/main.go") - run(t, "./issue19418.exe") -} - -func TestIssue19529(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./issue19529/plugin.go") -} - -func TestIssue22175(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "issue22175_plugin1.so", "./issue22175/plugin1.go") - goCmd(t, "build", "-buildmode=plugin", "-o", "issue22175_plugin2.so", "./issue22175/plugin2.go") - goCmd(t, "build", "-o", "issue22175.exe", "./issue22175/main.go") - run(t, "./issue22175.exe") -} - -func TestIssue22295(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "issue.22295.so", "./issue22295.pkg") - goCmd(t, "build", "-o", "issue22295.exe", "./issue22295.pkg/main.go") - run(t, "./issue22295.exe") -} - -func TestIssue24351(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "issue24351.so", "./issue24351/plugin.go") - goCmd(t, "build", "-o", "issue24351.exe", "./issue24351/main.go") - run(t, "./issue24351.exe") -} - -func TestIssue25756(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "life.so", "./issue25756/plugin") - goCmd(t, "build", "-o", "issue25756.exe", "./issue25756/main.go") - // Fails intermittently, but 20 runs should cause the failure - for n := 20; n > 0; n-- { - t.Run(fmt.Sprint(n), func(t *testing.T) { - t.Parallel() - run(t, "./issue25756.exe") - }) - } -} - -// Test with main using -buildmode=pie with plugin for issue #43228 -func TestIssue25756pie(t *testing.T) { - 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") - goCmd(t, "build", "-o", "method.exe", "./method/main.go") - run(t, "./method.exe") -} - -func TestMethod2(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "method2.so", "./method2/plugin.go") - goCmd(t, "build", "-o", "method2.exe", "./method2/main.go") - run(t, "./method2.exe") -} - -func TestMethod3(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "method3.so", "./method3/plugin.go") - goCmd(t, "build", "-o", "method3.exe", "./method3/main.go") - run(t, "./method3.exe") -} - -func TestIssue44956(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p1.so", "./issue44956/plugin1.go") - goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p2.so", "./issue44956/plugin2.go") - goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go") - run(t, "./issue44956.exe") -} - -func TestIssue52937(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "issue52937.so", "./issue52937/main.go") -} - -func TestIssue53989(t *testing.T) { - goCmd(t, "build", "-buildmode=plugin", "-o", "issue53989.so", "./issue53989/plugin.go") - goCmd(t, "build", "-o", "issue53989.exe", "./issue53989/main.go") - run(t, "./issue53989.exe") -} - -func TestForkExec(t *testing.T) { - // Issue 38824: importing the plugin package causes it hang in forkExec on darwin. - - 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 - } - } - done <- 1 - }() - select { - case <-done: - case <-time.After(5 * time.Minute): - cmd.Process.Kill() - t.Fatalf("subprocess hang") - } -} diff --git a/misc/cgo/testplugin/testdata/checkdwarf/main.go b/misc/cgo/testplugin/testdata/checkdwarf/main.go deleted file mode 100644 index 7886c834e7..0000000000 --- a/misc/cgo/testplugin/testdata/checkdwarf/main.go +++ /dev/null @@ -1,106 +0,0 @@ -// 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. - -// Usage: -// -// checkdwarf <exe> <suffix> -// -// Opens <exe>, which must be an executable or a library and checks that -// there is an entry in .debug_info whose name ends in <suffix> - -package main - -import ( - "debug/dwarf" - "debug/elf" - "debug/macho" - "debug/pe" - "fmt" - "os" - "strings" -) - -func usage() { - fmt.Fprintf(os.Stderr, "checkdwarf executable-or-library DIE-suffix\n") -} - -type dwarfer interface { - DWARF() (*dwarf.Data, error) -} - -func openElf(path string) dwarfer { - exe, err := elf.Open(path) - if err != nil { - return nil - } - return exe -} - -func openMacho(path string) dwarfer { - exe, err := macho.Open(path) - if err != nil { - return nil - } - return exe -} - -func openPE(path string) dwarfer { - exe, err := pe.Open(path) - if err != nil { - return nil - } - return exe -} - -func main() { - if len(os.Args) != 3 { - usage() - } - - exePath := os.Args[1] - dieSuffix := os.Args[2] - - var exe dwarfer - - for _, openfn := range []func(string) dwarfer{openMacho, openPE, openElf} { - exe = openfn(exePath) - if exe != nil { - break - } - } - - if exe == nil { - fmt.Fprintf(os.Stderr, "could not open %s\n", exePath) - os.Exit(1) - } - - data, err := exe.DWARF() - if err != nil { - fmt.Fprintf(os.Stderr, "%s: error opening DWARF: %v\n", exePath, err) - os.Exit(1) - } - - rdr := data.Reader() - for { - e, err := rdr.Next() - if err != nil { - fmt.Fprintf(os.Stderr, "%s: error reading DWARF: %v\n", exePath, err) - os.Exit(1) - } - if e == nil { - break - } - name, hasname := e.Val(dwarf.AttrName).(string) - if !hasname { - continue - } - if strings.HasSuffix(name, dieSuffix) { - // found - os.Exit(0) - } - } - - fmt.Fprintf(os.Stderr, "%s: no entry with a name ending in %q was found\n", exePath, dieSuffix) - os.Exit(1) -} diff --git a/misc/cgo/testplugin/testdata/common/common.go b/misc/cgo/testplugin/testdata/common/common.go deleted file mode 100644 index b064e6bccf..0000000000 --- a/misc/cgo/testplugin/testdata/common/common.go +++ /dev/null @@ -1,11 +0,0 @@ -// 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 common - -var X int - -func init() { - X = 3 -} diff --git a/misc/cgo/testplugin/testdata/forkexec/main.go b/misc/cgo/testplugin/testdata/forkexec/main.go deleted file mode 100644 index 3169ff5f04..0000000000 --- a/misc/cgo/testplugin/testdata/forkexec/main.go +++ /dev/null @@ -1,30 +0,0 @@ -// 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. - -package main - -import ( - "os" - "os/exec" - _ "plugin" - "sync" -) - -func main() { - if os.Args[1] != "1" { - return - } - - var wg sync.WaitGroup - for i := 0; i < 8; i++ { - wg.Add(1) - go func() { - defer wg.Done() - // does not matter what we exec, just exec itself - cmd := exec.Command("./forkexec.exe", "0") - cmd.Run() - }() - } - wg.Wait() -} diff --git a/misc/cgo/testplugin/testdata/host/host.go b/misc/cgo/testplugin/testdata/host/host.go deleted file mode 100644 index a3799328cd..0000000000 --- a/misc/cgo/testplugin/testdata/host/host.go +++ /dev/null @@ -1,176 +0,0 @@ -// 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 main - -import ( - "fmt" - "log" - "path/filepath" - "plugin" - "strings" - - "testplugin/common" -) - -func init() { - common.X *= 5 -} - -// testUnnamed tests that two plugins built with .go files passed on -// the command line do not have overlapping symbols. That is, -// unnamed1.so/FuncInt and unnamed2.so/FuncInt should be distinct functions. -func testUnnamed() { - p, err := plugin.Open("unnamed1.so") - if err != nil { - log.Fatalf(`plugin.Open("unnamed1.so"): %v`, err) - } - fn, err := p.Lookup("FuncInt") - if err != nil { - log.Fatalf(`unnamed1.so: Lookup("FuncInt") failed: %v`, err) - } - if got, want := fn.(func() int)(), 1; got != want { - log.Fatalf("unnamed1.so: FuncInt()=%d, want %d", got, want) - } - - p, err = plugin.Open("unnamed2.so") - if err != nil { - log.Fatalf(`plugin.Open("unnamed2.so"): %v`, err) - } - fn, err = p.Lookup("FuncInt") - if err != nil { - log.Fatalf(`unnamed2.so: Lookup("FuncInt") failed: %v`, err) - } - if got, want := fn.(func() int)(), 2; got != want { - log.Fatalf("unnamed2.so: FuncInt()=%d, want %d", got, want) - } -} - -func main() { - if got, want := common.X, 3*5; got != want { - log.Fatalf("before plugin load common.X=%d, want %d", got, want) - } - - p, err := plugin.Open("plugin1.so") - if err != nil { - log.Fatalf("plugin.Open failed: %v", err) - } - - const wantX = 3 * 5 * 7 - if got := common.X; got != wantX { - log.Fatalf("after plugin load common.X=%d, want %d", got, wantX) - } - - seven, err := p.Lookup("Seven") - if err != nil { - log.Fatalf(`Lookup("Seven") failed: %v`, err) - } - if got, want := *seven.(*int), 7; got != want { - log.Fatalf("plugin1.Seven=%d, want %d", got, want) - } - - readFunc, err := p.Lookup("ReadCommonX") - if err != nil { - log.Fatalf(`plugin1.Lookup("ReadCommonX") failed: %v`, err) - } - if got := readFunc.(func() int)(); got != wantX { - log.Fatalf("plugin1.ReadCommonX()=%d, want %d", got, wantX) - } - - // sub/plugin1.so is a different plugin with the same name as - // the already loaded plugin. It also depends on common. Test - // that we can load the different plugin, it is actually - // different, and that it sees the same common package. - subpPath, err := filepath.Abs("sub/plugin1.so") - if err != nil { - log.Fatalf("filepath.Abs(%q) failed: %v", subpPath, err) - } - subp, err := plugin.Open(subpPath) - if err != nil { - log.Fatalf("plugin.Open(%q) failed: %v", subpPath, err) - } - - funcVar, err := subp.Lookup("FuncVar") - if err != nil { - log.Fatalf(`sub/plugin1.Lookup("FuncVar") failed: %v`, err) - } - called := false - *funcVar.(*func()) = func() { - called = true - } - - readFunc, err = subp.Lookup("ReadCommonX") - if err != nil { - log.Fatalf(`sub/plugin1.Lookup("ReadCommonX") failed: %v`, err) - } - if got := readFunc.(func() int)(); got != wantX { - log.Fatalf("sub/plugin1.ReadCommonX()=%d, want %d", got, wantX) - } - if !called { - log.Fatal("calling ReadCommonX did not call FuncVar") - } - - subf, err := subp.Lookup("F") - if err != nil { - log.Fatalf(`sub/plugin1.Lookup("F") failed: %v`, err) - } - if gotf := subf.(func() int)(); gotf != 17 { - log.Fatalf(`sub/plugin1.F()=%d, want 17`, gotf) - } - f, err := p.Lookup("F") - if err != nil { - log.Fatalf(`plugin1.Lookup("F") failed: %v`, err) - } - if gotf := f.(func() int)(); gotf != 3 { - log.Fatalf(`plugin1.F()=%d, want 17`, gotf) - } - - p2, err := plugin.Open("plugin2.so") - if err != nil { - log.Fatalf("plugin.Open failed: %v", err) - } - // Check that plugin2's init function was called, and - // that it modifies the same global variable as the host. - if got, want := common.X, 2; got != want { - log.Fatalf("after loading plugin2, common.X=%d, want %d", got, want) - } - - _, err = plugin.Open("plugin2-dup.so") - if err == nil { - log.Fatal(`plugin.Open("plugin2-dup.so"): duplicate open should have failed`) - } - if s := err.Error(); !strings.Contains(s, "already loaded") { - log.Fatal(`plugin.Open("plugin2.so"): error does not mention "already loaded"`) - } - - _, err = plugin.Open("plugin-mismatch.so") - if err == nil { - log.Fatal(`plugin.Open("plugin-mismatch.so"): should have failed`) - } - if s := err.Error(); !strings.Contains(s, "different version") { - log.Fatalf(`plugin.Open("plugin-mismatch.so"): error does not mention "different version": %v`, s) - } - - _, err = plugin.Open("plugin2-dup.so") - if err == nil { - log.Fatal(`plugin.Open("plugin2-dup.so"): duplicate open after bad plugin should have failed`) - } - _, err = plugin.Open("plugin2.so") - if err != nil { - log.Fatalf(`plugin.Open("plugin2.so"): second open with same name failed: %v`, err) - } - - // Test that unexported types with the same names in - // different plugins do not interfere with each other. - // - // See Issue #21386. - UnexportedNameReuse, _ := p.Lookup("UnexportedNameReuse") - UnexportedNameReuse.(func())() - UnexportedNameReuse, _ = p2.Lookup("UnexportedNameReuse") - UnexportedNameReuse.(func())() - - testUnnamed() - - fmt.Println("PASS") -} diff --git a/misc/cgo/testplugin/testdata/iface/main.go b/misc/cgo/testplugin/testdata/iface/main.go deleted file mode 100644 index c04f28880f..0000000000 --- a/misc/cgo/testplugin/testdata/iface/main.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2017 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 - -import ( - "log" - "plugin" - - "testplugin/iface_i" -) - -func main() { - a, err := plugin.Open("iface_a.so") - if err != nil { - log.Fatalf(`plugin.Open("iface_a.so"): %v`, err) - } - b, err := plugin.Open("iface_b.so") - if err != nil { - log.Fatalf(`plugin.Open("iface_b.so"): %v`, err) - } - - af, err := a.Lookup("F") - if err != nil { - log.Fatalf(`a.Lookup("F") failed: %v`, err) - } - bf, err := b.Lookup("F") - if err != nil { - log.Fatalf(`b.Lookup("F") failed: %v`, err) - } - if af.(func() interface{})() != bf.(func() interface{})() { - panic("empty interfaces not equal") - } - - ag, err := a.Lookup("G") - if err != nil { - log.Fatalf(`a.Lookup("G") failed: %v`, err) - } - bg, err := b.Lookup("G") - if err != nil { - log.Fatalf(`b.Lookup("G") failed: %v`, err) - } - if ag.(func() iface_i.I)() != bg.(func() iface_i.I)() { - panic("nonempty interfaces not equal") - } -} diff --git a/misc/cgo/testplugin/testdata/iface_a/a.go b/misc/cgo/testplugin/testdata/iface_a/a.go deleted file mode 100644 index 357f7e827e..0000000000 --- a/misc/cgo/testplugin/testdata/iface_a/a.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 - -import "testplugin/iface_i" - -//go:noinline -func F() interface{} { - return (*iface_i.T)(nil) -} - -//go:noinline -func G() iface_i.I { - return (*iface_i.T)(nil) -} diff --git a/misc/cgo/testplugin/testdata/iface_b/b.go b/misc/cgo/testplugin/testdata/iface_b/b.go deleted file mode 100644 index 357f7e827e..0000000000 --- a/misc/cgo/testplugin/testdata/iface_b/b.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 - -import "testplugin/iface_i" - -//go:noinline -func F() interface{} { - return (*iface_i.T)(nil) -} - -//go:noinline -func G() iface_i.I { - return (*iface_i.T)(nil) -} diff --git a/misc/cgo/testplugin/testdata/iface_i/i.go b/misc/cgo/testplugin/testdata/iface_i/i.go deleted file mode 100644 index 31c80387c7..0000000000 --- a/misc/cgo/testplugin/testdata/iface_i/i.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 iface_i - -type I interface { - M() -} - -type T struct { -} - -func (t *T) M() { -} - -// *T implements I diff --git a/misc/cgo/testplugin/testdata/issue18584/main.go b/misc/cgo/testplugin/testdata/issue18584/main.go deleted file mode 100644 index c280fd4620..0000000000 --- a/misc/cgo/testplugin/testdata/issue18584/main.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 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 - -import "plugin" - -func main() { - p, err := plugin.Open("plugin.so") - if err != nil { - panic(err) - } - - sym, err := p.Lookup("G") - if err != nil { - panic(err) - } - g := sym.(func() bool) - if !g() { - panic("expected types to match, Issue #18584") - } -} diff --git a/misc/cgo/testplugin/testdata/issue18584/plugin.go b/misc/cgo/testplugin/testdata/issue18584/plugin.go deleted file mode 100644 index be0868d375..0000000000 --- a/misc/cgo/testplugin/testdata/issue18584/plugin.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2017 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 - -import "reflect" - -type C struct { -} - -func F(c *C) *C { - return nil -} - -func G() bool { - var c *C - return reflect.TypeOf(F).Out(0) == reflect.TypeOf(c) -} diff --git a/misc/cgo/testplugin/testdata/issue18676/dynamodbstreamsevt/definition.go b/misc/cgo/testplugin/testdata/issue18676/dynamodbstreamsevt/definition.go deleted file mode 100644 index 70fd054d08..0000000000 --- a/misc/cgo/testplugin/testdata/issue18676/dynamodbstreamsevt/definition.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2017 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 dynamodbstreamsevt - -import "encoding/json" - -var foo json.RawMessage - -type Event struct{} - -func (e *Event) Dummy() {} diff --git a/misc/cgo/testplugin/testdata/issue18676/main.go b/misc/cgo/testplugin/testdata/issue18676/main.go deleted file mode 100644 index 471f3d969c..0000000000 --- a/misc/cgo/testplugin/testdata/issue18676/main.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2017 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. - -// The bug happened like this: -// 1. The main binary adds an itab for *json.UnsupportedValueError / error -// (concrete type / interface type). This itab goes in hash bucket 0x111. -// 2. The plugin adds that same itab again. That makes a cycle in the itab -// chain rooted at hash bucket 0x111. -// 3. The main binary then asks for the itab for *dynamodbstreamsevt.Event / -// json.Unmarshaler. This itab happens to also live in bucket 0x111. -// The lookup code goes into an infinite loop searching for this itab. -// -// The code is carefully crafted so that the two itabs are both from the -// same bucket, and so that the second itab doesn't exist in -// the itab hashmap yet (so the entire linked list must be searched). -package main - -import ( - "encoding/json" - "plugin" - "testplugin/issue18676/dynamodbstreamsevt" -) - -func main() { - plugin.Open("plugin.so") - - var x interface{} = (*dynamodbstreamsevt.Event)(nil) - if _, ok := x.(json.Unmarshaler); !ok { - println("something") - } -} diff --git a/misc/cgo/testplugin/testdata/issue18676/plugin.go b/misc/cgo/testplugin/testdata/issue18676/plugin.go deleted file mode 100644 index e7fc74f777..0000000000 --- a/misc/cgo/testplugin/testdata/issue18676/plugin.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2017 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 - -import "C" - -import "testplugin/issue18676/dynamodbstreamsevt" - -func F(evt *dynamodbstreamsevt.Event) {} diff --git a/misc/cgo/testplugin/testdata/issue19418/main.go b/misc/cgo/testplugin/testdata/issue19418/main.go deleted file mode 100644 index 2ec9f9aaaa..0000000000 --- a/misc/cgo/testplugin/testdata/issue19418/main.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017 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 - -import ( - "fmt" - "os" - "plugin" -) - -func main() { - p, err := plugin.Open("plugin.so") - if err != nil { - panic(err) - } - - val, err := p.Lookup("Val") - if err != nil { - panic(err) - } - got := *val.(*string) - const want = "linkstr" - if got != want { - fmt.Fprintf(os.Stderr, "issue19418 value is %q, want %q\n", got, want) - os.Exit(2) - } -} diff --git a/misc/cgo/testplugin/testdata/issue19418/plugin.go b/misc/cgo/testplugin/testdata/issue19418/plugin.go deleted file mode 100644 index fe93b16143..0000000000 --- a/misc/cgo/testplugin/testdata/issue19418/plugin.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2017 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 - -var Val = "val-unset" diff --git a/misc/cgo/testplugin/testdata/issue19529/plugin.go b/misc/cgo/testplugin/testdata/issue19529/plugin.go deleted file mode 100644 index ad2df6cc7c..0000000000 --- a/misc/cgo/testplugin/testdata/issue19529/plugin.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -import ( - "reflect" -) - -type Foo struct { - Bar string `json:"Bar@baz,omitempty"` -} - -func F() { - println(reflect.TypeOf(Foo{}).Field(0).Tag) -} - -func main() {} diff --git a/misc/cgo/testplugin/testdata/issue19534/main.go b/misc/cgo/testplugin/testdata/issue19534/main.go deleted file mode 100644 index de263b6f0f..0000000000 --- a/misc/cgo/testplugin/testdata/issue19534/main.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2017 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 - -import "plugin" - -func main() { - p, err := plugin.Open("plugin.so") - if err != nil { - panic(err) - } - - sym, err := p.Lookup("Foo") - if err != nil { - panic(err) - } - f := sym.(func() int) - if f() != 42 { - panic("expected f() == 42") - } -} diff --git a/misc/cgo/testplugin/testdata/issue19534/plugin.go b/misc/cgo/testplugin/testdata/issue19534/plugin.go deleted file mode 100644 index 582d33305c..0000000000 --- a/misc/cgo/testplugin/testdata/issue19534/plugin.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2017 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 - -func Foo() int { - return 42 -} diff --git a/misc/cgo/testplugin/testdata/issue22175/main.go b/misc/cgo/testplugin/testdata/issue22175/main.go deleted file mode 100644 index 9be9bab9dc..0000000000 --- a/misc/cgo/testplugin/testdata/issue22175/main.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2017 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 - -import ( - "fmt" - "os" - "plugin" -) - -func main() { - p2, err := plugin.Open("issue22175_plugin1.so") - if err != nil { - panic(err) - } - f, err := p2.Lookup("F") - if err != nil { - panic(err) - } - got := f.(func() int)() - const want = 971 - if got != want { - fmt.Fprintf(os.Stderr, "issue22175: F()=%d, want %d", got, want) - os.Exit(1) - } -} diff --git a/misc/cgo/testplugin/testdata/issue22175/plugin1.go b/misc/cgo/testplugin/testdata/issue22175/plugin1.go deleted file mode 100644 index 5ae6cb631e..0000000000 --- a/misc/cgo/testplugin/testdata/issue22175/plugin1.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 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 - -import "plugin" - -func F() int { - p2, err := plugin.Open("issue22175_plugin2.so") - if err != nil { - panic(err) - } - g, err := p2.Lookup("G") - if err != nil { - panic(err) - } - return g.(func() int)() -} - -func main() {} diff --git a/misc/cgo/testplugin/testdata/issue22175/plugin2.go b/misc/cgo/testplugin/testdata/issue22175/plugin2.go deleted file mode 100644 index f387a192e6..0000000000 --- a/misc/cgo/testplugin/testdata/issue22175/plugin2.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2017 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 - -func G() int { return 971 } - -func main() {} diff --git a/misc/cgo/testplugin/testdata/issue22295.pkg/main.go b/misc/cgo/testplugin/testdata/issue22295.pkg/main.go deleted file mode 100644 index 44b2a2140e..0000000000 --- a/misc/cgo/testplugin/testdata/issue22295.pkg/main.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2017 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 ignore - -package main - -import ( - "log" - "plugin" -) - -func main() { - p, err := plugin.Open("issue.22295.so") - if err != nil { - log.Fatal(err) - } - f, err := p.Lookup("F") - if err != nil { - log.Fatal(err) - } - const want = 2503 - got := f.(func() int)() - if got != want { - log.Fatalf("got %d, want %d", got, want) - } -} diff --git a/misc/cgo/testplugin/testdata/issue22295.pkg/plugin.go b/misc/cgo/testplugin/testdata/issue22295.pkg/plugin.go deleted file mode 100644 index 46b08a405b..0000000000 --- a/misc/cgo/testplugin/testdata/issue22295.pkg/plugin.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 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 - -var f *int - -func init() { - f = new(int) - *f = 2503 -} - -func F() int { return *f } - -func main() {} diff --git a/misc/cgo/testplugin/testdata/issue24351/main.go b/misc/cgo/testplugin/testdata/issue24351/main.go deleted file mode 100644 index 4107adff7b..0000000000 --- a/misc/cgo/testplugin/testdata/issue24351/main.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -package main - -import "plugin" - -func main() { - p, err := plugin.Open("issue24351.so") - if err != nil { - panic(err) - } - f, err := p.Lookup("B") - if err != nil { - panic(err) - } - c := make(chan bool) - f.(func(chan bool))(c) - <-c -} diff --git a/misc/cgo/testplugin/testdata/issue24351/plugin.go b/misc/cgo/testplugin/testdata/issue24351/plugin.go deleted file mode 100644 index db17e0a609..0000000000 --- a/misc/cgo/testplugin/testdata/issue24351/plugin.go +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -package main - -import "fmt" - -func B(c chan bool) { - go func() { - fmt.Println(1.5) - c <- true - }() -} diff --git a/misc/cgo/testplugin/testdata/issue25756/main.go b/misc/cgo/testplugin/testdata/issue25756/main.go deleted file mode 100644 index 817daf42f6..0000000000 --- a/misc/cgo/testplugin/testdata/issue25756/main.go +++ /dev/null @@ -1,52 +0,0 @@ -// 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. - -// Run the game of life in C using Go for parallelization. - -package main - -import ( - "flag" - "fmt" - "plugin" -) - -const MAXDIM = 100 - -var dim = flag.Int("dim", 16, "board dimensions") -var gen = flag.Int("gen", 10, "generations") - -func main() { - flag.Parse() - - var a [MAXDIM * MAXDIM]int32 - for i := 2; i < *dim; i += 8 { - for j := 2; j < *dim-3; j += 8 { - for y := 0; y < 3; y++ { - a[i**dim+j+y] = 1 - } - } - } - - p, err := plugin.Open("life.so") - if err != nil { - panic(err) - } - f, err := p.Lookup("Run") - if err != nil { - panic(err) - } - f.(func(int, int, int, []int32))(*gen, *dim, *dim, a[:]) - - for i := 0; i < *dim; i++ { - for j := 0; j < *dim; j++ { - if a[i**dim+j] == 0 { - fmt.Print(" ") - } else { - fmt.Print("X") - } - } - fmt.Print("\n") - } -} diff --git a/misc/cgo/testplugin/testdata/issue25756/plugin/c-life.c b/misc/cgo/testplugin/testdata/issue25756/plugin/c-life.c deleted file mode 100644 index f853163e2f..0000000000 --- a/misc/cgo/testplugin/testdata/issue25756/plugin/c-life.c +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2010 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 <assert.h> -#include "life.h" -#include "_cgo_export.h" - -const int MYCONST = 0; - -// Do the actual manipulation of the life board in C. This could be -// done easily in Go, we are just using C for demonstration -// purposes. -void -Step(int x, int y, int *a, int *n) -{ - struct GoStart_return r; - - // Use Go to start 4 goroutines each of which handles 1/4 of the - // board. - r = GoStart(0, x, y, 0, x / 2, 0, y / 2, a, n); - assert(r.r0 == 0 && r.r1 == 100); // test multiple returns - r = GoStart(1, x, y, x / 2, x, 0, y / 2, a, n); - assert(r.r0 == 1 && r.r1 == 101); // test multiple returns - GoStart(2, x, y, 0, x / 2, y / 2, y, a, n); - GoStart(3, x, y, x / 2, x, y / 2, y, a, n); - GoWait(0); - GoWait(1); - GoWait(2); - GoWait(3); -} - -// The actual computation. This is called in parallel. -void -DoStep(int xdim, int ydim, int xstart, int xend, int ystart, int yend, int *a, int *n) -{ - int x, y, c, i, j; - - for(x = xstart; x < xend; x++) { - for(y = ystart; y < yend; y++) { - c = 0; - for(i = -1; i <= 1; i++) { - for(j = -1; j <= 1; j++) { - if(x+i >= 0 && x+i < xdim && - y+j >= 0 && y+j < ydim && - (i != 0 || j != 0)) - c += a[(x+i)*xdim + (y+j)] != 0; - } - } - if(c == 3 || (c == 2 && a[x*xdim + y] != 0)) - n[x*xdim + y] = 1; - else - n[x*xdim + y] = 0; - } - } -} diff --git a/misc/cgo/testplugin/testdata/issue25756/plugin/life.go b/misc/cgo/testplugin/testdata/issue25756/plugin/life.go deleted file mode 100644 index 468bc6fab6..0000000000 --- a/misc/cgo/testplugin/testdata/issue25756/plugin/life.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2010 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 - -// #include "life.h" -import "C" - -import "unsafe" - -func Run(gen, x, y int, a []int32) { - n := make([]int32, x*y) - for i := 0; i < gen; i++ { - C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0]))) - copy(a, n) - } -} - -// Keep the channels visible from Go. -var chans [4]chan bool - -// Double return value is just for testing. -// -//export GoStart -func GoStart(i, xdim, ydim, xstart, xend, ystart, yend C.int, a *C.int, n *C.int) (int, int) { - c := make(chan bool, int(C.MYCONST)) - go func() { - C.DoStep(xdim, ydim, xstart, xend, ystart, yend, a, n) - c <- true - }() - chans[i] = c - return int(i), int(i + 100) -} - -//export GoWait -func GoWait(i C.int) { - <-chans[i] - chans[i] = nil -} diff --git a/misc/cgo/testplugin/testdata/issue25756/plugin/life.h b/misc/cgo/testplugin/testdata/issue25756/plugin/life.h deleted file mode 100644 index 11d2b97226..0000000000 --- a/misc/cgo/testplugin/testdata/issue25756/plugin/life.h +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2010 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. - -extern void Step(int, int, int *, int *); -extern void DoStep(int, int, int, int, int, int, int *, int *); -extern const int MYCONST; diff --git a/misc/cgo/testplugin/testdata/issue44956/base/base.go b/misc/cgo/testplugin/testdata/issue44956/base/base.go deleted file mode 100644 index 609aa0dff4..0000000000 --- a/misc/cgo/testplugin/testdata/issue44956/base/base.go +++ /dev/null @@ -1,7 +0,0 @@ -// 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. - -package base - -var X = &map[int]int{123: 456} diff --git a/misc/cgo/testplugin/testdata/issue44956/main.go b/misc/cgo/testplugin/testdata/issue44956/main.go deleted file mode 100644 index 287a60585e..0000000000 --- a/misc/cgo/testplugin/testdata/issue44956/main.go +++ /dev/null @@ -1,47 +0,0 @@ -// 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 44956: writable static temp is not exported correctly. -// In the test below, package base is -// -// X = &map{...} -// -// which compiles to -// -// X = &stmp // static -// stmp = makemap(...) // in init function -// -// plugin1 and plugin2 both import base. plugin1 doesn't use -// base.X, so that symbol is deadcoded in plugin1. -// -// plugin1 is loaded first. base.init runs at that point, which -// initialize base.stmp. -// -// plugin2 is then loaded. base.init already ran, so it doesn't run -// again. When base.stmp is not exported, plugin2's base.X points to -// its own private base.stmp, which is not initialized, fail. - -package main - -import "plugin" - -func main() { - _, err := plugin.Open("issue44956p1.so") - if err != nil { - panic("FAIL") - } - - p2, err := plugin.Open("issue44956p2.so") - if err != nil { - panic("FAIL") - } - f, err := p2.Lookup("F") - if err != nil { - panic("FAIL") - } - x := f.(func() *map[int]int)() - if x == nil || (*x)[123] != 456 { - panic("FAIL") - } -} diff --git a/misc/cgo/testplugin/testdata/issue44956/plugin1.go b/misc/cgo/testplugin/testdata/issue44956/plugin1.go deleted file mode 100644 index 499fa31abf..0000000000 --- a/misc/cgo/testplugin/testdata/issue44956/plugin1.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -package main - -import _ "testplugin/issue44956/base" - -func main() {} diff --git a/misc/cgo/testplugin/testdata/issue44956/plugin2.go b/misc/cgo/testplugin/testdata/issue44956/plugin2.go deleted file mode 100644 index a73542ca71..0000000000 --- a/misc/cgo/testplugin/testdata/issue44956/plugin2.go +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -package main - -import "testplugin/issue44956/base" - -func F() *map[int]int { return base.X } - -func main() {} diff --git a/misc/cgo/testplugin/testdata/issue52937/main.go b/misc/cgo/testplugin/testdata/issue52937/main.go deleted file mode 100644 index 66f09effea..0000000000 --- a/misc/cgo/testplugin/testdata/issue52937/main.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2022 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 - -func main() {} -func F[T any]() {} -func G[T any](T) {} diff --git a/misc/cgo/testplugin/testdata/issue53989/main.go b/misc/cgo/testplugin/testdata/issue53989/main.go deleted file mode 100644 index 6907dfd858..0000000000 --- a/misc/cgo/testplugin/testdata/issue53989/main.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 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 53989: the use of jump table caused a function -// from the plugin jumps in the middle of the function -// to the function with the same name in the main -// executable. As these two functions may be compiled -// differently as plugin needs to be PIC, this causes -// crash. - -package main - -import ( - "plugin" - - "testplugin/issue53989/p" -) - -func main() { - p.Square(7) // call the function in main executable - - p, err := plugin.Open("issue53989.so") - if err != nil { - panic(err) - } - f, err := p.Lookup("Square") - if err != nil { - panic(err) - } - f.(func(int))(7) // call the plugin one -} diff --git a/misc/cgo/testplugin/testdata/issue53989/p/p.go b/misc/cgo/testplugin/testdata/issue53989/p/p.go deleted file mode 100644 index 02567c1cee..0000000000 --- a/misc/cgo/testplugin/testdata/issue53989/p/p.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2022 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 - -import ( - "fmt" - "runtime" -) - -var y int - -//go:noinline -func Square(x int) { - var pc0, pc1 [1]uintptr - runtime.Callers(1, pc0[:]) // get PC at entry - - // a switch using jump table - switch x { - case 1: - y = 1 - case 2: - y = 4 - case 3: - y = 9 - case 4: - y = 16 - case 5: - y = 25 - case 6: - y = 36 - case 7: - y = 49 - case 8: - y = 64 - default: - panic("too large") - } - - // check PC is in the same function - runtime.Callers(1, pc1[:]) - if pc1[0] < pc0[0] || pc1[0] > pc0[0]+1000000 { - fmt.Printf("jump across DSO boundary. pc0=%x, pc1=%x\n", pc0[0], pc1[0]) - panic("FAIL") - } - - if y != x*x { - fmt.Printf("x=%d y=%d!=%d\n", x, y, x*x) - panic("FAIL") - } -} diff --git a/misc/cgo/testplugin/testdata/issue53989/plugin.go b/misc/cgo/testplugin/testdata/issue53989/plugin.go deleted file mode 100644 index a753ee4419..0000000000 --- a/misc/cgo/testplugin/testdata/issue53989/plugin.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2022 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 - -import "testplugin/issue53989/p" - -func Square(x int) { // export Square for plugin - p.Square(x) -} - -func main() {} diff --git a/misc/cgo/testplugin/testdata/method/main.go b/misc/cgo/testplugin/testdata/method/main.go deleted file mode 100644 index 5e9189b450..0000000000 --- a/misc/cgo/testplugin/testdata/method/main.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -// Issue 42579: methods of symbols exported from plugin must be live. - -package main - -import ( - "plugin" - "reflect" -) - -func main() { - p, err := plugin.Open("plugin.so") - if err != nil { - panic(err) - } - - x, err := p.Lookup("X") - if err != nil { - panic(err) - } - - reflect.ValueOf(x).Elem().MethodByName("M").Call(nil) -} diff --git a/misc/cgo/testplugin/testdata/method/plugin.go b/misc/cgo/testplugin/testdata/method/plugin.go deleted file mode 100644 index 240edd3bc4..0000000000 --- a/misc/cgo/testplugin/testdata/method/plugin.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -package main - -func main() {} - -type T int - -func (T) M() { println("M") } - -var X T diff --git a/misc/cgo/testplugin/testdata/method2/main.go b/misc/cgo/testplugin/testdata/method2/main.go deleted file mode 100644 index 89afbda3d4..0000000000 --- a/misc/cgo/testplugin/testdata/method2/main.go +++ /dev/null @@ -1,32 +0,0 @@ -// 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. - -// A type can be passed to a plugin and converted to interface -// there. So its methods need to be live. - -package main - -import ( - "plugin" - - "testplugin/method2/p" -) - -var t p.T - -type I interface{ M() } - -func main() { - pl, err := plugin.Open("method2.so") - if err != nil { - panic(err) - } - - f, err := pl.Lookup("F") - if err != nil { - panic(err) - } - - f.(func(p.T) interface{})(t).(I).M() -} diff --git a/misc/cgo/testplugin/testdata/method2/p/p.go b/misc/cgo/testplugin/testdata/method2/p/p.go deleted file mode 100644 index acb526acec..0000000000 --- a/misc/cgo/testplugin/testdata/method2/p/p.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -package p - -type T int - -func (T) M() { println("M") } diff --git a/misc/cgo/testplugin/testdata/method2/plugin.go b/misc/cgo/testplugin/testdata/method2/plugin.go deleted file mode 100644 index 6198e7648e..0000000000 --- a/misc/cgo/testplugin/testdata/method2/plugin.go +++ /dev/null @@ -1,11 +0,0 @@ -// 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. - -package main - -import "testplugin/method2/p" - -func main() {} - -func F(t p.T) interface{} { return t } diff --git a/misc/cgo/testplugin/testdata/method3/main.go b/misc/cgo/testplugin/testdata/method3/main.go deleted file mode 100644 index a3a51711cd..0000000000 --- a/misc/cgo/testplugin/testdata/method3/main.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2022 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. - -// An unexported method can be reachable from the plugin via interface -// when a package is shared. So it need to be live. - -package main - -import ( - "plugin" - - "testplugin/method3/p" -) - -var i p.I - -func main() { - pl, err := plugin.Open("method3.so") - if err != nil { - panic(err) - } - - f, err := pl.Lookup("F") - if err != nil { - panic(err) - } - - f.(func())() - - i = p.T(123) -} diff --git a/misc/cgo/testplugin/testdata/method3/p/p.go b/misc/cgo/testplugin/testdata/method3/p/p.go deleted file mode 100644 index f72f7c715c..0000000000 --- a/misc/cgo/testplugin/testdata/method3/p/p.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2022 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 - -type T int - -func (T) m() { println("m") } - -type I interface{ m() } - -func F() { - i.m() -} - -var i I = T(123) diff --git a/misc/cgo/testplugin/testdata/method3/plugin.go b/misc/cgo/testplugin/testdata/method3/plugin.go deleted file mode 100644 index bd25b31857..0000000000 --- a/misc/cgo/testplugin/testdata/method3/plugin.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2022 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 - -import "testplugin/method3/p" - -func main() {} - -func F() { p.F() } diff --git a/misc/cgo/testplugin/testdata/plugin1/plugin1.go b/misc/cgo/testplugin/testdata/plugin1/plugin1.go deleted file mode 100644 index d29d674ade..0000000000 --- a/misc/cgo/testplugin/testdata/plugin1/plugin1.go +++ /dev/null @@ -1,57 +0,0 @@ -// 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 main - -// // No C code required. -import "C" - -import ( - "reflect" - - "testplugin/common" -) - -func F() int { - _ = make([]byte, 1<<21) // trigger stack unwind, Issue #18190. - return 3 -} - -func ReadCommonX() int { - return common.X -} - -var Seven int - -func call(fn func()) { - fn() -} - -func g() { - common.X *= Seven -} - -func init() { - Seven = 7 - call(g) -} - -type sameNameReusedInPlugins struct { - X string -} - -type sameNameHolder struct { - F *sameNameReusedInPlugins -} - -func UnexportedNameReuse() { - h := sameNameHolder{} - v := reflect.ValueOf(&h).Elem().Field(0) - newval := reflect.New(v.Type().Elem()) - v.Set(newval) -} - -func main() { - panic("plugin1.main called") -} diff --git a/misc/cgo/testplugin/testdata/plugin2/plugin2.go b/misc/cgo/testplugin/testdata/plugin2/plugin2.go deleted file mode 100644 index 31ed642ca5..0000000000 --- a/misc/cgo/testplugin/testdata/plugin2/plugin2.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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 main - -//#include <errno.h> -//#include <string.h> -import "C" - -// #include -// void cfunc() {} // uses cgo_topofstack - -import ( - "reflect" - "strings" - - "testplugin/common" -) - -func init() { - _ = strings.NewReplacer() // trigger stack unwind, Issue #18190. - C.strerror(C.EIO) // uses cgo_topofstack - common.X = 2 -} - -type sameNameReusedInPlugins struct { - X string -} - -type sameNameHolder struct { - F *sameNameReusedInPlugins -} - -func UnexportedNameReuse() { - h := sameNameHolder{} - v := reflect.ValueOf(&h).Elem().Field(0) - newval := reflect.New(v.Type().Elem()) - v.Set(newval) -} - -func main() { - panic("plugin1.main called") -} diff --git a/misc/cgo/testplugin/testdata/sub/plugin1/plugin1.go b/misc/cgo/testplugin/testdata/sub/plugin1/plugin1.go deleted file mode 100644 index 5f891b09a3..0000000000 --- a/misc/cgo/testplugin/testdata/sub/plugin1/plugin1.go +++ /dev/null @@ -1,23 +0,0 @@ -// 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 main - -// // No C code required. -import "C" - -import "testplugin/common" - -func F() int { return 17 } - -var FuncVar = func() {} - -func ReadCommonX() int { - FuncVar() - return common.X -} - -func main() { - panic("plugin1.main called") -} diff --git a/misc/cgo/testplugin/testdata/unnamed1/main.go b/misc/cgo/testplugin/testdata/unnamed1/main.go deleted file mode 100644 index 1620dc48ce..0000000000 --- a/misc/cgo/testplugin/testdata/unnamed1/main.go +++ /dev/null @@ -1,25 +0,0 @@ -// 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. - -//go:build ignore - -package main - -// // No C code required. -import "C" - -func FuncInt() int { return 1 } - -// Add a recursive type to check that type equality across plugins doesn't -// crash. See https://golang.org/issues/19258 -func FuncRecursive() X { return X{} } - -type Y struct { - X *X -} -type X struct { - Y Y -} - -func main() {} diff --git a/misc/cgo/testplugin/testdata/unnamed2/main.go b/misc/cgo/testplugin/testdata/unnamed2/main.go deleted file mode 100644 index 027ef6475c..0000000000 --- a/misc/cgo/testplugin/testdata/unnamed2/main.go +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -//go:build ignore - -package main - -// // No C code required. -import "C" - -func FuncInt() int { return 2 } - -func FuncRecursive() X { return X{} } - -type Y struct { - X *X -} -type X struct { - Y Y -} - -func main() {} diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go deleted file mode 100644 index 932cfb1b60..0000000000 --- a/misc/cgo/testsanitizers/asan_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// 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. - -package sanitizers_test - -import ( - "fmt" - "strings" - "testing" -) - -func TestASAN(t *testing.T) { - goos, err := goEnv("GOOS") - if err != nil { - t.Fatal(err) - } - goarch, err := goEnv("GOARCH") - if err != nil { - t.Fatal(err) - } - // The asan tests require support for the -asan option. - if !aSanSupported(goos, goarch) { - t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch) - } - // The current implementation is only compatible with the ASan library from version - // v7 to v9 (See the description in src/runtime/asan/asan.go). Therefore, using the - // -asan option must use a compatible version of ASan library, which requires that - // the gcc version is not less than 7 and the clang version is not less than 9, - // otherwise a segmentation fault will occur. - if !compilerRequiredAsanVersion(goos, goarch) { - t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch) - } - - t.Parallel() - requireOvercommit(t) - config := configure("address") - config.skipIfCSanitizerBroken(t) - - mustRun(t, config.goCmd("build", "std")) - - cases := []struct { - src string - memoryAccessError string - errorLocation string - experiments []string - }{ - {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free", errorLocation: "asan1_fail.go:25"}, - {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow", errorLocation: "asan2_fail.go:31"}, - {src: "asan3_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan3_fail.go:13"}, - {src: "asan4_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan4_fail.go:13"}, - {src: "asan5_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan5_fail.go:18"}, - {src: "asan_useAfterReturn.go"}, - {src: "asan_unsafe_fail1.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail1.go:25"}, - {src: "asan_unsafe_fail2.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail2.go:25"}, - {src: "asan_unsafe_fail3.go", memoryAccessError: "use-after-poison", errorLocation: "asan_unsafe_fail3.go:18"}, - {src: "asan_global1_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global1_fail.go:12"}, - {src: "asan_global2_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global2_fail.go:19"}, - {src: "asan_global3_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global3_fail.go:13"}, - {src: "asan_global4_fail.go", memoryAccessError: "global-buffer-overflow", errorLocation: "asan_global4_fail.go:21"}, - {src: "asan_global5.go"}, - {src: "arena_fail.go", memoryAccessError: "use-after-poison", errorLocation: "arena_fail.go:26", experiments: []string{"arenas"}}, - } - for _, tc := range cases { - tc := tc - name := strings.TrimSuffix(tc.src, ".go") - t.Run(name, func(t *testing.T) { - t.Parallel() - - dir := newTempDir(t) - defer dir.RemoveAll(t) - - outPath := dir.Join(name) - mustRun(t, config.goCmdWithExperiments("build", []string{"-o", outPath, srcPath(tc.src)}, tc.experiments)) - - cmd := hangProneCmd(outPath) - if tc.memoryAccessError != "" { - outb, err := cmd.CombinedOutput() - out := string(outb) - if err != nil && strings.Contains(out, tc.memoryAccessError) { - // This string is output if the - // sanitizer library needs a - // symbolizer program and can't find it. - const noSymbolizer = "external symbolizer" - // Check if -asan option can correctly print where the error occurred. - if tc.errorLocation != "" && - !strings.Contains(out, tc.errorLocation) && - !strings.Contains(out, noSymbolizer) && - compilerSupportsLocation() { - - t.Errorf("%#q exited without expected location of the error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.errorLocation, out) - } - return - } - t.Fatalf("%#q exited without expected memory access error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.memoryAccessError, out) - } - mustRun(t, cmd) - }) - } -} - -func TestASANLinkerX(t *testing.T) { - // Test ASAN with linker's -X flag (see issue 56175). - goos, err := goEnv("GOOS") - if err != nil { - t.Fatal(err) - } - goarch, err := goEnv("GOARCH") - if err != nil { - t.Fatal(err) - } - // The asan tests require support for the -asan option. - if !aSanSupported(goos, goarch) { - t.Skipf("skipping on %s/%s; -asan option is not supported.", goos, goarch) - } - if !compilerRequiredAsanVersion(goos, goarch) { - t.Skipf("skipping on %s/%s: too old version of compiler", goos, goarch) - } - - t.Parallel() - requireOvercommit(t) - config := configure("address") - config.skipIfCSanitizerBroken(t) - - dir := newTempDir(t) - defer dir.RemoveAll(t) - - var ldflags string - for i := 1; i <= 10; i++ { - ldflags += fmt.Sprintf("-X=main.S%d=%d -X=misc/cgo/testsanitizers/testdata/asan_linkerx/p.S%d=%d ", i, i, i, i) - } - - // build the binary - outPath := dir.Join("main.exe") - cmd := config.goCmd("build", "-ldflags="+ldflags, "-o", outPath) - cmd.Dir = srcPath("asan_linkerx") - mustRun(t, cmd) - - // run the binary - mustRun(t, hangProneCmd(outPath)) -} diff --git a/misc/cgo/testsanitizers/cc_test.go b/misc/cgo/testsanitizers/cc_test.go deleted file mode 100644 index 8eda1372f6..0000000000 --- a/misc/cgo/testsanitizers/cc_test.go +++ /dev/null @@ -1,583 +0,0 @@ -// Copyright 2017 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. - -// sanitizers_test checks the use of Go with sanitizers like msan, asan, etc. -// See https://github.com/google/sanitizers. -package sanitizers_test - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "os" - "os/exec" - "path/filepath" - "regexp" - "strconv" - "strings" - "sync" - "syscall" - "testing" - "time" - "unicode" -) - -var overcommit struct { - sync.Once - value int - err error -} - -// requireOvercommit skips t if the kernel does not allow overcommit. -func requireOvercommit(t *testing.T) { - t.Helper() - - overcommit.Once.Do(func() { - var out []byte - out, overcommit.err = os.ReadFile("/proc/sys/vm/overcommit_memory") - if overcommit.err != nil { - return - } - overcommit.value, overcommit.err = strconv.Atoi(string(bytes.TrimSpace(out))) - }) - - if overcommit.err != nil { - t.Skipf("couldn't determine vm.overcommit_memory (%v); assuming no overcommit", overcommit.err) - } - if overcommit.value == 2 { - t.Skip("vm.overcommit_memory=2") - } -} - -var env struct { - sync.Once - m map[string]string - err error -} - -// goEnv returns the output of $(go env) as a map. -func goEnv(key string) (string, error) { - env.Once.Do(func() { - var out []byte - out, env.err = exec.Command("go", "env", "-json").Output() - if env.err != nil { - return - } - - env.m = make(map[string]string) - env.err = json.Unmarshal(out, &env.m) - }) - if env.err != nil { - return "", env.err - } - - v, ok := env.m[key] - if !ok { - return "", fmt.Errorf("`go env`: no entry for %v", key) - } - return v, nil -} - -// replaceEnv sets the key environment variable to value in cmd. -func replaceEnv(cmd *exec.Cmd, key, value string) { - if cmd.Env == nil { - cmd.Env = cmd.Environ() - } - cmd.Env = append(cmd.Env, key+"="+value) -} - -// appendExperimentEnv appends comma-separated experiments to GOEXPERIMENT. -func appendExperimentEnv(cmd *exec.Cmd, experiments []string) { - if cmd.Env == nil { - cmd.Env = cmd.Environ() - } - exps := strings.Join(experiments, ",") - for _, evar := range cmd.Env { - c := strings.SplitN(evar, "=", 2) - if c[0] == "GOEXPERIMENT" { - exps = c[1] + "," + exps - } - } - cmd.Env = append(cmd.Env, "GOEXPERIMENT="+exps) -} - -// mustRun executes t and fails cmd with a well-formatted message if it fails. -func mustRun(t *testing.T, cmd *exec.Cmd) { - t.Helper() - out := new(strings.Builder) - cmd.Stdout = out - cmd.Stderr = out - - err := cmd.Start() - if err != nil { - t.Fatalf("%v: %v", cmd, err) - } - - if deadline, ok := t.Deadline(); ok { - timeout := time.Until(deadline) - timeout -= timeout / 10 // Leave 10% headroom for logging and cleanup. - timer := time.AfterFunc(timeout, func() { - cmd.Process.Signal(syscall.SIGQUIT) - }) - defer timer.Stop() - } - - if err := cmd.Wait(); err != nil { - t.Fatalf("%v exited with %v\n%s", cmd, err, out) - } -} - -// cc returns a cmd that executes `$(go env CC) $(go env GOGCCFLAGS) $args`. -func cc(args ...string) (*exec.Cmd, error) { - CC, err := goEnv("CC") - if err != nil { - return nil, err - } - - GOGCCFLAGS, err := goEnv("GOGCCFLAGS") - if err != nil { - return nil, err - } - - // Split GOGCCFLAGS, respecting quoting. - // - // TODO(bcmills): This code also appears in - // misc/cgo/testcarchive/carchive_test.go, and perhaps ought to go in - // src/cmd/dist/test.go as well. Figure out where to put it so that it can be - // shared. - var flags []string - quote := '\000' - start := 0 - lastSpace := true - backslash := false - for i, c := range GOGCCFLAGS { - if quote == '\000' && unicode.IsSpace(c) { - if !lastSpace { - flags = append(flags, GOGCCFLAGS[start:i]) - lastSpace = true - } - } else { - if lastSpace { - start = i - lastSpace = false - } - if quote == '\000' && !backslash && (c == '"' || c == '\'') { - quote = c - backslash = false - } else if !backslash && quote == c { - quote = '\000' - } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' { - backslash = true - } else { - backslash = false - } - } - } - if !lastSpace { - flags = append(flags, GOGCCFLAGS[start:]) - } - - cmd := exec.Command(CC, flags...) - cmd.Args = append(cmd.Args, args...) - return cmd, nil -} - -type version struct { - name string - major, minor int -} - -var compiler struct { - sync.Once - version - err error -} - -// compilerVersion detects the version of $(go env CC). -// -// It returns a non-nil error if the compiler matches a known version schema but -// the version could not be parsed, or if $(go env CC) could not be determined. -func compilerVersion() (version, error) { - compiler.Once.Do(func() { - compiler.err = func() error { - compiler.name = "unknown" - - cmd, err := cc("--version") - if err != nil { - return err - } - out, err := cmd.Output() - if err != nil { - // Compiler does not support "--version" flag: not Clang or GCC. - return nil - } - - var match [][]byte - if bytes.HasPrefix(out, []byte("gcc")) { - compiler.name = "gcc" - cmd, err := cc("-dumpfullversion", "-dumpversion") - if err != nil { - return err - } - out, err := cmd.Output() - if err != nil { - // gcc, but does not support gcc's "-v" flag?! - return err - } - gccRE := regexp.MustCompile(`(\d+)\.(\d+)`) - match = gccRE.FindSubmatch(out) - } else { - clangRE := regexp.MustCompile(`clang version (\d+)\.(\d+)`) - if match = clangRE.FindSubmatch(out); len(match) > 0 { - compiler.name = "clang" - } - } - - if len(match) < 3 { - return nil // "unknown" - } - if compiler.major, err = strconv.Atoi(string(match[1])); err != nil { - return err - } - if compiler.minor, err = strconv.Atoi(string(match[2])); err != nil { - return err - } - return nil - }() - }) - return compiler.version, compiler.err -} - -// compilerSupportsLocation reports whether the compiler should be -// able to provide file/line information in backtraces. -func compilerSupportsLocation() bool { - compiler, err := compilerVersion() - if err != nil { - return false - } - switch compiler.name { - case "gcc": - return compiler.major >= 10 - case "clang": - return true - default: - return false - } -} - -// 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 { - compiler, err := compilerVersion() - if err != nil { - return false - } - if compiler.name == "gcc" && goarch == "ppc64le" { - return compiler.major >= 9 - } - return true -} - -// compilerRequiredAsanVersion reports whether the compiler is the version required by Asan. -func compilerRequiredAsanVersion(goos, goarch string) bool { - compiler, err := compilerVersion() - if err != nil { - return false - } - switch compiler.name { - case "gcc": - if goarch == "ppc64le" { - return compiler.major >= 9 - } - return compiler.major >= 7 - case "clang": - return compiler.major >= 9 - default: - return false - } -} - -type compilerCheck struct { - once sync.Once - err error - skip bool // If true, skip with err instead of failing with it. -} - -type config struct { - sanitizer string - - cFlags, ldFlags, goFlags []string - - sanitizerCheck, runtimeCheck compilerCheck -} - -var configs struct { - sync.Mutex - m map[string]*config -} - -// configure returns the configuration for the given sanitizer. -func configure(sanitizer string) *config { - configs.Lock() - defer configs.Unlock() - if c, ok := configs.m[sanitizer]; ok { - return c - } - - c := &config{ - sanitizer: sanitizer, - cFlags: []string{"-fsanitize=" + sanitizer}, - ldFlags: []string{"-fsanitize=" + sanitizer}, - } - - if testing.Verbose() { - c.goFlags = append(c.goFlags, "-x") - } - - switch sanitizer { - case "memory": - c.goFlags = append(c.goFlags, "-msan") - - case "thread": - c.goFlags = append(c.goFlags, "--installsuffix=tsan") - compiler, _ := compilerVersion() - if compiler.name == "gcc" { - c.cFlags = append(c.cFlags, "-fPIC") - c.ldFlags = append(c.ldFlags, "-fPIC", "-static-libtsan") - } - - case "address": - c.goFlags = append(c.goFlags, "-asan") - // Set the debug mode to print the C stack trace. - c.cFlags = append(c.cFlags, "-g") - - case "fuzzer": - c.goFlags = append(c.goFlags, "-tags=libfuzzer", "-gcflags=-d=libfuzzer") - - default: - panic(fmt.Sprintf("unrecognized sanitizer: %q", sanitizer)) - } - - if configs.m == nil { - configs.m = make(map[string]*config) - } - configs.m[sanitizer] = c - return c -} - -// goCmd returns a Cmd that executes "go $subcommand $args" with appropriate -// additional flags and environment. -func (c *config) goCmd(subcommand string, args ...string) *exec.Cmd { - return c.goCmdWithExperiments(subcommand, args, nil) -} - -// goCmdWithExperiments returns a Cmd that executes -// "GOEXPERIMENT=$experiments go $subcommand $args" with appropriate -// additional flags and CGO-related environment variables. -func (c *config) goCmdWithExperiments(subcommand string, args []string, experiments []string) *exec.Cmd { - cmd := exec.Command("go", subcommand) - cmd.Args = append(cmd.Args, c.goFlags...) - cmd.Args = append(cmd.Args, args...) - replaceEnv(cmd, "CGO_CFLAGS", strings.Join(c.cFlags, " ")) - replaceEnv(cmd, "CGO_LDFLAGS", strings.Join(c.ldFlags, " ")) - appendExperimentEnv(cmd, experiments) - return cmd -} - -// skipIfCSanitizerBroken skips t if the C compiler does not produce working -// binaries as configured. -func (c *config) skipIfCSanitizerBroken(t *testing.T) { - check := &c.sanitizerCheck - check.once.Do(func() { - check.skip, check.err = c.checkCSanitizer() - }) - if check.err != nil { - t.Helper() - if check.skip { - t.Skip(check.err) - } - t.Fatal(check.err) - } -} - -var cMain = []byte(` -int main() { - return 0; -} -`) - -var cLibFuzzerInput = []byte(` -#include <stddef.h> -int LLVMFuzzerTestOneInput(char *data, size_t size) { - return 0; -} -`) - -func (c *config) checkCSanitizer() (skip bool, err error) { - 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") - cInput := cMain - if c.sanitizer == "fuzzer" { - // libFuzzer generates the main function itself, and uses a different input. - cInput = cLibFuzzerInput - } - if err := os.WriteFile(src, cInput, 0600); err != nil { - return false, fmt.Errorf("failed to write C source file: %v", err) - } - - dst := filepath.Join(dir, "return0") - cmd, err := cc(c.cFlags...) - if err != nil { - return false, err - } - cmd.Args = append(cmd.Args, c.ldFlags...) - cmd.Args = append(cmd.Args, "-o", dst, src) - out, err := cmd.CombinedOutput() - if err != nil { - if bytes.Contains(out, []byte("-fsanitize")) && - (bytes.Contains(out, []byte("unrecognized")) || - bytes.Contains(out, []byte("unsupported"))) { - return true, errors.New(string(out)) - } - return true, fmt.Errorf("%#q failed: %v\n%s", strings.Join(cmd.Args, " "), err, out) - } - - if c.sanitizer == "fuzzer" { - // For fuzzer, don't try running the test binary. It never finishes. - return false, nil - } - - if out, err := exec.Command(dst).CombinedOutput(); err != nil { - if os.IsNotExist(err) { - return true, fmt.Errorf("%#q failed to produce executable: %v", strings.Join(cmd.Args, " "), err) - } - snippet, _, _ := bytes.Cut(out, []byte("\n")) - return true, fmt.Errorf("%#q generated broken executable: %v\n%s", strings.Join(cmd.Args, " "), err, snippet) - } - - return false, nil -} - -// skipIfRuntimeIncompatible skips t if the Go runtime is suspected not to work -// with cgo as configured. -func (c *config) skipIfRuntimeIncompatible(t *testing.T) { - check := &c.runtimeCheck - check.once.Do(func() { - check.skip, check.err = c.checkRuntime() - }) - if check.err != nil { - t.Helper() - if check.skip { - t.Skip(check.err) - } - t.Fatal(check.err) - } -} - -func (c *config) checkRuntime() (skip bool, err error) { - if c.sanitizer != "thread" { - return false, nil - } - - // libcgo.h sets CGO_TSAN if it detects TSAN support in the C compiler. - // Dump the preprocessor defines to check that works. - // (Sometimes it doesn't: see https://golang.org/issue/15983.) - cmd, err := cc(c.cFlags...) - if err != nil { - return false, err - } - cmd.Args = append(cmd.Args, "-dM", "-E", "../../../src/runtime/cgo/libcgo.h") - cmdStr := strings.Join(cmd.Args, " ") - out, err := cmd.CombinedOutput() - if err != nil { - return false, fmt.Errorf("%#q exited with %v\n%s", cmdStr, err, out) - } - if !bytes.Contains(out, []byte("#define CGO_TSAN")) { - return true, fmt.Errorf("%#q did not define CGO_TSAN", cmdStr) - } - return false, nil -} - -// srcPath returns the path to the given file relative to this test's source tree. -func srcPath(path string) string { - return filepath.Join("testdata", path) -} - -// A tempDir manages a temporary directory within a test. -type tempDir struct { - base string -} - -func (d *tempDir) RemoveAll(t *testing.T) { - t.Helper() - if d.base == "" { - return - } - if err := os.RemoveAll(d.base); err != nil { - t.Fatalf("Failed to remove temp dir: %v", err) - } -} - -func (d *tempDir) Base() string { - return d.base -} - -func (d *tempDir) Join(name string) string { - return filepath.Join(d.base, name) -} - -func newTempDir(t *testing.T) *tempDir { - t.Helper() - dir, err := os.MkdirTemp("", filepath.Dir(t.Name())) - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } - return &tempDir{base: dir} -} - -// hangProneCmd returns an exec.Cmd for a command that is likely to hang. -// -// If one of these tests hangs, the caller is likely to kill the test process -// using SIGINT, which will be sent to all of the processes in the test's group. -// Unfortunately, TSAN in particular is prone to dropping signals, so the SIGINT -// may terminate the test binary but leave the subprocess running. hangProneCmd -// configures subprocess to receive SIGKILL instead to ensure that it won't -// leak. -func hangProneCmd(name string, arg ...string) *exec.Cmd { - cmd := exec.Command(name, arg...) - cmd.SysProcAttr = &syscall.SysProcAttr{ - Pdeathsig: syscall.SIGKILL, - } - return cmd -} - -// mSanSupported is a copy of the function cmd/internal/sys.MSanSupported, -// because the internal package can't be used here. -func mSanSupported(goos, goarch string) bool { - switch goos { - case "linux": - return goarch == "amd64" || goarch == "arm64" - case "freebsd": - return goarch == "amd64" - default: - return false - } -} - -// aSanSupported is a copy of the function cmd/internal/sys.ASanSupported, -// because the internal package can't be used here. -func aSanSupported(goos, goarch string) bool { - switch goos { - case "linux": - return goarch == "amd64" || goarch == "arm64" || goarch == "riscv64" || goarch == "ppc64le" - default: - return false - } -} diff --git a/misc/cgo/testsanitizers/cshared_test.go b/misc/cgo/testsanitizers/cshared_test.go deleted file mode 100644 index 21b13ce4ed..0000000000 --- a/misc/cgo/testsanitizers/cshared_test.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2017 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 sanitizers_test - -import ( - "fmt" - "os" - "strings" - "testing" -) - -func TestShared(t *testing.T) { - t.Parallel() - requireOvercommit(t) - - GOOS, err := goEnv("GOOS") - if err != nil { - t.Fatal(err) - } - - GOARCH, err := goEnv("GOARCH") - if err != nil { - t.Fatal(err) - } - - libExt := "so" - if GOOS == "darwin" { - libExt = "dylib" - } - - cases := []struct { - src string - sanitizer string - }{ - { - src: "msan_shared.go", - sanitizer: "memory", - }, - { - src: "tsan_shared.go", - sanitizer: "thread", - }, - } - - 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 - } - if tc.sanitizer == "thread" && !compilerRequiredTsanVersion(GOOS, GOARCH) { - t.Logf("skipping %s test on %s/%s; compiler version too old for -tsan.", name, GOOS, GOARCH) - continue - } - - t.Run(name, func(t *testing.T) { - t.Parallel() - config := configure(tc.sanitizer) - config.skipIfCSanitizerBroken(t) - - dir := newTempDir(t) - defer dir.RemoveAll(t) - - lib := dir.Join(fmt.Sprintf("lib%s.%s", name, libExt)) - mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src))) - - cSrc := dir.Join("main.c") - if err := os.WriteFile(cSrc, cMain, 0600); err != nil { - t.Fatalf("failed to write C source file: %v", err) - } - - dstBin := dir.Join(name) - cmd, err := cc(config.cFlags...) - if err != nil { - t.Fatal(err) - } - cmd.Args = append(cmd.Args, config.ldFlags...) - cmd.Args = append(cmd.Args, "-o", dstBin, cSrc, lib) - mustRun(t, cmd) - - cmd = hangProneCmd(dstBin) - replaceEnv(cmd, "LD_LIBRARY_PATH", ".") - mustRun(t, cmd) - }) - } -} diff --git a/misc/cgo/testsanitizers/libfuzzer_test.go b/misc/cgo/testsanitizers/libfuzzer_test.go deleted file mode 100644 index 345751b9c7..0000000000 --- a/misc/cgo/testsanitizers/libfuzzer_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2022 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 sanitizers_test - -import ( - "strings" - "testing" -) - -func TestLibFuzzer(t *testing.T) { - goos, err := goEnv("GOOS") - if err != nil { - t.Fatal(err) - } - goarch, err := goEnv("GOARCH") - if err != nil { - t.Fatal(err) - } - if !libFuzzerSupported(goos, goarch) { - t.Skipf("skipping on %s/%s; libfuzzer option is not supported.", goos, goarch) - } - config := configure("fuzzer") - config.skipIfCSanitizerBroken(t) - - cases := []struct { - goSrc string - cSrc string - expectedError string - }{ - {goSrc: "libfuzzer1.go", expectedError: "panic: found it"}, - {goSrc: "libfuzzer2.go", cSrc: "libfuzzer2.c", expectedError: "panic: found it"}, - } - for _, tc := range cases { - tc := tc - name := strings.TrimSuffix(tc.goSrc, ".go") - t.Run(name, func(t *testing.T) { - t.Parallel() - - dir := newTempDir(t) - defer dir.RemoveAll(t) - - // build Go code in libfuzzer mode to a c-archive - outPath := dir.Join(name) - archivePath := dir.Join(name + ".a") - mustRun(t, config.goCmd("build", "-buildmode=c-archive", "-o", archivePath, srcPath(tc.goSrc))) - - // build C code (if any) and link with Go code - cmd, err := cc(config.cFlags...) - if err != nil { - t.Fatalf("error running cc: %v", err) - } - cmd.Args = append(cmd.Args, config.ldFlags...) - cmd.Args = append(cmd.Args, "-o", outPath, "-I", dir.Base()) - if tc.cSrc != "" { - cmd.Args = append(cmd.Args, srcPath(tc.cSrc)) - } - cmd.Args = append(cmd.Args, archivePath) - mustRun(t, cmd) - - cmd = hangProneCmd(outPath) - cmd.Dir = dir.Base() - outb, err := cmd.CombinedOutput() - out := string(outb) - if err == nil { - t.Fatalf("fuzzing succeeded unexpectedly; output:\n%s", out) - } - if !strings.Contains(out, tc.expectedError) { - t.Errorf("exited without expected error %q; got\n%s", tc.expectedError, out) - } - }) - } -} - -// libFuzzerSupported is a copy of the function internal/platform.FuzzInstrumented, -// because the internal package can't be used here. -func libFuzzerSupported(goos, goarch string) bool { - switch goarch { - case "amd64", "arm64": - // TODO(#14565): support more architectures. - switch goos { - case "darwin", "freebsd", "linux", "windows": - return true - default: - return false - } - default: - return false - } -} diff --git a/misc/cgo/testsanitizers/msan_test.go b/misc/cgo/testsanitizers/msan_test.go deleted file mode 100644 index 96397e0a87..0000000000 --- a/misc/cgo/testsanitizers/msan_test.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2017 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 sanitizers_test - -import ( - "strings" - "testing" -) - -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() - // Overcommit is enabled by default on FreeBSD (vm.overcommit=0, see tuning(7)). - // Do not skip tests with stricter overcommit settings unless testing shows that FreeBSD has similar issues. - if goos == "linux" { - requireOvercommit(t) - } - config := configure("memory") - config.skipIfCSanitizerBroken(t) - - mustRun(t, config.goCmd("build", "std")) - - cases := []struct { - src string - wantErr bool - experiments []string - }{ - {src: "msan.go"}, - {src: "msan2.go"}, - {src: "msan2_cmsan.go"}, - {src: "msan3.go"}, - {src: "msan4.go"}, - {src: "msan5.go"}, - {src: "msan6.go"}, - {src: "msan7.go"}, - {src: "msan8.go"}, - {src: "msan_fail.go", wantErr: true}, - // This may not always fail specifically due to MSAN. It may sometimes - // fail because of a fault. However, we don't care what kind of error we - // get here, just that we get an error. This is an MSAN test because without - // MSAN it would not fail deterministically. - {src: "arena_fail.go", wantErr: true, experiments: []string{"arenas"}}, - } - for _, tc := range cases { - tc := tc - name := strings.TrimSuffix(tc.src, ".go") - t.Run(name, func(t *testing.T) { - t.Parallel() - - dir := newTempDir(t) - defer dir.RemoveAll(t) - - outPath := dir.Join(name) - mustRun(t, config.goCmdWithExperiments("build", []string{"-o", outPath, srcPath(tc.src)}, tc.experiments)) - - cmd := hangProneCmd(outPath) - if tc.wantErr { - out, err := cmd.CombinedOutput() - if err != nil { - return - } - t.Fatalf("%#q exited without error; want MSAN failure\n%s", strings.Join(cmd.Args, " "), out) - } - mustRun(t, cmd) - }) - } -} diff --git a/misc/cgo/testsanitizers/testdata/arena_fail.go b/misc/cgo/testsanitizers/testdata/arena_fail.go deleted file mode 100644 index 5b6c52e435..0000000000 --- a/misc/cgo/testsanitizers/testdata/arena_fail.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2022 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 goexperiment.arenas - -package main - -import "arena" - -func main() { - a := arena.NewArena() - x := arena.New[[200]byte](a) - x[0] = 9 - a.Free() - // Use after free. - // - // ASAN should detect this deterministically as Free - // should poison the arena memory. - // - // MSAN should detect that this access is to freed - // memory. This may crash with an "accessed freed arena - // memory" error before MSAN gets a chance, but if MSAN - // was not enabled there would be a chance that this - // could fail to crash on its own. - println(x[0]) -} diff --git a/misc/cgo/testsanitizers/testdata/asan1_fail.go b/misc/cgo/testsanitizers/testdata/asan1_fail.go deleted file mode 100644 index 80289e5c30..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan1_fail.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -package main - -/* -#include <stdlib.h> -#include <stdio.h> - -int *p; -int* test() { - p = (int *)malloc(2 * sizeof(int)); - free(p); - return p; -} -*/ -import "C" -import "fmt" - -func main() { - // C passes Go an invalid pointer. - a := C.test() - // Use after free - *a = 2 // BOOM - // We shouldn't get here; asan should stop us first. - fmt.Println(*a) -} diff --git a/misc/cgo/testsanitizers/testdata/asan2_fail.go b/misc/cgo/testsanitizers/testdata/asan2_fail.go deleted file mode 100644 index 3ab0608571..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan2_fail.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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. - -package main - -/* -#include <stdlib.h> -#include <stdio.h> - -int *p; -int* f() { - int i; - p = (int *)malloc(5*sizeof(int)); - for (i = 0; i < 5; i++) { - p[i] = i+10; - } - return p; -} -*/ -import "C" -import ( - "fmt" - "unsafe" -) - -func main() { - a := C.f() - q5 := (*C.int)(unsafe.Add(unsafe.Pointer(a), 4*5)) - // Access to C pointer out of bounds. - *q5 = 100 // BOOM - // We shouldn't get here; asan should stop us first. - fmt.Printf("q5: %d, %x\n", *q5, q5) -} diff --git a/misc/cgo/testsanitizers/testdata/asan3_fail.go b/misc/cgo/testsanitizers/testdata/asan3_fail.go deleted file mode 100644 index 9f6d26dd89..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan3_fail.go +++ /dev/null @@ -1,23 +0,0 @@ -// 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. - -package main - -/* -#include <stdlib.h> -#include <stdio.h> - -void test(int *a) { - // Access Go pointer out of bounds. - int c = a[5]; // BOOM - // We shouldn't get here; asan should stop us first. - printf("a[5]=%d\n", c); -} -*/ -import "C" - -func main() { - cIntSlice := []C.int{200, 201, 203, 203, 204} - C.test(&cIntSlice[0]) -} diff --git a/misc/cgo/testsanitizers/testdata/asan4_fail.go b/misc/cgo/testsanitizers/testdata/asan4_fail.go deleted file mode 100644 index 12098458ae..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan4_fail.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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. - -package main - -/* -#include <stdlib.h> -#include <stdio.h> - -void test(int* a) { - // Access Go pointer out of bounds. - a[3] = 300; // BOOM - // We shouldn't get here; asan should stop us first. - printf("a[3]=%d\n", a[3]); -}*/ -import "C" - -func main() { - var cIntArray [2]C.int - C.test(&cIntArray[0]) // cIntArray is moved to heap. -} diff --git a/misc/cgo/testsanitizers/testdata/asan5_fail.go b/misc/cgo/testsanitizers/testdata/asan5_fail.go deleted file mode 100644 index d6853eab73..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan5_fail.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "fmt" - "runtime" - "unsafe" -) - -func main() { - p := new([1024 * 1000]int) - p[0] = 10 - r := bar(&p[1024*1000-1]) - fmt.Printf("r value is %d", r) -} - -func bar(a *int) int { - p := unsafe.Add(unsafe.Pointer(a), 2*unsafe.Sizeof(int(1))) - runtime.ASanWrite(p, 8) // BOOM - *((*int)(p)) = 10 - return *((*int)(p)) -} diff --git a/misc/cgo/testsanitizers/testdata/asan_global1_fail.go b/misc/cgo/testsanitizers/testdata/asan_global1_fail.go deleted file mode 100644 index 6cfc0b7138..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_global1_fail.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2022 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 - -/* -#include <stdlib.h> -#include <stdio.h> - -int test(int *a) { - a[2] = 300; // BOOM - return a[2]; -} -*/ -import "C" - -import "fmt" - -var cIntArray [2]C.int - -func main() { - r := C.test(&cIntArray[0]) - fmt.Println("r value = ", r) -} diff --git a/misc/cgo/testsanitizers/testdata/asan_global2_fail.go b/misc/cgo/testsanitizers/testdata/asan_global2_fail.go deleted file mode 100644 index 1932633368..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_global2_fail.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2022 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 - -/* -#include <stdlib.h> -#include <stdio.h> - -struct ss { - int *p; - int len; - int cap; -}; - -int test(struct ss *a) { - struct ss *t = a + 1; - t->len = 100; // BOOM - return t->len; -} -*/ -import "C" -import "fmt" - -var tt C.struct_ss - -func main() { - r := C.test(&tt) - fmt.Println("r value = ", r) -} diff --git a/misc/cgo/testsanitizers/testdata/asan_global3_fail.go b/misc/cgo/testsanitizers/testdata/asan_global3_fail.go deleted file mode 100644 index 9ab026c7fa..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_global3_fail.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 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 - -/* -#include <stdlib.h> -#include <stdio.h> - -int test(int *a) { - int* p = a+1; - *p = 10; // BOOM - return *p; -} -*/ -import "C" -import ( - "fmt" - "unsafe" -) - -var cIntV C.int - -func main() { - r := C.test((*C.int)(unsafe.Pointer(&cIntV))) - fmt.Printf("r value is %d", r) -} diff --git a/misc/cgo/testsanitizers/testdata/asan_global4_fail.go b/misc/cgo/testsanitizers/testdata/asan_global4_fail.go deleted file mode 100644 index d593598d5b..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_global4_fail.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2022 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 - -import ( - "fmt" - "unsafe" -) - -var intGlo int - -func main() { - r := bar(&intGlo) - fmt.Printf("r value is %d", r) -} - -func bar(a *int) int { - p := (*int)(unsafe.Add(unsafe.Pointer(a), 1*unsafe.Sizeof(int(1)))) - if *p == 10 { // BOOM - fmt.Println("its value is 10") - } - return *p -} diff --git a/misc/cgo/testsanitizers/testdata/asan_global5.go b/misc/cgo/testsanitizers/testdata/asan_global5.go deleted file mode 100644 index 0ed103da4f..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_global5.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2022 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 - -import ( - "fmt" -) - -type Any struct { - s string - b int64 -} - -var Sg = []interface{}{ - Any{"a", 10}, -} - -func main() { - fmt.Println(Sg[0]) -} diff --git a/misc/cgo/testsanitizers/testdata/asan_linkerx/main.go b/misc/cgo/testsanitizers/testdata/asan_linkerx/main.go deleted file mode 100644 index bbd6127d90..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_linkerx/main.go +++ /dev/null @@ -1,28 +0,0 @@ -package main - -import "misc/cgo/testsanitizers/testdata/asan_linkerx/p" - -func pstring(s *string) { - println(*s) -} - -func main() { - all := []*string{ - &S1, &S2, &S3, &S4, &S5, &S6, &S7, &S8, &S9, &S10, - &p.S1, &p.S2, &p.S3, &p.S4, &p.S5, &p.S6, &p.S7, &p.S8, &p.S9, &p.S10, - } - for _, ps := range all { - pstring(ps) - } -} - -var S1 string -var S2 string -var S3 string -var S4 string -var S5 string -var S6 string -var S7 string -var S8 string -var S9 string -var S10 string diff --git a/misc/cgo/testsanitizers/testdata/asan_linkerx/p/p.go b/misc/cgo/testsanitizers/testdata/asan_linkerx/p/p.go deleted file mode 100644 index c31f00109d..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_linkerx/p/p.go +++ /dev/null @@ -1,12 +0,0 @@ -package p - -var S1 string -var S2 string -var S3 string -var S4 string -var S5 string -var S6 string -var S7 string -var S8 string -var S9 string -var S10 string diff --git a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go deleted file mode 100644 index ec54a66880..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail1.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2022 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 - -import ( - "fmt" - "unsafe" -) - -func main() { - a := 1 - b := 2 - c := add(a, b) - d := a + b - fmt.Println(c, d) -} - -//go:noinline -func add(a1, b1 int) int { - // The arguments. - // When -asan is enabled, unsafe.Pointer(&a1) conversion is escaping. - var p *int = (*int)(unsafe.Add(unsafe.Pointer(&a1), 1*unsafe.Sizeof(int(1)))) - *p = 10 // BOOM - return a1 + b1 -} diff --git a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go deleted file mode 100644 index 70f21275af..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail2.go +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2022 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 - -import ( - "fmt" - "unsafe" -) - -func main() { - a := 1 - b := 2 - c := add(a, b) - d := a + b - fmt.Println(c, d) -} - -//go:noinline -func add(a1, b1 int) (ret int) { - // The return value - // When -asan is enabled, the unsafe.Pointer(&ret) conversion is escaping. - var p *int = (*int)(unsafe.Add(unsafe.Pointer(&ret), 1*unsafe.Sizeof(int(1)))) - *p = 123 // BOOM - ret = a1 + b1 - return -} diff --git a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go b/misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go deleted file mode 100644 index 47a8a072ef..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_unsafe_fail3.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2022 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 - -import ( - "fmt" - "unsafe" -) - -func main() { - a := 1 - b := 2 - // The local variables. - // When -asan is enabled, the unsafe.Pointer(&a) conversion is escaping. - var p *int = (*int)(unsafe.Add(unsafe.Pointer(&a), 1*unsafe.Sizeof(int(1)))) - *p = 20 // BOOM - d := a + b - fmt.Println(d) -} diff --git a/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go b/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go deleted file mode 100644 index 3d3d5a6ab1..0000000000 --- a/misc/cgo/testsanitizers/testdata/asan_useAfterReturn.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -package main - -// The -fsanitize=address option of C compier can detect stack-use-after-return bugs. -// In the following program, the local variable 'local' was moved to heap by the Go -// compiler because foo() is returning the reference to 'local', and return stack of -// foo() will be invalid. Thus for main() to use the reference to 'local', the 'local' -// must be available even after foo() has finished. Therefore, Go has no such issue. - -import "fmt" - -var ptr *int - -func main() { - foo() - fmt.Printf("ptr=%x, %v", *ptr, ptr) -} - -func foo() { - var local int - local = 1 - ptr = &local // local is moved to heap. -} diff --git a/misc/cgo/testsanitizers/testdata/libfuzzer1.go b/misc/cgo/testsanitizers/testdata/libfuzzer1.go deleted file mode 100644 index d178fb1ca0..0000000000 --- a/misc/cgo/testsanitizers/testdata/libfuzzer1.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import "C" - -import "unsafe" - -//export LLVMFuzzerTestOneInput -func LLVMFuzzerTestOneInput(p unsafe.Pointer, sz C.int) C.int { - b := C.GoBytes(p, sz) - if len(b) >= 6 && b[0] == 'F' && b[1] == 'u' && b[2] == 'z' && b[3] == 'z' && b[4] == 'M' && b[5] == 'e' { - panic("found it") - } - return 0 -} - -func main() {} diff --git a/misc/cgo/testsanitizers/testdata/libfuzzer2.c b/misc/cgo/testsanitizers/testdata/libfuzzer2.c deleted file mode 100644 index 567ff5a1cc..0000000000 --- a/misc/cgo/testsanitizers/testdata/libfuzzer2.c +++ /dev/null @@ -1,11 +0,0 @@ -#include <stddef.h> - -#include "libfuzzer2.h" - -int LLVMFuzzerTestOneInput(char *data, size_t size) { - if (size > 0 && data[0] == 'H') - if (size > 1 && data[1] == 'I') - if (size > 2 && data[2] == '!') - FuzzMe(data, size); - return 0; -} diff --git a/misc/cgo/testsanitizers/testdata/libfuzzer2.go b/misc/cgo/testsanitizers/testdata/libfuzzer2.go deleted file mode 100644 index c7a4325976..0000000000 --- a/misc/cgo/testsanitizers/testdata/libfuzzer2.go +++ /dev/null @@ -1,16 +0,0 @@ -package main - -import "C" - -import "unsafe" - -//export FuzzMe -func FuzzMe(p unsafe.Pointer, sz C.int) { - b := C.GoBytes(p, sz) - b = b[3:] - if len(b) >= 4 && b[0] == 'f' && b[1] == 'u' && b[2] == 'z' && b[3] == 'z' { - panic("found it") - } -} - -func main() {} diff --git a/misc/cgo/testsanitizers/testdata/msan.go b/misc/cgo/testsanitizers/testdata/msan.go deleted file mode 100644 index 5d73c38079..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan.go +++ /dev/null @@ -1,35 +0,0 @@ -// 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 main - -/* -#include <stdint.h> - -void f(int32_t *p, int n) { - int i; - - for (i = 0; i < n; i++) { - p[i] = (int32_t)i; - } -} -*/ -import "C" - -import ( - "fmt" - "os" - "unsafe" -) - -func main() { - a := make([]int32, 10) - C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a))) - for i, v := range a { - if i != int(v) { - fmt.Printf("bad %d: %v\n", i, a) - os.Exit(1) - } - } -} diff --git a/misc/cgo/testsanitizers/testdata/msan2.go b/misc/cgo/testsanitizers/testdata/msan2.go deleted file mode 100644 index 6690cb034f..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan2.go +++ /dev/null @@ -1,35 +0,0 @@ -// 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 main - -/* -#include <string.h> -#include <stdint.h> -#include <stdlib.h> - -void f(int32_t *p, int n) { - int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n); - memcpy(p, q, n * sizeof(*p)); - free(q); -} - -void g(int32_t *p, int n) { - if (p[4] != 1) { - abort(); - } -} -*/ -import "C" - -import ( - "unsafe" -) - -func main() { - a := make([]int32, 10) - C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a))) - a[4] = 1 - C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a))) -} diff --git a/misc/cgo/testsanitizers/testdata/msan2_cmsan.go b/misc/cgo/testsanitizers/testdata/msan2_cmsan.go deleted file mode 100644 index 8fdaea90c9..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan2_cmsan.go +++ /dev/null @@ -1,38 +0,0 @@ -// 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 main - -/* -#cgo LDFLAGS: -fsanitize=memory -#cgo CPPFLAGS: -fsanitize=memory - -#include <string.h> -#include <stdint.h> -#include <stdlib.h> - -void f(int32_t *p, int n) { - int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n); - memcpy(p, q, n * sizeof(*p)); - free(q); -} - -void g(int32_t *p, int n) { - if (p[4] != 1) { - abort(); - } -} -*/ -import "C" - -import ( - "unsafe" -) - -func main() { - a := make([]int32, 10) - C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a))) - a[4] = 1 - C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a))) -} diff --git a/misc/cgo/testsanitizers/testdata/msan3.go b/misc/cgo/testsanitizers/testdata/msan3.go deleted file mode 100644 index 61a9c29e1a..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan3.go +++ /dev/null @@ -1,33 +0,0 @@ -// 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 main - -/* -extern int *GoFn(int *); - -// Yes, you can have definitions if you use //export, as long as they are weak. -int f(void) __attribute__ ((weak)); - -int f() { - int i; - int *p = GoFn(&i); - if (*p != 12345) - return 0; - return 1; -} -*/ -import "C" - -//export GoFn -func GoFn(p *C.int) *C.int { - *p = C.int(12345) - return p -} - -func main() { - if r := C.f(); r != 1 { - panic(r) - } -} diff --git a/misc/cgo/testsanitizers/testdata/msan4.go b/misc/cgo/testsanitizers/testdata/msan4.go deleted file mode 100644 index 6c91ff5f09..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan4.go +++ /dev/null @@ -1,50 +0,0 @@ -// 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 main - -// The memory profiler can call copy from a slice on the system stack, -// which msan used to think meant a reference to uninitialized memory. - -/* -#include <time.h> -#include <unistd.h> - -extern void Nop(char*); - -// Use weak as a hack to permit defining a function even though we use export. -void poison() __attribute__ ((weak)); - -// Poison the stack. -void poison() { - char a[1024]; - Nop(&a[0]); -} - -*/ -import "C" - -import ( - "runtime" -) - -func main() { - runtime.MemProfileRate = 1 - start(100) -} - -func start(i int) { - if i == 0 { - return - } - C.poison() - // Tie up a thread. - // We won't actually wait for this sleep to complete. - go func() { C.sleep(1) }() - start(i - 1) -} - -//export Nop -func Nop(*C.char) { -} diff --git a/misc/cgo/testsanitizers/testdata/msan5.go b/misc/cgo/testsanitizers/testdata/msan5.go deleted file mode 100644 index f1479eb8a0..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan5.go +++ /dev/null @@ -1,57 +0,0 @@ -// 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 main - -// Using reflect to set a value was not seen by msan. - -/* -#include <stdlib.h> - -extern void Go1(int*); -extern void Go2(char*); - -// Use weak as a hack to permit defining a function even though we use export. -void C1() __attribute__ ((weak)); -void C2() __attribute__ ((weak)); - -void C1() { - int i; - Go1(&i); - if (i != 42) { - abort(); - } -} - -void C2() { - char a[2]; - a[1] = 42; - Go2(a); - if (a[0] != 42) { - abort(); - } -} -*/ -import "C" - -import ( - "reflect" - "unsafe" -) - -//export Go1 -func Go1(p *C.int) { - reflect.ValueOf(p).Elem().Set(reflect.ValueOf(C.int(42))) -} - -//export Go2 -func Go2(p *C.char) { - a := (*[2]byte)(unsafe.Pointer(p)) - reflect.Copy(reflect.ValueOf(a[:1]), reflect.ValueOf(a[1:])) -} - -func main() { - C.C1() - C.C2() -} diff --git a/misc/cgo/testsanitizers/testdata/msan6.go b/misc/cgo/testsanitizers/testdata/msan6.go deleted file mode 100644 index e96e8f9ead..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan6.go +++ /dev/null @@ -1,75 +0,0 @@ -// 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. - -package main - -// A C function returning a value on the Go stack could leave the Go -// stack marked as uninitialized, potentially causing a later error -// when the stack is used for something else. Issue 26209. - -/* -#cgo LDFLAGS: -fsanitize=memory -#cgo CPPFLAGS: -fsanitize=memory - -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -typedef struct { - uintptr_t a[20]; -} S; - -S f() { - S *p; - - p = (S *)(malloc(sizeof(S))); - p->a[0] = 0; - return *p; -} -*/ -import "C" - -// allocateStack extends the stack so that stack copying doesn't -// confuse the msan data structures. -// -//go:noinline -func allocateStack(i int) int { - if i == 0 { - return i - } - return allocateStack(i - 1) -} - -// F1 marks a chunk of stack as uninitialized. -// C.f returns an uninitialized struct on the stack, so msan will mark -// the stack as uninitialized. -// -//go:noinline -func F1() uintptr { - s := C.f() - return uintptr(s.a[0]) -} - -// F2 allocates a struct on the stack and converts it to an empty interface, -// which will call msanread and see that the data appears uninitialized. -// -//go:noinline -func F2() interface{} { - return C.S{} -} - -func poisonStack(i int) int { - if i == 0 { - return int(F1()) - } - F1() - r := poisonStack(i - 1) - F2() - return r -} - -func main() { - allocateStack(16384) - poisonStack(128) -} diff --git a/misc/cgo/testsanitizers/testdata/msan7.go b/misc/cgo/testsanitizers/testdata/msan7.go deleted file mode 100644 index 2f29fd21b2..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan7.go +++ /dev/null @@ -1,38 +0,0 @@ -// 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. - -package main - -// Test passing C struct to exported Go function. - -/* -#include <stdint.h> -#include <stdlib.h> - -// T is a C struct with alignment padding after b. -// The padding bytes are not considered initialized by MSAN. -// It is big enough to be passed on stack in C ABI (and least -// on AMD64). -typedef struct { char b; uintptr_t x, y; } T; - -extern void F(T); - -// Use weak as a hack to permit defining a function even though we use export. -void CF(int x) __attribute__ ((weak)); -void CF(int x) { - T *t = malloc(sizeof(T)); - t->b = (char)x; - t->x = x; - t->y = x; - F(*t); -} -*/ -import "C" - -//export F -func F(t C.T) { println(t.b, t.x, t.y) } - -func main() { - C.CF(C.int(0)) -} diff --git a/misc/cgo/testsanitizers/testdata/msan8.go b/misc/cgo/testsanitizers/testdata/msan8.go deleted file mode 100644 index 1cb5c5677f..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan8.go +++ /dev/null @@ -1,109 +0,0 @@ -// 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. - -package main - -/* -#include <pthread.h> -#include <signal.h> -#include <stdint.h> - -#include <sanitizer/msan_interface.h> - -// cgoTracebackArg is the type of the argument passed to msanGoTraceback. -struct cgoTracebackArg { - uintptr_t context; - uintptr_t sigContext; - uintptr_t* buf; - uintptr_t max; -}; - -// msanGoTraceback is registered as the cgo traceback function. -// This will be called when a signal occurs. -void msanGoTraceback(void* parg) { - struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg); - arg->buf[0] = 0; -} - -// msanGoWait will be called with all registers undefined as far as -// msan is concerned. It just waits for a signal. -// Because the registers are msan-undefined, the signal handler will -// be invoked with all registers msan-undefined. -__attribute__((noinline)) -void msanGoWait(unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6) { - sigset_t mask; - - sigemptyset(&mask); - sigsuspend(&mask); -} - -// msanGoSignalThread is the thread ID of the msanGoLoop thread. -static pthread_t msanGoSignalThread; - -// msanGoSignalThreadSet is used to record that msanGoSignalThread -// has been initialized. This is accessed atomically. -static int32_t msanGoSignalThreadSet; - -// uninit is explicitly poisoned, so that we can make all registers -// undefined by calling msanGoWait. -static unsigned long uninit; - -// msanGoLoop loops calling msanGoWait, with the arguments passed -// such that msan thinks that they are undefined. msan permits -// undefined values to be used as long as they are not used to -// for conditionals or for memory access. -void msanGoLoop() { - int i; - - msanGoSignalThread = pthread_self(); - __atomic_store_n(&msanGoSignalThreadSet, 1, __ATOMIC_SEQ_CST); - - // Force uninit to be undefined for msan. - __msan_poison(&uninit, sizeof uninit); - for (i = 0; i < 100; i++) { - msanGoWait(uninit, uninit, uninit, uninit, uninit, uninit); - } -} - -// msanGoReady returns whether msanGoSignalThread is set. -int msanGoReady() { - return __atomic_load_n(&msanGoSignalThreadSet, __ATOMIC_SEQ_CST) != 0; -} - -// msanGoSendSignal sends a signal to the msanGoLoop thread. -void msanGoSendSignal() { - pthread_kill(msanGoSignalThread, SIGWINCH); -} -*/ -import "C" - -import ( - "runtime" - "time" -) - -func main() { - runtime.SetCgoTraceback(0, C.msanGoTraceback, nil, nil) - - c := make(chan bool) - go func() { - defer func() { c <- true }() - C.msanGoLoop() - }() - - for C.msanGoReady() == 0 { - time.Sleep(time.Microsecond) - } - -loop: - for { - select { - case <-c: - break loop - default: - C.msanGoSendSignal() - time.Sleep(time.Microsecond) - } - } -} diff --git a/misc/cgo/testsanitizers/testdata/msan_fail.go b/misc/cgo/testsanitizers/testdata/msan_fail.go deleted file mode 100644 index 4c8dab34f6..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan_fail.go +++ /dev/null @@ -1,36 +0,0 @@ -// 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 main - -/* -#include <string.h> -#include <stdint.h> -#include <stdlib.h> - -void f(int32_t *p, int n) { - int32_t * volatile q = (int32_t *)malloc(sizeof(int32_t) * n); - memcpy(p, q, n * sizeof(*p)); - free(q); -} - -void g(int32_t *p, int n) { - if (p[4] != 1) { - // We shouldn't get here; msan should stop us first. - exit(0); - } -} -*/ -import "C" - -import ( - "unsafe" -) - -func main() { - a := make([]int32, 10) - C.f((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a))) - a[3] = 1 - C.g((*C.int32_t)(unsafe.Pointer(&a[0])), C.int(len(a))) -} diff --git a/misc/cgo/testsanitizers/testdata/msan_shared.go b/misc/cgo/testsanitizers/testdata/msan_shared.go deleted file mode 100644 index 966947cac3..0000000000 --- a/misc/cgo/testsanitizers/testdata/msan_shared.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2017 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. - -// This program segfaulted during libpreinit when built with -msan: -// http://golang.org/issue/18707 - -package main - -import "C" - -func main() {} diff --git a/misc/cgo/testsanitizers/testdata/tsan.go b/misc/cgo/testsanitizers/testdata/tsan.go deleted file mode 100644 index 6c377a701f..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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 main - -// This program produced false race reports when run under the C/C++ -// ThreadSanitizer, as it did not understand the synchronization in -// the Go code. - -/* -#cgo CFLAGS: -fsanitize=thread -#cgo LDFLAGS: -fsanitize=thread - -int val; - -int getVal() { - return val; -} - -void setVal(int i) { - val = i; -} -*/ -import "C" - -import ( - "runtime" -) - -func main() { - runtime.LockOSThread() - C.setVal(1) - c := make(chan bool) - go func() { - runtime.LockOSThread() - C.setVal(2) - c <- true - }() - <-c - if v := C.getVal(); v != 2 { - panic(v) - } -} diff --git a/misc/cgo/testsanitizers/testdata/tsan10.go b/misc/cgo/testsanitizers/testdata/tsan10.go deleted file mode 100644 index a40f245553..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan10.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2017 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 - -// This program hung when run under the C/C++ ThreadSanitizer. -// TSAN defers asynchronous signals until the signaled thread calls into libc. -// Since the Go runtime makes direct futex syscalls, Go runtime threads could -// run for an arbitrarily long time without triggering the libc interceptors. -// See https://golang.org/issue/18717. - -import ( - "os" - "os/signal" - "syscall" -) - -/* -#cgo CFLAGS: -g -fsanitize=thread -#cgo LDFLAGS: -g -fsanitize=thread -*/ -import "C" - -func main() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGUSR1) - defer signal.Stop(c) - syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) - <-c -} diff --git a/misc/cgo/testsanitizers/testdata/tsan11.go b/misc/cgo/testsanitizers/testdata/tsan11.go deleted file mode 100644 index 189e10f699..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan11.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 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 - -// This program hung when run under the C/C++ ThreadSanitizer. TSAN defers -// asynchronous signals until the signaled thread calls into libc. The runtime's -// sysmon goroutine idles itself using direct usleep syscalls, so it could -// run for an arbitrarily long time without triggering the libc interceptors. -// See https://golang.org/issue/18717. - -import ( - "os" - "os/signal" - "syscall" -) - -/* -#cgo CFLAGS: -g -fsanitize=thread -#cgo LDFLAGS: -g -fsanitize=thread - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -static void raise_usr2(int signo) { - raise(SIGUSR2); -} - -static void register_handler(int signo) { - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_ONSTACK; - sa.sa_handler = raise_usr2; - - if (sigaction(SIGUSR1, &sa, NULL) != 0) { - perror("failed to register SIGUSR1 handler"); - exit(EXIT_FAILURE); - } -} -*/ -import "C" - -func main() { - ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGUSR2) - - C.register_handler(C.int(syscall.SIGUSR1)) - syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) - - <-ch -} diff --git a/misc/cgo/testsanitizers/testdata/tsan12.go b/misc/cgo/testsanitizers/testdata/tsan12.go deleted file mode 100644 index 0ef545d09b..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan12.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2017 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 - -// This program hung when run under the C/C++ ThreadSanitizer. TSAN installs a -// libc interceptor that writes signal handlers to a global variable within the -// TSAN runtime instead of making a sigaction system call. A bug in -// syscall.runtime_AfterForkInChild corrupted TSAN's signal forwarding table -// during calls to (*os/exec.Cmd).Run, causing the parent process to fail to -// invoke signal handlers. - -import ( - "fmt" - "os" - "os/exec" - "os/signal" - "syscall" -) - -import "C" - -func main() { - ch := make(chan os.Signal, 1) - signal.Notify(ch, syscall.SIGUSR1) - - if err := exec.Command("true").Run(); err != nil { - fmt.Fprintf(os.Stderr, "Unexpected error from `true`: %v", err) - os.Exit(1) - } - - syscall.Kill(syscall.Getpid(), syscall.SIGUSR1) - <-ch -} diff --git a/misc/cgo/testsanitizers/testdata/tsan13.go b/misc/cgo/testsanitizers/testdata/tsan13.go deleted file mode 100644 index ebdf63581b..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan13.go +++ /dev/null @@ -1,90 +0,0 @@ -// 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 - -// This program failed when run under the C/C++ ThreadSanitizer. -// There was no TSAN synchronization for the call to the cgo -// traceback routine. - -/* -#cgo CFLAGS: -g -fsanitize=thread -#cgo LDFLAGS: -g -fsanitize=thread - -#include <pthread.h> -#include <stdint.h> -#include <stdlib.h> -#include <sys/time.h> -#include <unistd.h> - -struct tracebackArg { - uintptr_t Context; - uintptr_t SigContext; - uintptr_t* Buf; - uintptr_t Max; -}; - -void tsanTraceback(struct tracebackArg *arg) { - arg->Buf[0] = 0; -} - -static void* spin(void *arg) { - size_t n; - struct timeval tvstart, tvnow; - int diff; - void *prev; - void *cur; - - prev = NULL; - gettimeofday(&tvstart, NULL); - for (n = 0; n < 1<<20; n++) { - cur = malloc(n); - free(prev); - prev = cur; - - gettimeofday(&tvnow, NULL); - diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec); - - // Profile frequency is 100Hz so we should definitely - // get some signals in 50 milliseconds. - if (diff > 50 * 1000) { - break; - } - } - - free(prev); - - return NULL; -} - -static void runThreads(int n) { - pthread_t ids[64]; - int i; - - if (n > 64) { - n = 64; - } - for (i = 0; i < n; i++) { - pthread_create(&ids[i], NULL, spin, NULL); - } - for (i = 0; i < n; i++) { - pthread_join(ids[i], NULL); - } -} -*/ -import "C" - -import ( - "io" - "runtime" - "runtime/pprof" - "unsafe" -) - -func main() { - runtime.SetCgoTraceback(0, unsafe.Pointer(C.tsanTraceback), nil, nil) - pprof.StartCPUProfile(io.Discard) - C.runThreads(C.int(runtime.GOMAXPROCS(0))) - pprof.StopCPUProfile() -} diff --git a/misc/cgo/testsanitizers/testdata/tsan2.go b/misc/cgo/testsanitizers/testdata/tsan2.go deleted file mode 100644 index 5018a1987c..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan2.go +++ /dev/null @@ -1,55 +0,0 @@ -// 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 main - -// This program produced false race reports when run under the C/C++ -// ThreadSanitizer, as it did not understand the synchronization in -// the Go code. - -/* -#cgo CFLAGS: -fsanitize=thread -#cgo LDFLAGS: -fsanitize=thread - -extern void GoRun(void); - -// Yes, you can have definitions if you use //export, as long as they are weak. - -int val __attribute__ ((weak)); - -int run(void) __attribute__ ((weak)); - -int run() { - val = 1; - GoRun(); - return val; -} - -void setVal(int) __attribute__ ((weak)); - -void setVal(int i) { - val = i; -} -*/ -import "C" - -import "runtime" - -//export GoRun -func GoRun() { - runtime.LockOSThread() - c := make(chan bool) - go func() { - runtime.LockOSThread() - C.setVal(2) - c <- true - }() - <-c -} - -func main() { - if v := C.run(); v != 2 { - panic(v) - } -} diff --git a/misc/cgo/testsanitizers/testdata/tsan3.go b/misc/cgo/testsanitizers/testdata/tsan3.go deleted file mode 100644 index 87f6c80f1b..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan3.go +++ /dev/null @@ -1,40 +0,0 @@ -// 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 main - -// The stubs for the C functions read and write the same slot on the -// g0 stack when copying arguments in and out. - -/* -#cgo CFLAGS: -fsanitize=thread -#cgo LDFLAGS: -fsanitize=thread - -int Func1() { - return 0; -} - -void Func2(int x) { - (void)x; -} -*/ -import "C" - -func main() { - const N = 10000 - done := make(chan bool, N) - for i := 0; i < N; i++ { - go func() { - C.Func1() - done <- true - }() - go func() { - C.Func2(0) - done <- true - }() - } - for i := 0; i < 2*N; i++ { - <-done - } -} diff --git a/misc/cgo/testsanitizers/testdata/tsan4.go b/misc/cgo/testsanitizers/testdata/tsan4.go deleted file mode 100644 index f0c76d8411..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan4.go +++ /dev/null @@ -1,34 +0,0 @@ -// 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 main - -// Check that calls to C.malloc/C.free do not trigger TSAN false -// positive reports. - -// #cgo CFLAGS: -fsanitize=thread -// #cgo LDFLAGS: -fsanitize=thread -// #include <stdlib.h> -import "C" - -import ( - "runtime" - "sync" -) - -func main() { - var wg sync.WaitGroup - for i := 0; i < 10; i++ { - wg.Add(1) - go func() { - defer wg.Done() - for i := 0; i < 100; i++ { - p := C.malloc(C.size_t(i * 10)) - runtime.Gosched() - C.free(p) - } - }() - } - wg.Wait() -} diff --git a/misc/cgo/testsanitizers/testdata/tsan5.go b/misc/cgo/testsanitizers/testdata/tsan5.go deleted file mode 100644 index 1214a7743b..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan5.go +++ /dev/null @@ -1,51 +0,0 @@ -// 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 main - -// Check that calls to C.malloc/C.free do not collide with the calls -// made by the os/user package. - -// #cgo CFLAGS: -fsanitize=thread -// #cgo LDFLAGS: -fsanitize=thread -// #include <stdlib.h> -import "C" - -import ( - "fmt" - "os" - "os/user" - "runtime" - "sync" -) - -func main() { - u, err := user.Current() - if err != nil { - fmt.Fprintln(os.Stderr, err) - // Let the test pass. - os.Exit(0) - } - - var wg sync.WaitGroup - for i := 0; i < 20; i++ { - wg.Add(2) - go func() { - defer wg.Done() - for i := 0; i < 1000; i++ { - user.Lookup(u.Username) - runtime.Gosched() - } - }() - go func() { - defer wg.Done() - for i := 0; i < 1000; i++ { - p := C.malloc(C.size_t(len(u.Username) + 1)) - runtime.Gosched() - C.free(p) - } - }() - } - wg.Wait() -} diff --git a/misc/cgo/testsanitizers/testdata/tsan6.go b/misc/cgo/testsanitizers/testdata/tsan6.go deleted file mode 100644 index c96f08d2f3..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan6.go +++ /dev/null @@ -1,49 +0,0 @@ -// 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 main - -// Check that writes to Go allocated memory, with Go synchronization, -// do not look like a race. - -/* -#cgo CFLAGS: -fsanitize=thread -#cgo LDFLAGS: -fsanitize=thread - -void f(char *p) { - *p = 1; -} -*/ -import "C" - -import ( - "runtime" - "sync" -) - -func main() { - var wg sync.WaitGroup - var mu sync.Mutex - c := make(chan []C.char, 100) - for i := 0; i < 10; i++ { - wg.Add(2) - go func() { - defer wg.Done() - for i := 0; i < 100; i++ { - c <- make([]C.char, 4096) - runtime.Gosched() - } - }() - go func() { - defer wg.Done() - for i := 0; i < 100; i++ { - p := &(<-c)[0] - mu.Lock() - C.f(p) - mu.Unlock() - } - }() - } - wg.Wait() -} diff --git a/misc/cgo/testsanitizers/testdata/tsan7.go b/misc/cgo/testsanitizers/testdata/tsan7.go deleted file mode 100644 index 2fb9e45ee2..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan7.go +++ /dev/null @@ -1,40 +0,0 @@ -// 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 main - -// Setting an environment variable in a cgo program changes the C -// environment. Test that this does not confuse the race detector. - -/* -#cgo CFLAGS: -fsanitize=thread -#cgo LDFLAGS: -fsanitize=thread -*/ -import "C" - -import ( - "fmt" - "os" - "sync" - "time" -) - -func main() { - var wg sync.WaitGroup - var mu sync.Mutex - f := func() { - defer wg.Done() - for i := 0; i < 100; i++ { - time.Sleep(time.Microsecond) - mu.Lock() - s := fmt.Sprint(i) - os.Setenv("TSAN_TEST"+s, s) - mu.Unlock() - } - } - wg.Add(2) - go f() - go f() - wg.Wait() -} diff --git a/misc/cgo/testsanitizers/testdata/tsan8.go b/misc/cgo/testsanitizers/testdata/tsan8.go deleted file mode 100644 index 88d82a6078..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan8.go +++ /dev/null @@ -1,60 +0,0 @@ -// 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 main - -// This program failed when run under the C/C++ ThreadSanitizer. The TSAN -// sigaction function interceptor returned SIG_DFL instead of the Go runtime's -// handler in registerSegvForwarder. - -/* -#cgo CFLAGS: -fsanitize=thread -#cgo LDFLAGS: -fsanitize=thread - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -struct sigaction prev_sa; - -void forwardSignal(int signo, siginfo_t *info, void *context) { - // One of sa_sigaction and/or sa_handler - if ((prev_sa.sa_flags&SA_SIGINFO) != 0) { - prev_sa.sa_sigaction(signo, info, context); - return; - } - if (prev_sa.sa_handler != SIG_IGN && prev_sa.sa_handler != SIG_DFL) { - prev_sa.sa_handler(signo); - return; - } - - fprintf(stderr, "No Go handler to forward to!\n"); - abort(); -} - -void registerSegvFowarder() { - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO | SA_ONSTACK; - sa.sa_sigaction = forwardSignal; - - if (sigaction(SIGSEGV, &sa, &prev_sa) != 0) { - perror("failed to register SEGV forwarder"); - exit(EXIT_FAILURE); - } -} -*/ -import "C" - -func main() { - C.registerSegvFowarder() - - defer func() { - recover() - }() - var nilp *int - *nilp = 42 -} diff --git a/misc/cgo/testsanitizers/testdata/tsan9.go b/misc/cgo/testsanitizers/testdata/tsan9.go deleted file mode 100644 index 06304be751..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan9.go +++ /dev/null @@ -1,67 +0,0 @@ -// 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 main - -// This program failed when run under the C/C++ ThreadSanitizer. The -// TSAN library was not keeping track of whether signals should be -// delivered on the alternate signal stack, and the Go signal handler -// was not preserving callee-saved registers from C callers. - -/* -#cgo CFLAGS: -g -fsanitize=thread -#cgo LDFLAGS: -g -fsanitize=thread - -#include <stdlib.h> -#include <sys/time.h> - -void spin() { - size_t n; - struct timeval tvstart, tvnow; - int diff; - void *prev = NULL, *cur; - - gettimeofday(&tvstart, NULL); - for (n = 0; n < 1<<20; n++) { - cur = malloc(n); - free(prev); - prev = cur; - - gettimeofday(&tvnow, NULL); - diff = (tvnow.tv_sec - tvstart.tv_sec) * 1000 * 1000 + (tvnow.tv_usec - tvstart.tv_usec); - - // Profile frequency is 100Hz so we should definitely - // get a signal in 50 milliseconds. - if (diff > 50 * 1000) { - break; - } - } - - free(prev); -} -*/ -import "C" - -import ( - "io" - "runtime/pprof" - "time" -) - -func goSpin() { - start := time.Now() - for n := 0; n < 1<<20; n++ { - _ = make([]byte, n) - if time.Since(start) > 50*time.Millisecond { - break - } - } -} - -func main() { - pprof.StartCPUProfile(io.Discard) - go C.spin() - goSpin() - pprof.StopCPUProfile() -} diff --git a/misc/cgo/testsanitizers/testdata/tsan_shared.go b/misc/cgo/testsanitizers/testdata/tsan_shared.go deleted file mode 100644 index 55ff67ecba..0000000000 --- a/misc/cgo/testsanitizers/testdata/tsan_shared.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2017 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 - -// This program failed with SIGSEGV when run under the C/C++ ThreadSanitizer. -// The Go runtime had re-registered the C handler with the wrong flags due to a -// typo, resulting in null pointers being passed for the info and context -// parameters to the handler. - -/* -#cgo CFLAGS: -fsanitize=thread -#cgo LDFLAGS: -fsanitize=thread - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <ucontext.h> - -void check_params(int signo, siginfo_t *info, void *context) { - ucontext_t* uc = (ucontext_t*)(context); - - if (info->si_signo != signo) { - fprintf(stderr, "info->si_signo does not match signo.\n"); - abort(); - } - - if (uc->uc_stack.ss_size == 0) { - fprintf(stderr, "uc_stack has size 0.\n"); - abort(); - } -} - - -// Set up the signal handler in a high priority constructor, so -// that it is installed before the Go code starts. - -static void register_handler(void) __attribute__ ((constructor (200))); - -static void register_handler() { - struct sigaction sa; - memset(&sa, 0, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = check_params; - - if (sigaction(SIGUSR1, &sa, NULL) != 0) { - perror("failed to register SIGUSR1 handler"); - exit(EXIT_FAILURE); - } -} -*/ -import "C" - -import "syscall" - -func init() { - C.raise(C.int(syscall.SIGUSR1)) -} - -func main() {} diff --git a/misc/cgo/testsanitizers/tsan_test.go b/misc/cgo/testsanitizers/tsan_test.go deleted file mode 100644 index f65d842363..0000000000 --- a/misc/cgo/testsanitizers/tsan_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2017 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 sanitizers_test - -import ( - "strings" - "testing" -) - -func TestTSAN(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 !compilerRequiredTsanVersion(goos, goarch) { - t.Skipf("skipping on %s/%s; compiler version for -tsan option is too old.", goos, goarch) - } - - t.Parallel() - requireOvercommit(t) - config := configure("thread") - config.skipIfCSanitizerBroken(t) - - mustRun(t, config.goCmd("build", "std")) - - cases := []struct { - src string - needsRuntime bool - }{ - {src: "tsan.go"}, - {src: "tsan2.go"}, - {src: "tsan3.go"}, - {src: "tsan4.go"}, - {src: "tsan5.go", needsRuntime: true}, - {src: "tsan6.go", needsRuntime: true}, - {src: "tsan7.go", needsRuntime: true}, - {src: "tsan8.go"}, - {src: "tsan9.go"}, - {src: "tsan10.go", needsRuntime: true}, - {src: "tsan11.go", needsRuntime: true}, - {src: "tsan12.go", needsRuntime: true}, - {src: "tsan13.go", needsRuntime: true}, - } - for _, tc := range cases { - tc := tc - name := strings.TrimSuffix(tc.src, ".go") - t.Run(name, func(t *testing.T) { - t.Parallel() - - dir := newTempDir(t) - defer dir.RemoveAll(t) - - outPath := dir.Join(name) - mustRun(t, config.goCmd("build", "-o", outPath, srcPath(tc.src))) - - cmd := hangProneCmd(outPath) - if tc.needsRuntime { - config.skipIfRuntimeIncompatible(t) - } - // If we don't see halt_on_error, the program - // will only exit non-zero if we call C.exit. - cmd.Env = append(cmd.Environ(), "TSAN_OPTIONS=halt_on_error=1") - mustRun(t, cmd) - }) - } -} diff --git a/misc/cgo/testshared/overlaydir_test.go b/misc/cgo/testshared/overlaydir_test.go deleted file mode 100644 index eb587a2d44..0000000000 --- a/misc/cgo/testshared/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 shared_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/testshared/shared_test.go b/misc/cgo/testshared/shared_test.go deleted file mode 100644 index 3a8fda05ed..0000000000 --- a/misc/cgo/testshared/shared_test.go +++ /dev/null @@ -1,1124 +0,0 @@ -// 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 shared_test - -import ( - "bufio" - "bytes" - "debug/elf" - "encoding/binary" - "flag" - "fmt" - "go/build" - "io" - "log" - "os" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "sort" - "strconv" - "strings" - "testing" - "time" -) - -var gopathInstallDir, gorootInstallDir string -var oldGOROOT string - -// This is the smallest set of packages we can link into a shared -// library (runtime/cgo is built implicitly). -var minpkgs = []string{"runtime", "sync/atomic"} -var soname = "libruntime,sync-atomic.so" - -var testX = flag.Bool("testx", false, "if true, pass -x to 'go' subcommands invoked by the test") -var testWork = flag.Bool("testwork", false, "if true, log and do not delete the temporary working directory") - -// run runs a command and calls t.Errorf if it fails. -func run(t *testing.T, msg string, args ...string) { - runWithEnv(t, msg, nil, args...) -} - -// runWithEnv runs a command under the given environment and calls t.Errorf if it fails. -func runWithEnv(t *testing.T, msg string, env []string, args ...string) { - c := exec.Command(args[0], args[1:]...) - if len(env) != 0 { - c.Env = append(os.Environ(), env...) - } - if output, err := c.CombinedOutput(); err != nil { - t.Errorf("executing %s (%s) failed %s:\n%s", strings.Join(args, " "), msg, err, output) - } -} - -// goCmd invokes the go tool with the installsuffix set up by TestMain. It calls -// t.Fatalf if the command fails. -func goCmd(t *testing.T, args ...string) string { - newargs := []string{args[0]} - if *testX && args[0] != "env" { - newargs = append(newargs, "-x", "-ldflags=-v") - } - newargs = append(newargs, args[1:]...) - c := exec.Command(filepath.Join(oldGOROOT, "bin", "go"), newargs...) - stderr := new(strings.Builder) - c.Stderr = stderr - - if testing.Verbose() && t == nil { - fmt.Fprintf(os.Stderr, "+ go %s\n", strings.Join(args, " ")) - c.Stderr = os.Stderr - } - output, err := c.Output() - - if err != nil { - if t != nil { - t.Helper() - t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr) - } else { - // Panic instead of using log.Fatalf so that deferred cleanup may run in testMain. - log.Panicf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr) - } - } - if testing.Verbose() && t != nil { - t.Logf("go %s", strings.Join(args, " ")) - if stderr.Len() > 0 { - t.Logf("%s", stderr) - } - } - return string(bytes.TrimSpace(output)) -} - -// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit). -func testMain(m *testing.M) (int, error) { - cwd, err := os.Getwd() - if err != nil { - log.Fatal(err) - } - oldGOROOT = filepath.Join(cwd, "../../..") - - workDir, err := os.MkdirTemp("", "shared_test") - if err != nil { - return 0, err - } - if *testWork || testing.Verbose() { - fmt.Printf("+ mkdir -p %s\n", workDir) - } - if !*testWork { - defer os.RemoveAll(workDir) - } - - // -buildmode=shared fundamentally does not work in module mode. - // (It tries to share package dependencies across builds, but in module mode - // each module has its own distinct set of dependency versions.) - // We would like to eliminate it (see https://go.dev/issue/47788), - // but first need to figure out a replacement that covers the small subset - // of use-cases where -buildmode=shared still works today. - // For now, run the tests in GOPATH mode only. - os.Setenv("GO111MODULE", "off") - - // Some tests need to edit the source in GOPATH, so copy this directory to a - // temporary directory and chdir to that. - gopath := filepath.Join(workDir, "gopath") - modRoot, err := cloneTestdataModule(gopath) - if err != nil { - return 0, err - } - if testing.Verbose() { - fmt.Printf("+ export GOPATH=%s\n", gopath) - fmt.Printf("+ cd %s\n", modRoot) - } - os.Setenv("GOPATH", gopath) - // Explicitly override GOBIN as well, in case it was set through a GOENV file. - os.Setenv("GOBIN", filepath.Join(gopath, "bin")) - os.Chdir(modRoot) - os.Setenv("PWD", modRoot) - - // The test also needs to install libraries into GOROOT/pkg, so copy the - // subset of GOROOT that we need. - // - // TODO(golang.org/issue/28553): Rework -buildmode=shared so that it does not - // need to write to GOROOT. - goroot := filepath.Join(workDir, "goroot") - if err := cloneGOROOTDeps(goroot); err != nil { - return 0, err - } - if testing.Verbose() { - fmt.Fprintf(os.Stderr, "+ export GOROOT=%s\n", goroot) - } - os.Setenv("GOROOT", goroot) - - myContext := build.Default - myContext.GOROOT = goroot - myContext.GOPATH = gopath - - // All tests depend on runtime being built into a shared library. Because - // that takes a few seconds, do it here and have all tests use the version - // built here. - goCmd(nil, append([]string{"install", "-buildmode=shared"}, minpkgs...)...) - - shlib := goCmd(nil, "list", "-linkshared", "-f={{.Shlib}}", "runtime") - if shlib != "" { - gorootInstallDir = filepath.Dir(shlib) - } - - myContext.InstallSuffix = "_dynlink" - depP, err := myContext.Import("./depBase", ".", build.ImportComment) - if err != nil { - return 0, fmt.Errorf("import failed: %v", err) - } - if depP.PkgTargetRoot == "" { - gopathInstallDir = filepath.Dir(goCmd(nil, "list", "-buildmode=shared", "-f", "{{.Target}}", "./depBase")) - } else { - gopathInstallDir = filepath.Join(depP.PkgTargetRoot, "testshared") - } - return m.Run(), nil -} - -func TestMain(m *testing.M) { - log.SetFlags(log.Lshortfile) - flag.Parse() - - exitCode, err := testMain(m) - if err != nil { - log.Fatal(err) - } - os.Exit(exitCode) -} - -// cloneTestdataModule clones the packages from src/testshared into gopath. -// It returns the directory within gopath at which the module root is located. -func cloneTestdataModule(gopath string) (string, error) { - modRoot := filepath.Join(gopath, "src", "testshared") - if err := overlayDir(modRoot, "testdata"); err != nil { - return "", err - } - if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil { - return "", err - } - return modRoot, nil -} - -// cloneGOROOTDeps copies (or symlinks) the portions of GOROOT/src and -// GOROOT/pkg relevant to this test into the given directory. -// It must be run from within the testdata module. -func cloneGOROOTDeps(goroot string) error { - // Before we clone GOROOT, figure out which packages we need to copy over. - listArgs := []string{ - "list", - "-deps", - "-f", "{{if and .Standard (not .ForTest)}}{{.ImportPath}}{{end}}", - } - stdDeps := goCmd(nil, append(listArgs, minpkgs...)...) - testdataDeps := goCmd(nil, append(listArgs, "-test", "./...")...) - - pkgs := append(strings.Split(strings.TrimSpace(stdDeps), "\n"), - strings.Split(strings.TrimSpace(testdataDeps), "\n")...) - sort.Strings(pkgs) - var pkgRoots []string - for _, pkg := range pkgs { - parentFound := false - for _, prev := range pkgRoots { - if pkg == prev || strings.HasPrefix(pkg, prev+"/") { - // We will copy in the source for pkg when we copy in prev. - parentFound = true - break - } - } - if !parentFound { - pkgRoots = append(pkgRoots, pkg) - } - } - - gorootDirs := []string{ - "pkg/tool", - "pkg/include", - } - for _, pkg := range pkgRoots { - gorootDirs = append(gorootDirs, filepath.Join("src", pkg)) - } - - for _, dir := range gorootDirs { - if testing.Verbose() { - fmt.Fprintf(os.Stderr, "+ cp -r %s %s\n", filepath.Join(oldGOROOT, dir), filepath.Join(goroot, dir)) - } - if err := overlayDir(filepath.Join(goroot, dir), filepath.Join(oldGOROOT, dir)); err != nil { - return err - } - } - - return nil -} - -// The shared library was built at the expected location. -func TestSOBuilt(t *testing.T) { - _, err := os.Stat(filepath.Join(gorootInstallDir, soname)) - if err != nil { - t.Error(err) - } -} - -func hasDynTag(f *elf.File, tag elf.DynTag) bool { - ds := f.SectionByType(elf.SHT_DYNAMIC) - if ds == nil { - return false - } - d, err := ds.Data() - if err != nil { - return false - } - for len(d) > 0 { - var t elf.DynTag - switch f.Class { - case elf.ELFCLASS32: - t = elf.DynTag(f.ByteOrder.Uint32(d[0:4])) - d = d[8:] - case elf.ELFCLASS64: - t = elf.DynTag(f.ByteOrder.Uint64(d[0:8])) - d = d[16:] - } - if t == tag { - return true - } - } - return false -} - -// The shared library does not have relocations against the text segment. -func TestNoTextrel(t *testing.T) { - sopath := filepath.Join(gorootInstallDir, soname) - f, err := elf.Open(sopath) - if err != nil { - t.Fatal("elf.Open failed: ", err) - } - defer f.Close() - if hasDynTag(f, elf.DT_TEXTREL) { - t.Errorf("%s has DT_TEXTREL set", soname) - } -} - -// The shared library does not contain symbols called ".dup" -// (See golang.org/issue/14841.) -func TestNoDupSymbols(t *testing.T) { - sopath := filepath.Join(gorootInstallDir, soname) - f, err := elf.Open(sopath) - if err != nil { - t.Fatal("elf.Open failed: ", err) - } - defer f.Close() - syms, err := f.Symbols() - if err != nil { - t.Errorf("error reading symbols %v", err) - return - } - for _, s := range syms { - if s.Name == ".dup" { - t.Fatalf("%s contains symbol called .dup", sopath) - } - } -} - -// The install command should have created a "shlibname" file for the -// listed packages (and runtime/cgo, and math on arm) indicating the -// name of the shared library containing it. -func TestShlibnameFiles(t *testing.T) { - pkgs := append([]string{}, minpkgs...) - pkgs = append(pkgs, "runtime/cgo") - if runtime.GOARCH == "arm" { - pkgs = append(pkgs, "math") - } - for _, pkg := range pkgs { - shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname") - contentsb, err := os.ReadFile(shlibnamefile) - if err != nil { - t.Errorf("error reading shlibnamefile for %s: %v", pkg, err) - continue - } - contents := strings.TrimSpace(string(contentsb)) - if contents != soname { - t.Errorf("shlibnamefile for %s has wrong contents: %q", pkg, contents) - } - } -} - -// Is a given offset into the file contained in a loaded segment? -func isOffsetLoaded(f *elf.File, offset uint64) bool { - for _, prog := range f.Progs { - if prog.Type == elf.PT_LOAD { - if prog.Off <= offset && offset < prog.Off+prog.Filesz { - return true - } - } - } - return false -} - -func rnd(v int32, r int32) int32 { - if r <= 0 { - return v - } - v += r - 1 - c := v % r - if c < 0 { - c += r - } - v -= c - return v -} - -func readwithpad(r io.Reader, sz int32) ([]byte, error) { - data := make([]byte, rnd(sz, 4)) - _, err := io.ReadFull(r, data) - if err != nil { - return nil, err - } - data = data[:sz] - return data, nil -} - -type note struct { - name string - tag int32 - desc string - section *elf.Section -} - -// Read all notes from f. As ELF section names are not supposed to be special, one -// looks for a particular note by scanning all SHT_NOTE sections looking for a note -// with a particular "name" and "tag". -func readNotes(f *elf.File) ([]*note, error) { - var notes []*note - for _, sect := range f.Sections { - if sect.Type != elf.SHT_NOTE { - continue - } - r := sect.Open() - for { - var namesize, descsize, tag int32 - err := binary.Read(r, f.ByteOrder, &namesize) - if err != nil { - if err == io.EOF { - break - } - return nil, fmt.Errorf("read namesize failed: %v", err) - } - err = binary.Read(r, f.ByteOrder, &descsize) - if err != nil { - return nil, fmt.Errorf("read descsize failed: %v", err) - } - err = binary.Read(r, f.ByteOrder, &tag) - if err != nil { - return nil, fmt.Errorf("read type failed: %v", err) - } - name, err := readwithpad(r, namesize) - if err != nil { - return nil, fmt.Errorf("read name failed: %v", err) - } - desc, err := readwithpad(r, descsize) - if err != nil { - return nil, fmt.Errorf("read desc failed: %v", err) - } - notes = append(notes, ¬e{name: string(name), tag: tag, desc: string(desc), section: sect}) - } - } - return notes, nil -} - -func dynStrings(t *testing.T, path string, flag elf.DynTag) []string { - t.Helper() - f, err := elf.Open(path) - if err != nil { - t.Fatalf("elf.Open(%q) failed: %v", path, err) - } - defer f.Close() - dynstrings, err := f.DynString(flag) - if err != nil { - t.Fatalf("DynString(%s) failed on %s: %v", flag, path, err) - } - return dynstrings -} - -func AssertIsLinkedToRegexp(t *testing.T, path string, re *regexp.Regexp) { - t.Helper() - for _, dynstring := range dynStrings(t, path, elf.DT_NEEDED) { - if re.MatchString(dynstring) { - return - } - } - t.Errorf("%s is not linked to anything matching %v", path, re) -} - -func AssertIsLinkedTo(t *testing.T, path, lib string) { - t.Helper() - AssertIsLinkedToRegexp(t, path, regexp.MustCompile(regexp.QuoteMeta(lib))) -} - -func AssertHasRPath(t *testing.T, path, dir string) { - t.Helper() - for _, tag := range []elf.DynTag{elf.DT_RPATH, elf.DT_RUNPATH} { - for _, dynstring := range dynStrings(t, path, tag) { - for _, rpath := range strings.Split(dynstring, ":") { - if filepath.Clean(rpath) == filepath.Clean(dir) { - return - } - } - } - } - t.Errorf("%s does not have rpath %s", path, dir) -} - -// Build a trivial program that links against the shared runtime and check it runs. -func TestTrivialExecutable(t *testing.T) { - goCmd(t, "install", "-linkshared", "./trivial") - run(t, "trivial executable", "../../bin/trivial") - AssertIsLinkedTo(t, "../../bin/trivial", soname) - AssertHasRPath(t, "../../bin/trivial", gorootInstallDir) - // It is 19K on linux/amd64, with separate-code in binutils ld and 64k being most common alignment - // 4*64k should be enough, but this might need revision eventually. - checkSize(t, "../../bin/trivial", 256000) -} - -// Build a trivial program in PIE mode that links against the shared runtime and check it runs. -func TestTrivialExecutablePIE(t *testing.T) { - goCmd(t, "build", "-buildmode=pie", "-o", "trivial.pie", "-linkshared", "./trivial") - run(t, "trivial executable", "./trivial.pie") - AssertIsLinkedTo(t, "./trivial.pie", soname) - AssertHasRPath(t, "./trivial.pie", gorootInstallDir) - // It is 19K on linux/amd64, with separate-code in binutils ld and 64k being most common alignment - // 4*64k should be enough, but this might need revision eventually. - checkSize(t, "./trivial.pie", 256000) -} - -// Check that the file size does not exceed a limit. -func checkSize(t *testing.T, f string, limit int64) { - fi, err := os.Stat(f) - if err != nil { - t.Fatalf("stat failed: %v", err) - } - if sz := fi.Size(); sz > limit { - t.Errorf("file too large: got %d, want <= %d", sz, limit) - } -} - -// Build a division test program and check it runs. -func TestDivisionExecutable(t *testing.T) { - goCmd(t, "install", "-linkshared", "./division") - run(t, "division executable", "../../bin/division") -} - -// Build an executable that uses cgo linked against the shared runtime and check it -// runs. -func TestCgoExecutable(t *testing.T) { - goCmd(t, "install", "-linkshared", "./execgo") - run(t, "cgo executable", "../../bin/execgo") -} - -func checkPIE(t *testing.T, name string) { - f, err := elf.Open(name) - if err != nil { - t.Fatal("elf.Open failed: ", err) - } - defer f.Close() - if f.Type != elf.ET_DYN { - t.Errorf("%s has type %v, want ET_DYN", name, f.Type) - } - if hasDynTag(f, elf.DT_TEXTREL) { - t.Errorf("%s has DT_TEXTREL set", name) - } -} - -func TestTrivialPIE(t *testing.T) { - if strings.HasSuffix(os.Getenv("GO_BUILDER_NAME"), "-alpine") { - t.Skip("skipping on alpine until issue #54354 resolved") - } - name := "trivial_pie" - goCmd(t, "build", "-buildmode=pie", "-o="+name, "./trivial") - defer os.Remove(name) - run(t, name, "./"+name) - checkPIE(t, name) -} - -func TestCgoPIE(t *testing.T) { - name := "cgo_pie" - goCmd(t, "build", "-buildmode=pie", "-o="+name, "./execgo") - defer os.Remove(name) - run(t, name, "./"+name) - checkPIE(t, name) -} - -// Build a GOPATH package into a shared library that links against the goroot runtime -// and an executable that links against both. -func TestGopathShlib(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase") - AssertIsLinkedTo(t, shlib, soname) - goCmd(t, "install", "-linkshared", "./exe") - AssertIsLinkedTo(t, "../../bin/exe", soname) - AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib)) - AssertHasRPath(t, "../../bin/exe", gorootInstallDir) - AssertHasRPath(t, "../../bin/exe", filepath.Dir(gopathInstallDir)) - // And check it runs. - run(t, "executable linked to GOPATH library", "../../bin/exe") -} - -// The shared library contains a note listing the packages it contains in a section -// that is not mapped into memory. -func testPkgListNote(t *testing.T, f *elf.File, note *note) { - if note.section.Flags != 0 { - t.Errorf("package list section has flags %v, want 0", note.section.Flags) - } - if isOffsetLoaded(f, note.section.Offset) { - t.Errorf("package list section contained in PT_LOAD segment") - } - if note.desc != "testshared/depBase\n" { - t.Errorf("incorrect package list %q, want %q", note.desc, "testshared/depBase\n") - } -} - -// The shared library contains a note containing the ABI hash that is mapped into -// memory and there is a local symbol called go.link.abihashbytes that points 16 -// bytes into it. -func testABIHashNote(t *testing.T, f *elf.File, note *note) { - if note.section.Flags != elf.SHF_ALLOC { - t.Errorf("abi hash section has flags %v, want SHF_ALLOC", note.section.Flags) - } - if !isOffsetLoaded(f, note.section.Offset) { - t.Errorf("abihash section not contained in PT_LOAD segment") - } - var hashbytes elf.Symbol - symbols, err := f.Symbols() - if err != nil { - t.Errorf("error reading symbols %v", err) - return - } - for _, sym := range symbols { - if sym.Name == "go:link.abihashbytes" { - hashbytes = sym - } - } - if hashbytes.Name == "" { - t.Errorf("no symbol called go:link.abihashbytes") - return - } - if elf.ST_BIND(hashbytes.Info) != elf.STB_LOCAL { - t.Errorf("%s has incorrect binding %v, want STB_LOCAL", hashbytes.Name, elf.ST_BIND(hashbytes.Info)) - } - if f.Sections[hashbytes.Section] != note.section { - t.Errorf("%s has incorrect section %v, want %s", hashbytes.Name, f.Sections[hashbytes.Section].Name, note.section.Name) - } - if hashbytes.Value-note.section.Addr != 16 { - t.Errorf("%s has incorrect offset into section %d, want 16", hashbytes.Name, hashbytes.Value-note.section.Addr) - } -} - -// A Go shared library contains a note indicating which other Go shared libraries it -// was linked against in an unmapped section. -func testDepsNote(t *testing.T, f *elf.File, note *note) { - if note.section.Flags != 0 { - t.Errorf("package list section has flags %v, want 0", note.section.Flags) - } - if isOffsetLoaded(f, note.section.Offset) { - t.Errorf("package list section contained in PT_LOAD segment") - } - // libdepBase.so just links against the lib containing the runtime. - if note.desc != soname { - t.Errorf("incorrect dependency list %q, want %q", note.desc, soname) - } -} - -// The shared library contains notes with defined contents; see above. -func TestNotes(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - shlib := goCmd(t, "list", "-f", "{{.Shlib}}", "-buildmode=shared", "-linkshared", "./depBase") - f, err := elf.Open(shlib) - if err != nil { - t.Fatal(err) - } - defer f.Close() - notes, err := readNotes(f) - if err != nil { - t.Fatal(err) - } - pkgListNoteFound := false - abiHashNoteFound := false - depsNoteFound := false - for _, note := range notes { - if note.name != "Go\x00\x00" { - continue - } - switch note.tag { - case 1: // ELF_NOTE_GOPKGLIST_TAG - if pkgListNoteFound { - t.Error("multiple package list notes") - } - testPkgListNote(t, f, note) - pkgListNoteFound = true - case 2: // ELF_NOTE_GOABIHASH_TAG - if abiHashNoteFound { - t.Error("multiple abi hash notes") - } - testABIHashNote(t, f, note) - abiHashNoteFound = true - case 3: // ELF_NOTE_GODEPS_TAG - if depsNoteFound { - t.Error("multiple dependency list notes") - } - testDepsNote(t, f, note) - depsNoteFound = true - } - } - if !pkgListNoteFound { - t.Error("package list note not found") - } - if !abiHashNoteFound { - t.Error("abi hash note not found") - } - if !depsNoteFound { - t.Error("deps note not found") - } -} - -// Build a GOPATH package (depBase) into a shared library that links against the goroot -// runtime, another package (dep2) that links against the first, and an -// executable that links against dep2. -func TestTwoGopathShlibs(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2") - goCmd(t, "install", "-linkshared", "./exe2") - run(t, "executable linked to GOPATH library", "../../bin/exe2") -} - -func TestThreeGopathShlibs(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep2") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./dep3") - goCmd(t, "install", "-linkshared", "./exe3") - run(t, "executable linked to GOPATH library", "../../bin/exe3") -} - -// If gccgo is not available or not new enough, call t.Skip. -func requireGccgo(t *testing.T) { - t.Helper() - - gccgoName := os.Getenv("GCCGO") - if gccgoName == "" { - gccgoName = "gccgo" - } - gccgoPath, err := exec.LookPath(gccgoName) - if err != nil { - t.Skip("gccgo not found") - } - cmd := exec.Command(gccgoPath, "-dumpversion") - output, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s -dumpversion failed: %v\n%s", gccgoPath, err, output) - } - dot := bytes.Index(output, []byte{'.'}) - if dot > 0 { - output = output[:dot] - } - major, err := strconv.Atoi(string(output)) - if err != nil { - t.Skipf("can't parse gccgo version number %s", output) - } - if major < 5 { - t.Skipf("gccgo too old (%s)", strings.TrimSpace(string(output))) - } - - gomod, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - t.Fatalf("go env GOMOD: %v", err) - } - if len(bytes.TrimSpace(gomod)) > 0 { - t.Skipf("gccgo not supported in module mode; see golang.org/issue/30344") - } -} - -// Build a GOPATH package into a shared library with gccgo and an executable that -// links against it. -func TestGoPathShlibGccgo(t *testing.T) { - requireGccgo(t) - - libgoRE := regexp.MustCompile("libgo.so.[0-9]+") - - goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase") - - // Run 'go list' after 'go install': with gccgo, we apparently don't know the - // shlib location until after we've installed it. - shlib := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase") - - AssertIsLinkedToRegexp(t, shlib, libgoRE) - goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe") - AssertIsLinkedToRegexp(t, "../../bin/exe", libgoRE) - AssertIsLinkedTo(t, "../../bin/exe", filepath.Base(shlib)) - AssertHasRPath(t, "../../bin/exe", filepath.Dir(shlib)) - // And check it runs. - run(t, "gccgo-built", "../../bin/exe") -} - -// The gccgo version of TestTwoGopathShlibs: build a GOPATH package into a shared -// library with gccgo, another GOPATH package that depends on the first and an -// executable that links the second library. -func TestTwoGopathShlibsGccgo(t *testing.T) { - requireGccgo(t) - - libgoRE := regexp.MustCompile("libgo.so.[0-9]+") - - goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "./dep2") - goCmd(t, "install", "-compiler=gccgo", "-linkshared", "./exe2") - - // Run 'go list' after 'go install': with gccgo, we apparently don't know the - // shlib location until after we've installed it. - dep2 := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./dep2") - depBase := goCmd(t, "list", "-compiler=gccgo", "-buildmode=shared", "-linkshared", "-f", "{{.Shlib}}", "./depBase") - - AssertIsLinkedToRegexp(t, depBase, libgoRE) - AssertIsLinkedToRegexp(t, dep2, libgoRE) - AssertIsLinkedTo(t, dep2, filepath.Base(depBase)) - AssertIsLinkedToRegexp(t, "../../bin/exe2", libgoRE) - AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(dep2)) - AssertIsLinkedTo(t, "../../bin/exe2", filepath.Base(depBase)) - - // And check it runs. - run(t, "gccgo-built", "../../bin/exe2") -} - -// Testing rebuilding of shared libraries when they are stale is a bit more -// complicated that it seems like it should be. First, we make everything "old": but -// only a few seconds old, or it might be older than gc (or the runtime source) and -// everything will get rebuilt. Then define a timestamp slightly newer than this -// time, which is what we set the mtime to of a file to cause it to be seen as new, -// and finally another slightly even newer one that we can compare files against to -// see if they have been rebuilt. -var oldTime = time.Now().Add(-9 * time.Second) -var nearlyNew = time.Now().Add(-6 * time.Second) -var stampTime = time.Now().Add(-3 * time.Second) - -// resetFileStamps makes "everything" (bin, src, pkg from GOPATH and the -// test-specific parts of GOROOT) appear old. -func resetFileStamps() { - chtime := func(path string, info os.FileInfo, err error) error { - return os.Chtimes(path, oldTime, oldTime) - } - reset := func(path string) { - if err := filepath.Walk(path, chtime); err != nil { - log.Panicf("resetFileStamps failed: %v", err) - } - - } - reset("../../bin") - reset("../../pkg") - reset("../../src") - reset(gorootInstallDir) -} - -// touch changes path and returns a function that changes it back. -// 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 := os.ReadFile(path) - if err != nil { - t.Fatal(err) - } - old := make([]byte, len(data)) - copy(old, data) - if bytes.HasPrefix(data, []byte("!<arch>\n")) { - // Change last digit of build ID. - // (Content ID in the new content-based build IDs.) - const marker = `build id "` - i := bytes.Index(data, []byte(marker)) - if i < 0 { - t.Fatal("cannot find build id in archive") - } - j := bytes.IndexByte(data[i+len(marker):], '"') - if j < 0 { - t.Fatal("cannot find build id in archive") - } - i += len(marker) + j - 1 - if data[i] == 'a' { - data[i] = 'b' - } else { - data[i] = 'a' - } - } else { - // assume it's a text file - data = append(data, '\n') - } - - // If the file is still a symlink from an overlay, delete it so that we will - // replace it with a regular file instead of overwriting the symlinked one. - fi, err := os.Lstat(path) - if err == nil && !fi.Mode().IsRegular() { - fi, err = os.Stat(path) - if err := os.Remove(path); err != nil { - t.Fatal(err) - } - } - if err != nil { - t.Fatal(err) - } - - // If we're replacing a symlink to a read-only file, make the new file - // user-writable. - perm := fi.Mode().Perm() | 0200 - - 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 := os.WriteFile(path, old, perm); err != nil { - t.Fatal(err) - } - } -} - -// isNew returns if the path is newer than the time stamp used by touch. -func isNew(t *testing.T, path string) bool { - t.Helper() - fi, err := os.Stat(path) - if err != nil { - t.Fatal(err) - } - return fi.ModTime().After(stampTime) -} - -// Fail unless path has been rebuilt (i.e. is newer than the time stamp used by -// isNew) -func AssertRebuilt(t *testing.T, msg, path string) { - t.Helper() - if !isNew(t, path) { - t.Errorf("%s was not rebuilt (%s)", msg, path) - } -} - -// Fail if path has been rebuilt (i.e. is newer than the time stamp used by isNew) -func AssertNotRebuilt(t *testing.T, msg, path string) { - t.Helper() - if isNew(t, path) { - t.Errorf("%s was rebuilt (%s)", msg, path) - } -} - -func TestRebuilding(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-linkshared", "./exe") - info := strings.Fields(goCmd(t, "list", "-buildmode=shared", "-linkshared", "-f", "{{.Target}} {{.Shlib}}", "./depBase")) - if len(info) != 2 { - t.Fatalf("go list failed to report Target and/or Shlib") - } - target := info[0] - shlib := info[1] - - // If the source is newer than both the .a file and the .so, both are rebuilt. - t.Run("newsource", func(t *testing.T) { - resetFileStamps() - cleanup := touch(t, "./depBase/dep.go") - defer func() { - cleanup() - goCmd(t, "install", "-linkshared", "./exe") - }() - goCmd(t, "install", "-linkshared", "./exe") - AssertRebuilt(t, "new source", target) - AssertRebuilt(t, "new source", shlib) - }) - - // If the .a file is newer than the .so, the .so is rebuilt (but not the .a) - t.Run("newarchive", func(t *testing.T) { - resetFileStamps() - AssertNotRebuilt(t, "new .a file before build", target) - goCmd(t, "list", "-linkshared", "-f={{.ImportPath}} {{.Stale}} {{.StaleReason}} {{.Target}}", "./depBase") - AssertNotRebuilt(t, "new .a file before build", target) - cleanup := touch(t, target) - defer func() { - cleanup() - goCmd(t, "install", "-v", "-linkshared", "./exe") - }() - goCmd(t, "install", "-v", "-linkshared", "./exe") - AssertNotRebuilt(t, "new .a file", target) - AssertRebuilt(t, "new .a file", shlib) - }) -} - -func appendFile(t *testing.T, path, content string) { - t.Helper() - f, err := os.OpenFile(path, os.O_WRONLY|os.O_APPEND, 0660) - if err != nil { - t.Fatalf("os.OpenFile failed: %v", err) - } - defer func() { - err := f.Close() - if err != nil { - t.Fatalf("f.Close failed: %v", err) - } - }() - _, err = f.WriteString(content) - if err != nil { - t.Fatalf("f.WriteString failed: %v", err) - } -} - -func createFile(t *testing.T, path, content string) { - t.Helper() - f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) - if err != nil { - t.Fatalf("os.OpenFile failed: %v", err) - } - _, err = f.WriteString(content) - if closeErr := f.Close(); err == nil { - err = closeErr - } - if err != nil { - t.Fatalf("WriteString failed: %v", err) - } -} - -func TestABIChecking(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - goCmd(t, "install", "-linkshared", "./exe") - - // If we make an ABI-breaking change to depBase and rebuild libp.so but not exe, - // exe will abort with a complaint on startup. - // This assumes adding an exported function breaks ABI, which is not true in - // some senses but suffices for the narrow definition of ABI compatibility the - // toolchain uses today. - resetFileStamps() - - createFile(t, "./depBase/break.go", "package depBase\nfunc ABIBreak() {}\n") - defer os.Remove("./depBase/break.go") - - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - c := exec.Command("../../bin/exe") - output, err := c.CombinedOutput() - if err == nil { - t.Fatal("executing exe did not fail after ABI break") - } - scanner := bufio.NewScanner(bytes.NewReader(output)) - foundMsg := false - const wantPrefix = "abi mismatch detected between the executable and lib" - for scanner.Scan() { - if strings.HasPrefix(scanner.Text(), wantPrefix) { - foundMsg = true - break - } - } - if err = scanner.Err(); err != nil { - t.Errorf("scanner encountered error: %v", err) - } - if !foundMsg { - t.Fatalf("exe failed, but without line %q; got output:\n%s", wantPrefix, output) - } - - // Rebuilding exe makes it work again. - goCmd(t, "install", "-linkshared", "./exe") - run(t, "rebuilt exe", "../../bin/exe") - - // If we make a change which does not break ABI (such as adding an unexported - // function) and rebuild libdepBase.so, exe still works, even if new function - // is in a file by itself. - resetFileStamps() - createFile(t, "./depBase/dep2.go", "package depBase\nfunc noABIBreak() {}\n") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./depBase") - run(t, "after non-ABI breaking change", "../../bin/exe") -} - -// If a package 'explicit' imports a package 'implicit', building -// 'explicit' into a shared library implicitly includes implicit in -// the shared library. Building an executable that imports both -// explicit and implicit builds the code from implicit into the -// executable rather than fetching it from the shared library. The -// link still succeeds and the executable still runs though. -func TestImplicitInclusion(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./explicit") - goCmd(t, "install", "-linkshared", "./implicitcmd") - run(t, "running executable linked against library that contains same package as it", "../../bin/implicitcmd") -} - -// Tests to make sure that the type fields of empty interfaces and itab -// fields of nonempty interfaces are unique even across modules, -// so that interface equality works correctly. -func TestInterface(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_a") - // Note: iface_i gets installed implicitly as a dependency of iface_a. - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./iface_b") - goCmd(t, "install", "-linkshared", "./iface") - run(t, "running type/itab uniqueness tester", "../../bin/iface") -} - -// Access a global variable from a library. -func TestGlobal(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./globallib") - goCmd(t, "install", "-linkshared", "./global") - run(t, "global executable", "../../bin/global") - AssertIsLinkedTo(t, "../../bin/global", soname) - AssertHasRPath(t, "../../bin/global", gorootInstallDir) -} - -// Run a test using -linkshared of an installed shared package. -// Issue 26400. -func TestTestInstalledShared(t *testing.T) { - goCmd(t, "test", "-linkshared", "-test.short", "sync/atomic") -} - -// Test generated pointer method with -linkshared. -// Issue 25065. -func TestGeneratedMethod(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue25065") -} - -// Test use of shared library struct with generated hash function. -// Issue 30768. -func TestGeneratedHash(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue30768/issue30768lib") - goCmd(t, "test", "-linkshared", "./issue30768") -} - -// Test that packages can be added not in dependency order (here a depends on b, and a adds -// before b). This could happen with e.g. go build -buildmode=shared std. See issue 39777. -func TestPackageOrder(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue39777/a", "./issue39777/b") -} - -// Test that GC data are generated correctly by the linker when it needs a type defined in -// a shared library. See issue 39927. -func TestGCData(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./gcdata/p") - goCmd(t, "build", "-linkshared", "./gcdata/main") - runWithEnv(t, "running gcdata/main", []string{"GODEBUG=clobberfree=1"}, "./main") -} - -// Test that we don't decode type symbols from shared libraries (which has no data, -// causing panic). See issue 44031. -func TestIssue44031(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/a") - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue44031/b") - goCmd(t, "run", "-linkshared", "./issue44031/main") -} - -// Test that we use a variable from shared libraries (which implement an -// interface in shared libraries.). A weak reference is used in the itab -// in main process. It can cause unreachable panic. See issue 47873. -func TestIssue47873(t *testing.T) { - goCmd(t, "install", "-buildmode=shared", "-linkshared", "./issue47837/a") - goCmd(t, "run", "-linkshared", "./issue47837/main") -} - -// Test that we can build std in shared mode. -func TestStd(t *testing.T) { - if testing.Short() { - t.Skip("skip in short mode") - } - t.Parallel() - tmpDir := t.TempDir() - // Use a temporary pkgdir to not interfere with other tests, and not write to GOROOT. - // Cannot use goCmd as it runs with cloned GOROOT which is incomplete. - runWithEnv(t, "building std", []string{"GOROOT=" + oldGOROOT}, - filepath.Join(oldGOROOT, "bin", "go"), "install", "-buildmode=shared", "-pkgdir="+tmpDir, "std") - - // Issue #58966. - runWithEnv(t, "testing issue #58966", []string{"GOROOT=" + oldGOROOT}, - filepath.Join(oldGOROOT, "bin", "go"), "run", "-linkshared", "-pkgdir="+tmpDir, "./issue58966/main.go") -} diff --git a/misc/cgo/testshared/testdata/dep2/dep2.go b/misc/cgo/testshared/testdata/dep2/dep2.go deleted file mode 100644 index 94f38cf507..0000000000 --- a/misc/cgo/testshared/testdata/dep2/dep2.go +++ /dev/null @@ -1,15 +0,0 @@ -package dep2 - -import "testshared/depBase" - -var W int = 1 - -var hasProg depBase.HasProg - -type Dep2 struct { - depBase.Dep -} - -func G() int { - return depBase.F() + 1 -} diff --git a/misc/cgo/testshared/testdata/dep3/dep3.go b/misc/cgo/testshared/testdata/dep3/dep3.go deleted file mode 100644 index 6b02ad2ee5..0000000000 --- a/misc/cgo/testshared/testdata/dep3/dep3.go +++ /dev/null @@ -1,22 +0,0 @@ -package dep3 - -// The point of this test file is that it references a type from -// depBase that is also referenced in dep2, but dep2 is loaded by the -// linker before depBase (because it is earlier in the import list). -// There was a bug in the linker where it would not correctly read out -// the type data in this case and later crash. - -import ( - "testshared/dep2" - "testshared/depBase" -) - -type Dep3 struct { - dep depBase.Dep - dep2 dep2.Dep2 -} - -func D3() int { - var x Dep3 - return x.dep.X + x.dep2.X -} diff --git a/misc/cgo/testshared/testdata/depBase/asm.s b/misc/cgo/testshared/testdata/depBase/asm.s deleted file mode 100644 index 51adca3a33..0000000000 --- a/misc/cgo/testshared/testdata/depBase/asm.s +++ /dev/null @@ -1,10 +0,0 @@ -// 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. - -//go:build gc - -#include "textflag.h" - -TEXT ·ImplementedInAsm(SB),NOSPLIT,$0-0 - RET diff --git a/misc/cgo/testshared/testdata/depBase/dep.go b/misc/cgo/testshared/testdata/depBase/dep.go deleted file mode 100644 index e7cc7c81eb..0000000000 --- a/misc/cgo/testshared/testdata/depBase/dep.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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 depBase - -import ( - "os" - "reflect" -) - -var SlicePtr interface{} = &[]int{} - -var V int = 1 - -var HasMask []string = []string{"hi"} - -type HasProg struct { - array [1024]*byte -} - -type Dep struct { - X int -} - -func (d *Dep) Method() int { - // This code below causes various go.itab.* symbols to be generated in - // the shared library. Similar code in ../exe/exe.go results in - // exercising https://golang.org/issues/17594 - reflect.TypeOf(os.Stdout).Elem() - return 10 -} - -func F() int { - defer func() {}() - return V -} diff --git a/misc/cgo/testshared/testdata/depBase/gccgo.go b/misc/cgo/testshared/testdata/depBase/gccgo.go deleted file mode 100644 index a59d0b8c3f..0000000000 --- a/misc/cgo/testshared/testdata/depBase/gccgo.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -//go:build gccgo - -package depBase - -func ImplementedInAsm() {} diff --git a/misc/cgo/testshared/testdata/depBase/stubs.go b/misc/cgo/testshared/testdata/depBase/stubs.go deleted file mode 100644 index c15e4e9a74..0000000000 --- a/misc/cgo/testshared/testdata/depBase/stubs.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -//go:build gc - -package depBase - -func ImplementedInAsm() diff --git a/misc/cgo/testshared/testdata/division/division.go b/misc/cgo/testshared/testdata/division/division.go deleted file mode 100644 index bb5fc98460..0000000000 --- a/misc/cgo/testshared/testdata/division/division.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 - -//go:noinline -func div(x, y uint32) uint32 { - return x / y -} - -func main() { - a := div(97, 11) - if a != 8 { - panic("FAIL") - } -} diff --git a/misc/cgo/testshared/testdata/exe/exe.go b/misc/cgo/testshared/testdata/exe/exe.go deleted file mode 100644 index ee95f97bc9..0000000000 --- a/misc/cgo/testshared/testdata/exe/exe.go +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - "os" - "reflect" - "runtime" - - "testshared/depBase" -) - -// Having a function declared in the main package triggered -// golang.org/issue/18250 -func DeclaredInMain() { -} - -type C struct { -} - -func F() *C { - return nil -} - -var slicePtr interface{} = &[]int{} - -func main() { - defer depBase.ImplementedInAsm() - // This code below causes various go.itab.* symbols to be generated in - // the executable. Similar code in ../depBase/dep.go results in - // exercising https://golang.org/issues/17594 - reflect.TypeOf(os.Stdout).Elem() - runtime.GC() - depBase.V = depBase.F() + 1 - - var c *C - if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) { - panic("bad reflection results, see golang.org/issue/18252") - } - - sp := reflect.New(reflect.TypeOf(slicePtr).Elem()) - s := sp.Interface() - - if reflect.TypeOf(s) != reflect.TypeOf(slicePtr) { - panic("bad reflection results, see golang.org/issue/18729") - } -} diff --git a/misc/cgo/testshared/testdata/exe2/exe2.go b/misc/cgo/testshared/testdata/exe2/exe2.go deleted file mode 100644 index 433f331e36..0000000000 --- a/misc/cgo/testshared/testdata/exe2/exe2.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -import "testshared/dep2" - -func main() { - d := &dep2.Dep2{} - dep2.W = dep2.G() + 1 + d.Method() -} diff --git a/misc/cgo/testshared/testdata/exe3/exe3.go b/misc/cgo/testshared/testdata/exe3/exe3.go deleted file mode 100644 index 533e3a9e3d..0000000000 --- a/misc/cgo/testshared/testdata/exe3/exe3.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -import "testshared/dep3" - -func main() { - dep3.D3() -} diff --git a/misc/cgo/testshared/testdata/execgo/exe.go b/misc/cgo/testshared/testdata/execgo/exe.go deleted file mode 100644 index 0427be8bdf..0000000000 --- a/misc/cgo/testshared/testdata/execgo/exe.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -/* - */ -import "C" - -func main() { -} diff --git a/misc/cgo/testshared/testdata/explicit/explicit.go b/misc/cgo/testshared/testdata/explicit/explicit.go deleted file mode 100644 index af969fcb23..0000000000 --- a/misc/cgo/testshared/testdata/explicit/explicit.go +++ /dev/null @@ -1,9 +0,0 @@ -package explicit - -import ( - "testshared/implicit" -) - -func E() int { - return implicit.I() -} diff --git a/misc/cgo/testshared/testdata/gcdata/main/main.go b/misc/cgo/testshared/testdata/gcdata/main/main.go deleted file mode 100644 index 394862fd94..0000000000 --- a/misc/cgo/testshared/testdata/gcdata/main/main.go +++ /dev/null @@ -1,37 +0,0 @@ -// 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. - -// Test that GC data is generated correctly for global -// variables with types defined in a shared library. -// See issue 39927. - -// This test run under GODEBUG=clobberfree=1. The check -// *x[i] == 12345 depends on this debug mode to clobber -// the value if the object is freed prematurely. - -package main - -import ( - "fmt" - "runtime" - "testshared/gcdata/p" -) - -var x p.T - -func main() { - for i := range x { - x[i] = new(int) - *x[i] = 12345 - } - runtime.GC() - runtime.GC() - runtime.GC() - for i := range x { - if *x[i] != 12345 { - fmt.Printf("x[%d] == %d, want 12345\n", i, *x[i]) - panic("FAIL") - } - } -} diff --git a/misc/cgo/testshared/testdata/gcdata/p/p.go b/misc/cgo/testshared/testdata/gcdata/p/p.go deleted file mode 100644 index 1fee75429e..0000000000 --- a/misc/cgo/testshared/testdata/gcdata/p/p.go +++ /dev/null @@ -1,7 +0,0 @@ -// 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. - -package p - -type T [10]*int diff --git a/misc/cgo/testshared/testdata/global/main.go b/misc/cgo/testshared/testdata/global/main.go deleted file mode 100644 index f43e7c3fb3..0000000000 --- a/misc/cgo/testshared/testdata/global/main.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2017 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 - -import ( - "testshared/globallib" -) - -//go:noinline -func testLoop() { - for i, s := range globallib.Data { - if s != int64(i) { - panic("testLoop: mismatch") - } - } -} - -//go:noinline -func ptrData() *[1<<20 + 10]int64 { - return &globallib.Data -} - -//go:noinline -func testMediumOffset() { - for i, s := range globallib.Data[1<<16-2:] { - if s != int64(i)+1<<16-2 { - panic("testMediumOffset: index mismatch") - } - } - - x := globallib.Data[1<<16-1] - if x != 1<<16-1 { - panic("testMediumOffset: direct mismatch") - } - - y := &globallib.Data[1<<16-3] - if y != &ptrData()[1<<16-3] { - panic("testMediumOffset: address mismatch") - } -} - -//go:noinline -func testLargeOffset() { - for i, s := range globallib.Data[1<<20:] { - if s != int64(i)+1<<20 { - panic("testLargeOffset: index mismatch") - } - } - - x := globallib.Data[1<<20+1] - if x != 1<<20+1 { - panic("testLargeOffset: direct mismatch") - } - - y := &globallib.Data[1<<20+2] - if y != &ptrData()[1<<20+2] { - panic("testLargeOffset: address mismatch") - } -} - -func main() { - testLoop() - - // SSA rules commonly merge offsets into addresses. These - // tests access global data in different ways to try - // and exercise different SSA rules. - testMediumOffset() - testLargeOffset() -} diff --git a/misc/cgo/testshared/testdata/globallib/global.go b/misc/cgo/testshared/testdata/globallib/global.go deleted file mode 100644 index b4372a2e9e..0000000000 --- a/misc/cgo/testshared/testdata/globallib/global.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 globallib - -// Data is large enough to that offsets into it do not fit into -// 16-bit or 20-bit immediates. Ideally we'd also try and overrun -// 32-bit immediates, but that requires the test machine to have -// too much memory. -var Data [1<<20 + 10]int64 - -func init() { - for i := range Data { - Data[i] = int64(i) - } -} diff --git a/misc/cgo/testshared/testdata/iface/main.go b/misc/cgo/testshared/testdata/iface/main.go deleted file mode 100644 index d26ebbcc9c..0000000000 --- a/misc/cgo/testshared/testdata/iface/main.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 - -import "testshared/iface_a" -import "testshared/iface_b" - -func main() { - if iface_a.F() != iface_b.F() { - panic("empty interfaces not equal") - } - if iface_a.G() != iface_b.G() { - panic("non-empty interfaces not equal") - } -} diff --git a/misc/cgo/testshared/testdata/iface_a/a.go b/misc/cgo/testshared/testdata/iface_a/a.go deleted file mode 100644 index e2cef1ecda..0000000000 --- a/misc/cgo/testshared/testdata/iface_a/a.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 iface_a - -import "testshared/iface_i" - -//go:noinline -func F() interface{} { - return (*iface_i.T)(nil) -} - -//go:noinline -func G() iface_i.I { - return (*iface_i.T)(nil) -} diff --git a/misc/cgo/testshared/testdata/iface_b/b.go b/misc/cgo/testshared/testdata/iface_b/b.go deleted file mode 100644 index dd3e027b37..0000000000 --- a/misc/cgo/testshared/testdata/iface_b/b.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 iface_b - -import "testshared/iface_i" - -//go:noinline -func F() interface{} { - return (*iface_i.T)(nil) -} - -//go:noinline -func G() iface_i.I { - return (*iface_i.T)(nil) -} diff --git a/misc/cgo/testshared/testdata/iface_i/i.go b/misc/cgo/testshared/testdata/iface_i/i.go deleted file mode 100644 index 31c80387c7..0000000000 --- a/misc/cgo/testshared/testdata/iface_i/i.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 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 iface_i - -type I interface { - M() -} - -type T struct { -} - -func (t *T) M() { -} - -// *T implements I diff --git a/misc/cgo/testshared/testdata/implicit/implicit.go b/misc/cgo/testshared/testdata/implicit/implicit.go deleted file mode 100644 index 5360188c56..0000000000 --- a/misc/cgo/testshared/testdata/implicit/implicit.go +++ /dev/null @@ -1,5 +0,0 @@ -package implicit - -func I() int { - return 42 -} diff --git a/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go b/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go deleted file mode 100644 index 4d4296738e..0000000000 --- a/misc/cgo/testshared/testdata/implicitcmd/implicitcmd.go +++ /dev/null @@ -1,10 +0,0 @@ -package main - -import ( - "testshared/explicit" - "testshared/implicit" -) - -func main() { - println(implicit.I() + explicit.E()) -} diff --git a/misc/cgo/testshared/testdata/issue25065/a.go b/misc/cgo/testshared/testdata/issue25065/a.go deleted file mode 100644 index 646de4e52f..0000000000 --- a/misc/cgo/testshared/testdata/issue25065/a.go +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -// Package issue25065 has a type with a method that is -// 1. referenced in a method expression -// 2. not called -// 3. not converted to an interface -// 4. is a value method but the reference is to the pointer method -// -// These cases avoid the call to makefuncsym from typecheckfunc, but we -// still need to call makefuncsym somehow or the symbol will not be defined. -package issue25065 - -type T int - -func (t T) M() {} - -func F() func(*T) { - return (*T).M -} diff --git a/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go b/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go deleted file mode 100644 index 9e45ebe683..0000000000 --- a/misc/cgo/testshared/testdata/issue30768/issue30768lib/lib.go +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 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 issue30768lib - -// S is a struct that requires a generated hash function. -type S struct { - A string - B int -} diff --git a/misc/cgo/testshared/testdata/issue30768/x_test.go b/misc/cgo/testshared/testdata/issue30768/x_test.go deleted file mode 100644 index 1bbd139d3e..0000000000 --- a/misc/cgo/testshared/testdata/issue30768/x_test.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 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 issue30768_test - -import ( - "testing" - - "testshared/issue30768/issue30768lib" -) - -type s struct { - s issue30768lib.S -} - -func Test30768(t *testing.T) { - // Calling t.Log will convert S to an empty interface, - // which will force a reference to the generated hash function, - // defined in the shared library. - t.Log(s{}) -} diff --git a/misc/cgo/testshared/testdata/issue39777/a/a.go b/misc/cgo/testshared/testdata/issue39777/a/a.go deleted file mode 100644 index c7bf835951..0000000000 --- a/misc/cgo/testshared/testdata/issue39777/a/a.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -package a - -import "testshared/issue39777/b" - -func F() { b.F() } diff --git a/misc/cgo/testshared/testdata/issue39777/b/b.go b/misc/cgo/testshared/testdata/issue39777/b/b.go deleted file mode 100644 index 4e681965e6..0000000000 --- a/misc/cgo/testshared/testdata/issue39777/b/b.go +++ /dev/null @@ -1,7 +0,0 @@ -// 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. - -package b - -func F() {} diff --git a/misc/cgo/testshared/testdata/issue44031/a/a.go b/misc/cgo/testshared/testdata/issue44031/a/a.go deleted file mode 100644 index 48827e682f..0000000000 --- a/misc/cgo/testshared/testdata/issue44031/a/a.go +++ /dev/null @@ -1,9 +0,0 @@ -// 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. - -package a - -type ATypeWithALoooooongName interface { // a long name, so the type descriptor symbol name is mangled - M() -} diff --git a/misc/cgo/testshared/testdata/issue44031/b/b.go b/misc/cgo/testshared/testdata/issue44031/b/b.go deleted file mode 100644 index ad3ebec2b9..0000000000 --- a/misc/cgo/testshared/testdata/issue44031/b/b.go +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -package b - -import "testshared/issue44031/a" - -type T int - -func (T) M() {} - -var i = a.ATypeWithALoooooongName(T(0)) - -func F() { - i.M() -} diff --git a/misc/cgo/testshared/testdata/issue44031/main/main.go b/misc/cgo/testshared/testdata/issue44031/main/main.go deleted file mode 100644 index 47f2e3a98e..0000000000 --- a/misc/cgo/testshared/testdata/issue44031/main/main.go +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -package main - -import "testshared/issue44031/b" - -type t int - -func (t) m() {} - -type i interface{ m() } // test that unexported method is correctly marked - -var v interface{} = t(0) - -func main() { - b.F() - v.(i).m() -} diff --git a/misc/cgo/testshared/testdata/issue47837/a/a.go b/misc/cgo/testshared/testdata/issue47837/a/a.go deleted file mode 100644 index 68588eda2f..0000000000 --- a/misc/cgo/testshared/testdata/issue47837/a/a.go +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -package a - -type A interface { - M() -} - -//go:noinline -func TheFuncWithArgA(a A) { - a.M() -} - -type ImplA struct{} - -//go:noinline -func (A *ImplA) M() {} diff --git a/misc/cgo/testshared/testdata/issue47837/main/main.go b/misc/cgo/testshared/testdata/issue47837/main/main.go deleted file mode 100644 index 77c6f34379..0000000000 --- a/misc/cgo/testshared/testdata/issue47837/main/main.go +++ /dev/null @@ -1,14 +0,0 @@ -// 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. - -package main - -import ( - "testshared/issue47837/a" -) - -func main() { - var vara a.ImplA - a.TheFuncWithArgA(&vara) -} diff --git a/misc/cgo/testshared/testdata/issue58966/main.go b/misc/cgo/testshared/testdata/issue58966/main.go deleted file mode 100644 index 2d923c3607..0000000000 --- a/misc/cgo/testshared/testdata/issue58966/main.go +++ /dev/null @@ -1,15 +0,0 @@ -// 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 - -import "crypto/elliptic" - -var curve elliptic.Curve - -func main() { - switch curve { - case elliptic.P224(): - } -} diff --git a/misc/cgo/testshared/testdata/trivial/trivial.go b/misc/cgo/testshared/testdata/trivial/trivial.go deleted file mode 100644 index 6ade47ce36..0000000000 --- a/misc/cgo/testshared/testdata/trivial/trivial.go +++ /dev/null @@ -1,9 +0,0 @@ -package main - -func main() { - // This is enough to make sure that the executable references - // a type descriptor, which was the cause of - // https://golang.org/issue/25970. - c := make(chan int) - _ = c -} diff --git a/misc/cgo/testso/noso_test.go b/misc/cgo/testso/noso_test.go deleted file mode 100644 index 45b13e1928..0000000000 --- a/misc/cgo/testso/noso_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2019 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 - -package so_test - -// Nothing to test. diff --git a/misc/cgo/testso/overlaydir_test.go b/misc/cgo/testso/overlaydir_test.go deleted file mode 100644 index 09a1d512f1..0000000000 --- a/misc/cgo/testso/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 so_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/testso/so_test.go b/misc/cgo/testso/so_test.go deleted file mode 100644 index 5c460d21b6..0000000000 --- a/misc/cgo/testso/so_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2019 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 - -package so_test - -import ( - "log" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "testing" -) - -func requireTestSOSupported(t *testing.T) { - t.Helper() - switch runtime.GOARCH { - case "arm64": - if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { - t.Skip("No exec facility on iOS.") - } - case "ppc64": - if runtime.GOOS == "linux" { - t.Skip("External linking not implemented on linux/ppc64 (issue #8912).") - } - } - if runtime.GOOS == "android" { - t.Skip("No exec facility on Android.") - } -} - -func TestSO(t *testing.T) { - requireTestSOSupported(t) - - GOPATH, err := os.MkdirTemp("", "cgosotest") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(GOPATH) - - modRoot := filepath.Join(GOPATH, "src", "cgosotest") - if err := overlayDir(modRoot, "testdata"); err != nil { - log.Panic(err) - } - if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { - log.Panic(err) - } - - cmd := exec.Command("go", "env", "CC", "GOGCCFLAGS") - cmd.Dir = modRoot - cmd.Stderr = new(strings.Builder) - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - out, err := cmd.Output() - if err != nil { - t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) - } - lines := strings.Split(string(out), "\n") - if len(lines) != 3 || lines[2] != "" { - t.Fatalf("Unexpected output from %s:\n%s", strings.Join(cmd.Args, " "), lines) - } - - cc := lines[0] - if cc == "" { - t.Fatal("CC environment variable (go env CC) cannot be empty") - } - gogccflags := strings.Split(lines[1], " ") - - // build shared object - ext := "so" - args := append(gogccflags, "-shared") - switch runtime.GOOS { - case "darwin", "ios": - ext = "dylib" - args = append(args, "-undefined", "suppress", "-flat_namespace") - 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" - } - sofname := "libcgosotest." + ext - args = append(args, "-o", sofname, "cgoso_c.c") - - cmd = exec.Command(cc, args...) - cmd.Dir = modRoot - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) - - if runtime.GOOS == "aix" { - // Shared object must be wrapped by an archive - cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1") - cmd.Dir = modRoot - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - } - - cmd = exec.Command("go", "build", "-o", "main.exe", "main.go") - cmd.Dir = modRoot - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) - - cmd = exec.Command("./main.exe") - cmd.Dir = modRoot - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - if runtime.GOOS != "windows" { - s := "LD_LIBRARY_PATH" - if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { - s = "DYLD_LIBRARY_PATH" - } - cmd.Env = append(os.Environ(), s+"=.") - - // On FreeBSD 64-bit architectures, the 32-bit linker looks for - // different environment variables. - if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { - cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.") - } - } - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) -} diff --git a/misc/cgo/testso/testdata/cgoso.c b/misc/cgo/testso/testdata/cgoso.c deleted file mode 100644 index 612e5d335a..0000000000 --- a/misc/cgo/testso/testdata/cgoso.c +++ /dev/null @@ -1,14 +0,0 @@ -// 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 "_cgo_export.h" - -#if defined(WIN32) || defined(_AIX) -extern void setCallback(void *); -void init() { - setCallback(goCallback); -} -#else -void init() {} -#endif diff --git a/misc/cgo/testso/testdata/cgoso.go b/misc/cgo/testso/testdata/cgoso.go deleted file mode 100644 index b59b2a8e8b..0000000000 --- a/misc/cgo/testso/testdata/cgoso.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2011 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 cgosotest - -/* -// intentionally write the same LDFLAGS differently -// to test correct handling of LDFLAGS. -#cgo linux LDFLAGS: -L. -lcgosotest -#cgo dragonfly LDFLAGS: -L. -l cgosotest -#cgo freebsd LDFLAGS: -L. -l cgosotest -#cgo openbsd LDFLAGS: -L. -l cgosotest -#cgo solaris LDFLAGS: -L. -lcgosotest -#cgo netbsd LDFLAGS: -L. libcgosotest.so -#cgo darwin LDFLAGS: -L. libcgosotest.dylib -#cgo windows LDFLAGS: -L. libcgosotest.a -#cgo aix LDFLAGS: -L. -l cgosotest - -void init(void); -void sofunc(void); -*/ -import "C" - -func Test() { - C.init() - C.sofunc() -} - -//export goCallback -func goCallback() { -} diff --git a/misc/cgo/testso/testdata/cgoso_c.c b/misc/cgo/testso/testdata/cgoso_c.c deleted file mode 100644 index d5fb559f83..0000000000 --- a/misc/cgo/testso/testdata/cgoso_c.c +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2011 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 ignore - -#ifdef WIN32 -// A Windows DLL is unable to call an arbitrary function in -// the main executable. Work around that by making the main -// executable pass the callback function pointer to us. -void (*goCallback)(void); -__declspec(dllexport) void setCallback(void *f) -{ - goCallback = (void (*)())f; -} -__declspec(dllexport) void sofunc(void); -#elif defined(_AIX) -// AIX doesn't allow the creation of a shared object with an -// undefined symbol. It's possible to bypass this problem by -// using -Wl,-G and -Wl,-brtl option which allows run-time linking. -// However, that's not how most of AIX shared object works. -// Therefore, it's better to consider goCallback as a pointer and -// to set up during an init function. -void (*goCallback)(void); -void setCallback(void *f) { goCallback = f; } -#else -extern void goCallback(void); -void setCallback(void *f) { (void)f; } -#endif - -// OpenBSD and older Darwin lack TLS support -#if !defined(__OpenBSD__) && !defined(__APPLE__) -__thread int tlsvar = 12345; -#endif - -void sofunc(void) -{ - goCallback(); -} diff --git a/misc/cgo/testso/testdata/cgoso_unix.go b/misc/cgo/testso/testdata/cgoso_unix.go deleted file mode 100644 index ea9cb0a903..0000000000 --- a/misc/cgo/testso/testdata/cgoso_unix.go +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -//go:build aix || dragonfly || freebsd || linux || netbsd || solaris - -package cgosotest - -/* -extern int __thread tlsvar; -int *getTLS() { return &tlsvar; } -*/ -import "C" - -func init() { - if v := *C.getTLS(); v != 12345 { - println("got", v) - panic("BAD TLS value") - } -} diff --git a/misc/cgo/testso/testdata/main.go b/misc/cgo/testso/testdata/main.go deleted file mode 100644 index 84382f739c..0000000000 --- a/misc/cgo/testso/testdata/main.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2011 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 ignore - -package main - -import "cgosotest" - -func main() { - cgosotest.Test() -} diff --git a/misc/cgo/testsovar/noso_test.go b/misc/cgo/testsovar/noso_test.go deleted file mode 100644 index 45b13e1928..0000000000 --- a/misc/cgo/testsovar/noso_test.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2019 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 - -package so_test - -// Nothing to test. diff --git a/misc/cgo/testsovar/overlaydir_test.go b/misc/cgo/testsovar/overlaydir_test.go deleted file mode 100644 index 09a1d512f1..0000000000 --- a/misc/cgo/testsovar/overlaydir_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 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 so_test - -import ( - "io" - "os" - "path/filepath" - "strings" -) - -// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. -// -// TODO: Once we no longer need to support the misc module in GOPATH mode, -// factor this function out into a package to reduce duplication. -func overlayDir(dstRoot, srcRoot string) error { - dstRoot = filepath.Clean(dstRoot) - if err := os.MkdirAll(dstRoot, 0777); err != nil { - return err - } - - srcRoot, err := filepath.Abs(srcRoot) - if err != nil { - return err - } - - return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { - if err != nil || srcPath == srcRoot { - return err - } - - suffix := strings.TrimPrefix(srcPath, srcRoot) - for len(suffix) > 0 && suffix[0] == filepath.Separator { - suffix = suffix[1:] - } - dstPath := filepath.Join(dstRoot, suffix) - - perm := info.Mode() & os.ModePerm - if info.Mode()&os.ModeSymlink != 0 { - info, err = os.Stat(srcPath) - if err != nil { - return err - } - perm = info.Mode() & os.ModePerm - } - - // Always copy directories (don't symlink them). - // If we add a file in the overlay, we don't want to add it in the original. - if info.IsDir() { - return os.MkdirAll(dstPath, perm|0200) - } - - // If the OS supports symlinks, use them instead of copying bytes. - if err := os.Symlink(srcPath, dstPath); err == nil { - return nil - } - - // Otherwise, copy the bytes. - src, err := os.Open(srcPath) - if err != nil { - return err - } - defer src.Close() - - dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) - if err != nil { - return err - } - - _, err = io.Copy(dst, src) - if closeErr := dst.Close(); err == nil { - err = closeErr - } - return err - }) -} diff --git a/misc/cgo/testsovar/so_test.go b/misc/cgo/testsovar/so_test.go deleted file mode 100644 index 5c460d21b6..0000000000 --- a/misc/cgo/testsovar/so_test.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2019 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 - -package so_test - -import ( - "log" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "testing" -) - -func requireTestSOSupported(t *testing.T) { - t.Helper() - switch runtime.GOARCH { - case "arm64": - if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { - t.Skip("No exec facility on iOS.") - } - case "ppc64": - if runtime.GOOS == "linux" { - t.Skip("External linking not implemented on linux/ppc64 (issue #8912).") - } - } - if runtime.GOOS == "android" { - t.Skip("No exec facility on Android.") - } -} - -func TestSO(t *testing.T) { - requireTestSOSupported(t) - - GOPATH, err := os.MkdirTemp("", "cgosotest") - if err != nil { - log.Fatal(err) - } - defer os.RemoveAll(GOPATH) - - modRoot := filepath.Join(GOPATH, "src", "cgosotest") - if err := overlayDir(modRoot, "testdata"); err != nil { - log.Panic(err) - } - if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil { - log.Panic(err) - } - - cmd := exec.Command("go", "env", "CC", "GOGCCFLAGS") - cmd.Dir = modRoot - cmd.Stderr = new(strings.Builder) - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - out, err := cmd.Output() - if err != nil { - t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr) - } - lines := strings.Split(string(out), "\n") - if len(lines) != 3 || lines[2] != "" { - t.Fatalf("Unexpected output from %s:\n%s", strings.Join(cmd.Args, " "), lines) - } - - cc := lines[0] - if cc == "" { - t.Fatal("CC environment variable (go env CC) cannot be empty") - } - gogccflags := strings.Split(lines[1], " ") - - // build shared object - ext := "so" - args := append(gogccflags, "-shared") - switch runtime.GOOS { - case "darwin", "ios": - ext = "dylib" - args = append(args, "-undefined", "suppress", "-flat_namespace") - 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" - } - sofname := "libcgosotest." + ext - args = append(args, "-o", sofname, "cgoso_c.c") - - cmd = exec.Command(cc, args...) - cmd.Dir = modRoot - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) - - if runtime.GOOS == "aix" { - // Shared object must be wrapped by an archive - cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1") - cmd.Dir = modRoot - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - } - - cmd = exec.Command("go", "build", "-o", "main.exe", "main.go") - cmd.Dir = modRoot - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) - - cmd = exec.Command("./main.exe") - cmd.Dir = modRoot - cmd.Env = append(os.Environ(), "GOPATH="+GOPATH) - if runtime.GOOS != "windows" { - s := "LD_LIBRARY_PATH" - if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { - s = "DYLD_LIBRARY_PATH" - } - cmd.Env = append(os.Environ(), s+"=.") - - // On FreeBSD 64-bit architectures, the 32-bit linker looks for - // different environment variables. - if runtime.GOOS == "freebsd" && runtime.GOARCH == "386" { - cmd.Env = append(cmd.Env, "LD_32_LIBRARY_PATH=.") - } - } - out, err = cmd.CombinedOutput() - if err != nil { - t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out) - } - t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out) -} diff --git a/misc/cgo/testsovar/testdata/cgoso.go b/misc/cgo/testsovar/testdata/cgoso.go deleted file mode 100644 index d9deb556da..0000000000 --- a/misc/cgo/testsovar/testdata/cgoso.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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 cgosotest - -// This test verifies that Go can access C variables -// in shared object file via cgo. - -/* -// intentionally write the same LDFLAGS differently -// to test correct handling of LDFLAGS. -#cgo windows CFLAGS: -DIMPORT_DLL -#cgo linux LDFLAGS: -L. -lcgosotest -#cgo dragonfly LDFLAGS: -L. -l cgosotest -#cgo freebsd LDFLAGS: -L. -l cgosotest -#cgo openbsd LDFLAGS: -L. -l cgosotest -#cgo solaris LDFLAGS: -L. -lcgosotest -#cgo netbsd LDFLAGS: -L. libcgosotest.so -#cgo darwin LDFLAGS: -L. libcgosotest.dylib -#cgo windows LDFLAGS: -L. libcgosotest.a -#cgo aix LDFLAGS: -L. -l cgosotest - -#include "cgoso_c.h" - -const char* getVar() { - return exported_var; -} -*/ -import "C" - -import "fmt" - -func Test() { - const want = "Hello world" - got := C.GoString(C.getVar()) - if got != want { - panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want)) - } - got = C.GoString(C.exported_var) - if got != want { - panic(fmt.Sprintf("testExportedVar: got %q, but want %q", got, want)) - } -} diff --git a/misc/cgo/testsovar/testdata/cgoso_c.c b/misc/cgo/testsovar/testdata/cgoso_c.c deleted file mode 100644 index 36f4d570ee..0000000000 --- a/misc/cgo/testsovar/testdata/cgoso_c.c +++ /dev/null @@ -1,7 +0,0 @@ -// 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. - -//go:build ignore - -const char *exported_var = "Hello world"; diff --git a/misc/cgo/testsovar/testdata/cgoso_c.h b/misc/cgo/testsovar/testdata/cgoso_c.h deleted file mode 100644 index eccd8c0d0c..0000000000 --- a/misc/cgo/testsovar/testdata/cgoso_c.h +++ /dev/null @@ -1,17 +0,0 @@ -// 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. - -//go:build ignore - -#ifdef WIN32 -#if defined(EXPORT_DLL) -# define VAR __declspec(dllexport) -#elif defined(IMPORT_DLL) -# define VAR __declspec(dllimport) -#endif -#else -# define VAR extern -#endif - -VAR const char *exported_var; diff --git a/misc/cgo/testsovar/testdata/main.go b/misc/cgo/testsovar/testdata/main.go deleted file mode 100644 index 018b835c6c..0000000000 --- a/misc/cgo/testsovar/testdata/main.go +++ /dev/null @@ -1,13 +0,0 @@ -// 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. - -//go:build ignore - -package main - -import "cgosotest" - -func main() { - cgosotest.Test() -} |