diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-06-07 12:27:24 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-06-07 12:27:36 -0700 |
commit | 0e39cdc0e9d76ba06d8cf3096ab94f17b1ffefb3 (patch) | |
tree | 11c736d419de5f33c484cb025b3c9cddbdcdb918 /src/cmd | |
parent | 7c8a5be2d6f26caed84c6bae2a115872af5b1021 (diff) | |
parent | 821270787109408ae7c86a01ccc93162be9c020c (diff) | |
download | go-0e39cdc0e9d76ba06d8cf3096ab94f17b1ffefb3.tar.gz go-0e39cdc0e9d76ba06d8cf3096ab94f17b1ffefb3.zip |
[dev.typeparams] all: merge master (8212707) into dev.typeparams
Conflicts:
- src/go/internal/gcimporter/iimport.go
CL 325429 and CL 319931 made unrelated changes to adjacent lines
Merge List:
+ 2021-06-07 8212707871 crypto/elliptic: update P-521 docs to say it's constant-time
+ 2021-06-07 7406180012 fmt: split package documentation into more sections
+ 2021-06-07 e3176bbc3e crypto/tls: fix typo in Config.NextProtos docs
+ 2021-06-05 e1fa26026d spec: improve wording consistency by eliminating "specifier"
+ 2021-06-05 f490134126 spec: improve wording by choosing an official term "keyword"
+ 2021-06-05 e3cb381704 go/internal/gcimporter: don't waste CPU copying bytes in `io.ReadAll`
+ 2021-06-05 9d669ed47a misc/cgo/errors: use expected column numbers
+ 2021-06-04 95939e8de7 cmd/compile/internal/abi: fix typo in comment
+ 2021-06-04 831f9376d8 net/http: fix ResponseWriter.ReadFrom with short reads
+ 2021-06-04 3a9d906edc os: avoid finalizer race in windows process object
+ 2021-06-04 105c5b50e0 os: terminate windows processes via handle directly
+ 2021-06-04 79cd407f88 syscall: regenerate zsyscall_windows.go
+ 2021-06-04 c6b6211229 doc/go1.17: document testing changes for Go 1.17
+ 2021-06-04 0214440075 syscall: do not pass console handles to PROC_THREAD_ATTRIBUTE_HANDLE_LIST on Windows 7
+ 2021-06-04 962d5c997a cmd/compile,go/types: restrict use of unsafe.{Add,Slice} to go1.17 or newer
+ 2021-06-04 b29b123e07 cmd/compile: remove spurious ir.Dump
+ 2021-06-03 6d98301114 cmd/link: use correct alignment in PE DWARF sections
+ 2021-06-03 e0d029f758 runtime: avoid gp.lockedm race in exitsyscall0
+ 2021-06-02 dd7ba3ba2c net: don't rely on system hosts in TestCVE202133195
+ 2021-06-02 4f572d7076 io/fs: minor corrections to Sub docs
+ 2021-06-02 e11d14225c doc/go1.17: remove runtime section
+ 2021-06-02 6e189afd3e doc/go1.17: mention SYS_WAIT6/WEXITED on NetBSD
+ 2021-06-02 ff9f5fb859 cmd/link: recognize clang linker error in testCGOLTO
+ 2021-06-02 1c6a2ea2ea doc/go1.17: document time changes for Go1.17
+ 2021-06-02 d743e67e06 doc/go1.17: document flag changes for Go 1.17
+ 2021-06-02 dc8f87b749 runtime/internal/sys: generate //go:build lines in gengoos.go
+ 2021-06-02 84c0e5d47f cmd/link: move issue 43830 tests out of TestScript
+ 2021-06-02 cae68700cc runtime: fix formatting
+ 2021-06-01 567ee865f6 cmd/go: add declaration to cgo_lto_issue43830 test
+ 2021-06-01 24e9707cbf cmd/link, cmd/cgo: support -flto in CFLAGS
Change-Id: I9ef88e7de0f8b1841ed9604b613b41672df67e71
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/cgo/gcc.go | 2 | ||||
-rw-r--r-- | src/cmd/cgo/out.go | 16 | ||||
-rw-r--r-- | src/cmd/compile/internal/abi/abiutils.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/noder.go | 3 | ||||
-rw-r--r-- | src/cmd/compile/internal/typecheck/func.go | 12 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/builtins.go | 10 | ||||
-rw-r--r-- | src/cmd/dist/test.go | 29 | ||||
-rw-r--r-- | src/cmd/link/cgo_test.go | 141 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/ar.go | 4 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/config.go | 6 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/lib.go | 26 | ||||
-rw-r--r-- | src/cmd/link/internal/ld/pe.go | 2 |
12 files changed, 233 insertions, 20 deletions
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index ae61725bc7..a73e998877 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -1638,6 +1638,8 @@ func (p *Package) gccCmd() []string { c = append(c, "-maix64") c = append(c, "-mcmodel=large") } + // disable LTO so we get an object whose symbols we can read + c = append(c, "-fno-lto") c = append(c, "-") //read input from standard input return c } diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 8c31d5b794..94152f4278 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -168,8 +168,18 @@ func (p *Package) writeDefs() { if *gccgo { fmt.Fprintf(fc, "extern byte *%s;\n", n.C) } else { - fmt.Fprintf(fm, "extern char %s[];\n", n.C) - fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) + // Force a reference to all symbols so that + // the external linker will add DT_NEEDED + // entries as needed on ELF systems. + // Treat function variables differently + // to avoid type confict errors from LTO + // (Link Time Optimization). + if n.Kind == "fpvar" { + fmt.Fprintf(fm, "extern void %s();\n", n.C) + } else { + fmt.Fprintf(fm, "extern char %s[];\n", n.C) + fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C) + } fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C) fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C) fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C) @@ -1042,7 +1052,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) { // This unpacks the argument struct above and calls the Go function. fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a *%s) {\n", cPrefix, exp.ExpName, gotype) - fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName) + fmt.Fprintf(fm, "void _cgoexp%s_%s(void* p){}\n", cPrefix, exp.ExpName) if gccResult != "void" { // Write results back to frame. diff --git a/src/cmd/compile/internal/abi/abiutils.go b/src/cmd/compile/internal/abi/abiutils.go index cb8e9d7b0f..b8ea1955d1 100644 --- a/src/cmd/compile/internal/abi/abiutils.go +++ b/src/cmd/compile/internal/abi/abiutils.go @@ -449,7 +449,7 @@ func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResul // parameterUpdateMu protects the Offset field of function/method parameters (a subset of structure Fields) var parameterUpdateMu sync.Mutex -// FieldOffsetOf returns a concurency-safe version of f.Offset +// FieldOffsetOf returns a concurrency-safe version of f.Offset func FieldOffsetOf(f *types.Field) int64 { parameterUpdateMu.Lock() defer parameterUpdateMu.Unlock() diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go index 2fb852b184..08c05a69be 100644 --- a/src/cmd/compile/internal/noder/noder.go +++ b/src/cmd/compile/internal/noder/noder.go @@ -886,9 +886,6 @@ func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype { if n == nil { return nil } - if _, ok := n.(ir.Ntype); !ok { - ir.Dump("NOT NTYPE", n) - } return n.(ir.Ntype) } diff --git a/src/cmd/compile/internal/typecheck/func.go b/src/cmd/compile/internal/typecheck/func.go index f9ee686f9e..15756a47e4 100644 --- a/src/cmd/compile/internal/typecheck/func.go +++ b/src/cmd/compile/internal/typecheck/func.go @@ -999,6 +999,12 @@ func tcRecover(n *ir.CallExpr) ir.Node { // tcUnsafeAdd typechecks an OUNSAFEADD node. func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr { + if !types.AllowsGoVersion(curpkg(), 1, 17) { + base.ErrorfVers("go1.17", "unsafe.Add") + n.SetType(nil) + return n + } + n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add") n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT]) if n.X.Type() == nil || n.Y.Type() == nil { @@ -1015,6 +1021,12 @@ func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr { // tcUnsafeSlice typechecks an OUNSAFESLICE node. func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr { + if !types.AllowsGoVersion(curpkg(), 1, 17) { + base.ErrorfVers("go1.17", "unsafe.Slice") + n.SetType(nil) + return n + } + n.X = Expr(n.X) n.Y = Expr(n.Y) if n.X.Type() == nil || n.Y.Type() == nil { diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index 8e13b0ff18..8f2d849ef5 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -579,6 +579,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Add: // unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer + if !check.allowVersion(check.pkg, 1, 17) { + check.error(call.Fun, "unsafe.Add requires go1.17 or later") + return + } + check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add") if x.mode == invalid { return @@ -675,6 +680,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( case _Slice: // unsafe.Slice(ptr *T, len IntegerType) []T + if !check.allowVersion(check.pkg, 1, 17) { + check.error(call.Fun, "unsafe.Slice requires go1.17 or later") + return + } + typ := asPointer(x.typ) if typ == nil { check.errorf(x, invalidArg+"%s is not a pointer", x) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 50bf80ba59..bc49c6d804 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -722,14 +722,29 @@ func (t *tester) registerTests() { }, }) if t.hasCxx() { - t.tests = append(t.tests, distTest{ - name: "swig_callback", - heading: "../misc/swig/callback", - fn: func(dt *distTest) error { - t.addCmd(dt, "misc/swig/callback", t.goTest()) - return nil + t.tests = append(t.tests, + distTest{ + name: "swig_callback", + heading: "../misc/swig/callback", + fn: func(dt *distTest) error { + t.addCmd(dt, "misc/swig/callback", t.goTest()) + return nil + }, + }, + distTest{ + name: "swig_callback_lto", + heading: "../misc/swig/callback", + fn: func(dt *distTest) error { + cmd := t.addCmd(dt, "misc/swig/callback", t.goTest()) + cmd.Env = append(os.Environ(), + "CGO_CFLAGS=-flto", + "CGO_CXXFLAGS=-flto", + "CGO_LDFLAGS=-flto", + ) + return nil + }, }, - }) + ) } } } diff --git a/src/cmd/link/cgo_test.go b/src/cmd/link/cgo_test.go new file mode 100644 index 0000000000..26ab802454 --- /dev/null +++ b/src/cmd/link/cgo_test.go @@ -0,0 +1,141 @@ +// 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 ( + "bytes" + "fmt" + "internal/testenv" + "os" + "os/exec" + "path/filepath" + "testing" +) + +// Issues 43830, 46295 +func TestCGOLTO(t *testing.T) { + testenv.MustHaveCGO(t) + testenv.MustHaveGoBuild(t) + + t.Parallel() + + for _, cc := range []string{"gcc", "clang"} { + for test := 0; test < 2; test++ { + t.Run(fmt.Sprintf("%s-%d", cc, test), func(t *testing.T) { + testCGOLTO(t, cc, test) + }) + } + } +} + +const test1_main = ` +package main + +/* +extern int myadd(int, int); +int c_add(int a, int b) { + return myadd(a, b); +} +*/ +import "C" + +func main() { + println(C.c_add(1, 2)) +} +` + +const test1_add = ` +package main + +import "C" + +/* test */ + +//export myadd +func myadd(a C.int, b C.int) C.int { + return a + b +} +` + +const test2_main = ` +package main + +import "fmt" + +/* +#include <stdio.h> + +void hello(void) { + printf("hello\n"); +} +*/ +import "C" + +func main() { + hello := C.hello + fmt.Printf("%v\n", hello) +} +` + +func testCGOLTO(t *testing.T, cc string, test int) { + t.Parallel() + + if _, err := exec.LookPath(cc); err != nil { + t.Skipf("no %s compiler", cc) + } + + dir := t.TempDir() + + writeTempFile := func(name, contents string) { + if err := os.WriteFile(filepath.Join(dir, name), []byte(contents), 0644); err != nil { + t.Fatal(err) + } + } + + writeTempFile("go.mod", "module cgolto\n") + + switch test { + case 0: + writeTempFile("main.go", test1_main) + writeTempFile("add.go", test1_add) + case 1: + writeTempFile("main.go", test2_main) + default: + t.Fatalf("bad case %d", test) + } + + cmd := exec.Command(testenv.GoToolPath(t), "build") + cmd.Dir = dir + cmd.Env = append(os.Environ(), + "CC="+cc, + "CGO_CFLAGS=-flto", + ) + + t.Log("go build") + out, err := cmd.CombinedOutput() + t.Logf("%s", out) + + if err != nil { + t.Logf("go build failed: %v", err) + + // Error messages we've seen indicating that LTO is not supported. + // These errors come from GCC or clang, not Go. + var noLTO = []string{ + `unrecognized command line option "-flto"`, + "unable to pass LLVM bit-code files to linker", + "file not recognized: File format not recognized", + "LTO support has not been enabled", + "linker command failed with exit code", + "gcc: can't load library", + } + for _, msg := range noLTO { + if bytes.Contains(out, []byte(msg)) { + t.Skipf("C compiler %v does not support LTO", cc) + } + } + + t.Error("failed") + } +} diff --git a/src/cmd/link/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go index 22f53a4df2..23915f9032 100644 --- a/src/cmd/link/internal/ld/ar.go +++ b/src/cmd/link/internal/ld/ar.go @@ -124,6 +124,10 @@ func hostArchive(ctxt *Link, name string) { libgcc := sym.Library{Pkg: "libgcc"} h := ldobj(ctxt, f, &libgcc, l, pname, name) + if h.ld == nil { + Errorf(nil, "%s unrecognized object file at offset %d", name, off) + continue + } f.MustSeek(h.off, 0) h.ld(ctxt, f, h.pkg, h.length, h.pn) } diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index ae0d7520eb..20f1d0b8c1 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -241,6 +241,10 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { return true, "dynamically linking with a shared library" } + if unknownObjFormat { + return true, "some input objects have an unrecognized file format" + } + return false, "" } @@ -248,7 +252,7 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { // // It is called after flags are processed and inputs are processed, // so the ctxt.LinkMode variable has an initial value from the -linkmode -// flag and the iscgo externalobj variables are set. +// flag and the iscgo, externalobj, and unknownObjFormat variables are set. func determineLinkMode(ctxt *Link) { extNeeded, extReason := mustLinkExternal(ctxt) via := "" diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index e8f001ba8e..644faeb2fb 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -343,10 +343,16 @@ var ( const pkgdef = "__.PKGDEF" var ( - // Set if we see an object compiled by the host compiler that is not - // from a package that is known to support internal linking mode. + // externalobj is set to true if we see an object compiled by + // the host compiler that is not from a package that is known + // to support internal linking mode. externalobj = false - theline string + + // unknownObjFormat is set to true if we see an object whose + // format we don't recognize. + unknownObjFormat = false + + theline string ) func Lflag(ctxt *Link, arg string) { @@ -1065,6 +1071,10 @@ func hostobjs(ctxt *Link) { } f.MustSeek(h.off, 0) + if h.ld == nil { + Errorf(nil, "%s: unrecognized object file format", h.pn) + continue + } h.ld(ctxt, f, h.pkg, h.length, h.pn) f.Close() } @@ -1855,6 +1865,14 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, return ldhostobj(ldxcoff, ctxt.HeadType, f, pkg, length, pn, file) } + if c1 != 'g' || c2 != 'o' || c3 != ' ' || c4 != 'o' { + // An unrecognized object is just passed to the external linker. + // If we try to read symbols from this object, we will + // report an error at that time. + unknownObjFormat = true + return ldhostobj(nil, ctxt.HeadType, f, pkg, length, pn, file) + } + /* check the header */ line, err := f.ReadString('\n') if err != nil { @@ -1874,7 +1892,7 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, return nil } - Errorf(nil, "%s: not an object file: @%d %02x%02x%02x%02x", pn, start, c1, c2, c3, c4) + Errorf(nil, "%s: not an object file: @%d %q", pn, start, line) return nil } diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 3540c07da1..8eb4231c3a 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -475,7 +475,7 @@ func (f *peFile) addDWARFSection(name string, size int) *peSection { off := f.stringTable.add(name) h := f.addSection(name, size, size) h.shortName = fmt.Sprintf("/%d", off) - h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA + h.characteristics = IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA return h } |