summaryrefslogtreecommitdiffstats
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/cgo/internal/testplugin/plugin_test.go19
-rw-r--r--src/cmd/compile/internal/compare/compare.go7
-rw-r--r--src/cmd/compile/internal/noder/irgen.go26
-rw-r--r--src/cmd/compile/internal/walk/assign.go43
-rw-r--r--src/cmd/go/internal/toolchain/select.go11
-rw-r--r--src/cmd/go/testdata/script/build_issue48319.txt7
-rw-r--r--src/cmd/go/testdata/script/build_plugin_reproducible.txt7
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_issue66175.txt109
-rw-r--r--src/cmd/link/internal/ld/macho.go20
9 files changed, 217 insertions, 32 deletions
diff --git a/src/cmd/cgo/internal/testplugin/plugin_test.go b/src/cmd/cgo/internal/testplugin/plugin_test.go
index 1e32ff8..4900ada 100644
--- a/src/cmd/cgo/internal/testplugin/plugin_test.go
+++ b/src/cmd/cgo/internal/testplugin/plugin_test.go
@@ -74,6 +74,7 @@ func testMain(m *testing.M) int {
}
defer os.RemoveAll(GOPATH)
tmpDir = GOPATH
+ fmt.Printf("TMPDIR=%s\n", tmpDir)
modRoot := filepath.Join(GOPATH, "src", "testplugin")
altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin")
@@ -395,3 +396,21 @@ func TestIssue62430(t *testing.T) {
goCmd(t, "build", "-o", "issue62430.exe", "./issue62430/main.go")
run(t, "./issue62430.exe")
}
+
+func TestTextSectionSplit(t *testing.T) {
+ globalSkip(t)
+ if runtime.GOOS != "darwin" || runtime.GOARCH != "arm64" {
+ t.Skipf("text section splitting is not done in %s/%s", runtime.GOOS, runtime.GOARCH)
+ }
+
+ // Use -ldflags=-debugtextsize=262144 to let the linker split text section
+ // at a smaller size threshold, so it actually splits for the test binary.
+ goCmd(nil, "build", "-ldflags=-debugtextsize=262144", "-o", "host-split.exe", "./host")
+ run(t, "./host-split.exe")
+
+ // Check that we did split text sections.
+ syms := goCmd(nil, "tool", "nm", "host-split.exe")
+ if !strings.Contains(syms, "runtime.text.1") {
+ t.Errorf("runtime.text.1 not found, text section not split?")
+ }
+}
diff --git a/src/cmd/compile/internal/compare/compare.go b/src/cmd/compile/internal/compare/compare.go
index e165cd6..cb2f84e 100644
--- a/src/cmd/compile/internal/compare/compare.go
+++ b/src/cmd/compile/internal/compare/compare.go
@@ -148,7 +148,7 @@ func calculateCostForType(t *types.Type) int64 {
return EqStructCost(t)
case types.TSLICE:
// Slices are not comparable.
- base.Fatalf("eqStructFieldCost: unexpected slice type")
+ base.Fatalf("calculateCostForType: unexpected slice type")
case types.TARRAY:
elemCost := calculateCostForType(t.Elem())
cost = t.NumElem() * elemCost
@@ -371,6 +371,11 @@ func eqmem(p, q ir.Node, field int, size int64) ir.Node {
}
func eqmemfunc(size int64, t *types.Type) (fn *ir.Name, needsize bool) {
+ if !base.Ctxt.Arch.CanMergeLoads && t.Alignment() < int64(base.Ctxt.Arch.Alignment) && t.Alignment() < t.Size() {
+ // We can't use larger comparisons if the value might not be aligned
+ // enough for the larger comparison. See issues 46283 and 67160.
+ size = 0
+ }
switch size {
case 1, 2, 4, 8, 16:
buf := fmt.Sprintf("memequal%d", int(size)*8)
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go
index e0b7bb9..145bcc8 100644
--- a/src/cmd/compile/internal/noder/irgen.go
+++ b/src/cmd/compile/internal/noder/irgen.go
@@ -34,7 +34,13 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
posBaseMap := make(map[*syntax.PosBase]*syntax.File)
for i, p := range noders {
files[i] = p.file
- posBaseMap[p.file.Pos().Base()] = p.file
+ // The file.Pos() is the position of the package clause.
+ // If there's a //line directive before that, file.Pos().Base()
+ // refers to that directive, not the file itself.
+ // Make sure to consistently map back to file base, here and
+ // when we look for a file in the conf.Error handler below,
+ // otherwise the file may not be found (was go.dev/issue/67141).
+ posBaseMap[fileBase(p.file.Pos())] = p.file
}
// typechecking
@@ -68,13 +74,12 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
terr := err.(types2.Error)
msg := terr.Msg
if versionErrorRx.MatchString(msg) {
- posBase := terr.Pos.Base()
- for !posBase.IsFileBase() { // line directive base
- posBase = posBase.Pos().Base()
- }
+ posBase := fileBase(terr.Pos)
fileVersion := info.FileVersions[posBase]
file := posBaseMap[posBase]
- if file.GoVersion == fileVersion {
+ if file == nil {
+ // This should never happen, but be careful and don't crash.
+ } else if file.GoVersion == fileVersion {
// If we have a version error caused by //go:build, report it.
msg = fmt.Sprintf("%s (file declares //go:build %s)", msg, fileVersion)
} else {
@@ -149,6 +154,15 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
return pkg, info
}
+// fileBase returns a file's position base given a position in the file.
+func fileBase(pos syntax.Pos) *syntax.PosBase {
+ base := pos.Base()
+ for !base.IsFileBase() { // line directive base
+ base = base.Pos().Base()
+ }
+ return base
+}
+
// A cycleFinder detects anonymous interface cycles (go.dev/issue/56103).
type cycleFinder struct {
cyclic map[*types2.Interface]bool
diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go
index fc3b858..63b6a1d 100644
--- a/src/cmd/compile/internal/walk/assign.go
+++ b/src/cmd/compile/internal/walk/assign.go
@@ -623,21 +623,23 @@ func isAppendOfMake(n ir.Node) bool {
// panicmakeslicelen()
// }
// s := l1
-// n := len(s) + l2
-// // Compare n and s as uint so growslice can panic on overflow of len(s) + l2.
-// // cap is a positive int and n can become negative when len(s) + l2
-// // overflows int. Interpreting n when negative as uint makes it larger
-// // than cap(s). growslice will check the int n arg and panic if n is
-// // negative. This prevents the overflow from being undetected.
-// if uint(n) <= uint(cap(s)) {
-// s = s[:n]
-// } else {
-// s = growslice(T, s.ptr, n, s.cap, l2, T)
+// if l2 != 0 {
+// n := len(s) + l2
+// // Compare n and s as uint so growslice can panic on overflow of len(s) + l2.
+// // cap is a positive int and n can become negative when len(s) + l2
+// // overflows int. Interpreting n when negative as uint makes it larger
+// // than cap(s). growslice will check the int n arg and panic if n is
+// // negative. This prevents the overflow from being undetected.
+// if uint(n) <= uint(cap(s)) {
+// s = s[:n]
+// } else {
+// s = growslice(T, s.ptr, n, s.cap, l2, T)
+// }
+// // clear the new portion of the underlying array.
+// hp := &s[len(s)-l2]
+// hn := l2 * sizeof(T)
+// memclr(hp, hn)
// }
-// // clear the new portion of the underlying array.
-// hp := &s[len(s)-l2]
-// hn := l2 * sizeof(T)
-// memclr(hp, hn)
// }
// s
//
@@ -671,11 +673,18 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
s := typecheck.TempAt(base.Pos, ir.CurFunc, l1.Type())
nodes = append(nodes, ir.NewAssignStmt(base.Pos, s, l1))
+ // if l2 != 0 {
+ // Avoid work if we're not appending anything. But more importantly,
+ // avoid allowing hp to be a past-the-end pointer when clearing. See issue 67255.
+ nifnz := ir.NewIfStmt(base.Pos, ir.NewBinaryExpr(base.Pos, ir.ONE, l2, ir.NewInt(base.Pos, 0)), nil, nil)
+ nifnz.Likely = true
+ nodes = append(nodes, nifnz)
+
elemtype := s.Type().Elem()
// n := s.len + l2
nn := typecheck.TempAt(base.Pos, ir.CurFunc, types.Types[types.TINT])
- nodes = append(nodes, ir.NewAssignStmt(base.Pos, nn, ir.NewBinaryExpr(base.Pos, ir.OADD, ir.NewUnaryExpr(base.Pos, ir.OLEN, s), l2)))
+ nifnz.Body = append(nifnz.Body, ir.NewAssignStmt(base.Pos, nn, ir.NewBinaryExpr(base.Pos, ir.OADD, ir.NewUnaryExpr(base.Pos, ir.OLEN, s), l2)))
// if uint(n) <= uint(s.cap)
nuint := typecheck.Conv(nn, types.Types[types.TUINT])
@@ -697,7 +706,7 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
l2)),
}
- nodes = append(nodes, nif)
+ nifnz.Body = append(nifnz.Body, nif)
// hp := &s[s.len - l2]
// TODO: &s[s.len] - hn?
@@ -723,7 +732,7 @@ func extendSlice(n *ir.CallExpr, init *ir.Nodes) ir.Node {
// if growslice isn't called do we need to do the zeroing ourselves.
nif.Body = append(nif.Body, clr...)
} else {
- nodes = append(nodes, clr...)
+ nifnz.Body = append(nifnz.Body, clr...)
}
typecheck.Stmts(nodes)
diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go
index dcf3be9..14a8d3c 100644
--- a/src/cmd/go/internal/toolchain/select.go
+++ b/src/cmd/go/internal/toolchain/select.go
@@ -184,6 +184,13 @@ func Select() {
}
if gover.Compare(goVers, minVers) > 0 {
gotoolchain = "go" + goVers
+ // Starting with Go 1.21, the first released version has a .0 patch version suffix.
+ // Don't try to download a language version (sans patch component), such as go1.22.
+ // Instead, use the first toolchain of that language version, such as 1.22.0.
+ // See golang.org/issue/62278.
+ if gover.IsLang(goVers) && gover.Compare(goVers, "1.21") >= 0 {
+ gotoolchain += ".0"
+ }
gover.Startup.AutoGoVersion = goVers
gover.Startup.AutoToolchain = "" // in case we are overriding it for being too old
}
@@ -312,6 +319,10 @@ func Exec(gotoolchain string) {
dir, err := modfetch.Download(context.Background(), m)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
+ toolVers := gover.FromToolchain(gotoolchain)
+ if gover.IsLang(toolVers) && gover.Compare(toolVers, "1.21") >= 0 {
+ base.Fatalf("invalid toolchain: %s is a language version but not a toolchain version (%s.x)", gotoolchain, gotoolchain)
+ }
base.Fatalf("download %s for %s/%s: toolchain not available", gotoolchain, runtime.GOOS, runtime.GOARCH)
}
base.Fatalf("download %s: %v", gotoolchain, err)
diff --git a/src/cmd/go/testdata/script/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt
index 4543303..148d8f0 100644
--- a/src/cmd/go/testdata/script/build_issue48319.txt
+++ b/src/cmd/go/testdata/script/build_issue48319.txt
@@ -4,6 +4,13 @@
[short] skip
[!cgo] skip
+# This test has problems when run on the LUCI darwin longtest builder,
+# which uses a more contemporary Xcode version that is unfriendly to
+# reproducible builds (see issue #64947 for the gory details). Note
+# that individual developers running "go test cmd/go" on Darwin may
+# still run into failures depending on their Xcode version.
+[GOOS:darwin] [go-builder] skip
+
# This test is sensitive to cache invalidation,
# so use a separate build cache that we can control.
env GOCACHE=$WORK/gocache
diff --git a/src/cmd/go/testdata/script/build_plugin_reproducible.txt b/src/cmd/go/testdata/script/build_plugin_reproducible.txt
index 5369954..aa489df 100644
--- a/src/cmd/go/testdata/script/build_plugin_reproducible.txt
+++ b/src/cmd/go/testdata/script/build_plugin_reproducible.txt
@@ -1,6 +1,13 @@
[!buildmode:plugin] skip
[short] skip
+# This test has problems when run on the LUCI darwin longtest builder,
+# which uses a more contemporary Xcode version that is unfriendly to
+# reproducible builds (see issue #64947 for the gory details). Note
+# that individual developers running "go test cmd/go" on Darwin may
+# still run into failures depending on their Xcode version.
+[GOOS:darwin] [go-builder] skip
+
go build -trimpath -buildvcs=false -buildmode=plugin -o a.so main.go
go build -trimpath -buildvcs=false -buildmode=plugin -o b.so main.go
cmp -q a.so b.so
diff --git a/src/cmd/go/testdata/script/gotoolchain_issue66175.txt b/src/cmd/go/testdata/script/gotoolchain_issue66175.txt
new file mode 100644
index 0000000..5db4dbf
--- /dev/null
+++ b/src/cmd/go/testdata/script/gotoolchain_issue66175.txt
@@ -0,0 +1,109 @@
+env TESTGO_VERSION=go1.14
+
+# Clear the path so this test doesn't fail if the system running it\
+# has a binary named go1.21 or go1.22 on its path.
+[GOOS:plan9] env path=
+[!GOOS:plan9] env PATH=
+
+# check for invalid toolchain in go.mod
+go mod init m
+go mod edit -go=1.14 -toolchain=go1.22
+! go version
+stderr 'go: invalid toolchain: go1.22 is a language version but not a toolchain version \(go1.22.x\)'
+
+rm go.mod
+go mod init m
+go mod edit -go=1.14 -toolchain=go1.21
+! go version
+stderr 'go: invalid toolchain: go1.21 is a language version but not a toolchain version \(go1.21.x\)'
+
+rm go.mod
+go mod init m
+go mod edit -go=1.14 -toolchain=go1.20
+! go version
+stderr 'go: downloading go1.20 '
+
+
+# check for invalid GOTOOLCHAIN
+env GOTOOLCHAIN=go1.14
+go version
+stdout 'go1.14'
+
+env GOTOOLCHAIN=go1.20
+! go version
+stderr 'go: downloading go1.20 '
+
+env GOTOOLCHAIN=go1.21
+! go version
+stderr 'go: invalid toolchain: go1.21 is a language version but not a toolchain version \(go1.21.x\)'
+
+env GOTOOLCHAIN=go1.22
+! go version
+stderr 'go: invalid toolchain: go1.22 is a language version but not a toolchain version \(go1.22.x\)'
+
+env GOTOOLCHAIN=go1.20+auto
+! go version
+stderr 'go: downloading go1.20 '
+
+env GOTOOLCHAIN=go1.21+auto
+! go version
+stderr 'go: invalid toolchain: go1.21 is a language version but not a toolchain version \(go1.21.x\)'
+
+env GOTOOLCHAIN=go1.22+auto
+! go version
+stderr 'go: invalid toolchain: go1.22 is a language version but not a toolchain version \(go1.22.x\)'
+
+env GOTOOLCHAIN=go1.21rc3
+! go version
+stderr 'go: downloading go1.21rc3 '
+
+env GOTOOLCHAIN=go1.22rc2
+! go version
+stderr 'go: downloading go1.22rc2 '
+
+env GOTOOLCHAIN=go1.66
+! go version
+stderr 'go: invalid toolchain: go1.66 is a language version but not a toolchain version \(go1.66.x\)'
+
+env GOTOOLCHAIN=go1.18beta2
+! go version
+stderr 'go: downloading go1.18beta2 '
+
+# go1.X is okay for path lookups
+env GOTOOLCHAIN=go1.20+path
+! go version
+stderr 'go: cannot find "go1.20" in PATH'
+
+env GOTOOLCHAIN=go1.21+path
+! go version
+stderr 'go: cannot find "go1.21" in PATH'
+
+env GOTOOLCHAIN=go1.22+path
+! go version
+stderr 'go: cannot find "go1.22" in PATH'
+
+# When a toolchain download takes place, download 1.X.0
+env GOTOOLCHAIN=auto
+rm go.mod
+go mod init m
+go mod edit -go=1.300 -toolchain=none
+! go version
+stderr 'go: downloading go1.300.0 '
+
+rm go.mod
+go mod init m
+go mod edit -go=1.21 -toolchain=none
+! go version
+stderr 'go: downloading go1.21.0 '
+
+rm go.mod
+go mod init m
+go mod edit -go=1.22 -toolchain=none
+! go version
+stderr 'go: downloading go1.22.0 '
+
+rm go.mod
+go mod init m
+go mod edit -go=1.15 -toolchain=none
+! go version
+stderr 'go: downloading go1.15 '
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index fc38b0d..a36043c 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -901,21 +901,25 @@ func collectmachosyms(ctxt *Link) {
// Add special runtime.text and runtime.etext symbols (which are local).
// We've already included this symbol in Textp on darwin if ctxt.DynlinkingGo().
// See data.go:/textaddress
+ // NOTE: runtime.text.N symbols (if we split text sections) are not added, though,
+ // so we handle them here.
if !*FlagS {
if !ctxt.DynlinkingGo() {
s := ldr.Lookup("runtime.text", 0)
if ldr.SymType(s) == sym.STEXT {
addsym(s)
}
- for n := range Segtext.Sections[1:] {
- s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n+1), 0)
- if s != 0 {
- addsym(s)
- } else {
- break
- }
+ }
+ for n := range Segtext.Sections[1:] {
+ s := ldr.Lookup(fmt.Sprintf("runtime.text.%d", n+1), 0)
+ if s != 0 {
+ addsym(s)
+ } else {
+ break
}
- s = ldr.Lookup("runtime.etext", 0)
+ }
+ if !ctxt.DynlinkingGo() {
+ s := ldr.Lookup("runtime.etext", 0)
if ldr.SymType(s) == sym.STEXT {
addsym(s)
}