aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-06-07 12:27:24 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-06-07 12:27:36 -0700
commit0e39cdc0e9d76ba06d8cf3096ab94f17b1ffefb3 (patch)
tree11c736d419de5f33c484cb025b3c9cddbdcdb918 /src/cmd
parent7c8a5be2d6f26caed84c6bae2a115872af5b1021 (diff)
parent821270787109408ae7c86a01ccc93162be9c020c (diff)
downloadgo-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.go2
-rw-r--r--src/cmd/cgo/out.go16
-rw-r--r--src/cmd/compile/internal/abi/abiutils.go2
-rw-r--r--src/cmd/compile/internal/noder/noder.go3
-rw-r--r--src/cmd/compile/internal/typecheck/func.go12
-rw-r--r--src/cmd/compile/internal/types2/builtins.go10
-rw-r--r--src/cmd/dist/test.go29
-rw-r--r--src/cmd/link/cgo_test.go141
-rw-r--r--src/cmd/link/internal/ld/ar.go4
-rw-r--r--src/cmd/link/internal/ld/config.go6
-rw-r--r--src/cmd/link/internal/ld/lib.go26
-rw-r--r--src/cmd/link/internal/ld/pe.go2
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
}