diff --git a/doc/go1.19.html b/doc/go1.19.html
index 50bc973c13..53c11bd26e 100644
--- a/doc/go1.19.html
+++ b/doc/go1.19.html
@@ -35,7 +35,7 @@ Do not send CLs removing the interior tags from such phrases.
the memory model used by C, C++, Java, JavaScript, Rust, and Swift.
Go only provides sequentially consistent atomics, not any of the more relaxed forms found in other languages.
Along with the memory model update,
- Go 1.19 introduces new types in the sync/atomic package
+ Go 1.19 introduces new types in the sync/atomic package
that make it easier to use atomic values, such as
atomic.Int64
and
@@ -741,7 +741,7 @@ as well as support for rendering them to HTML, Markdown, and text.
-
The GOROOT function now returns the empty string
@@ -807,6 +807,7 @@ as well as support for rendering them to HTML, Markdown, and text.
Compared to v2, it is now typically 1.5x to 2x faster, uses half
as much memory, and it supports an unlimited number of
goroutines.
+ On Linux, the race detector now requires at least glibc version 2.17.
@@ -847,7 +848,6 @@ as well as support for rendering them to HTML, Markdown, and text. but often easier to use: it returns an additional boolean reporting whether an equal value was found.
+Some operations (slice expressions,
+append and copy)
+rely on a slightly more loose form of core types which accept byte slices and strings.
+Specifically, if there are exactly two types, []byte and string,
+which are the underlying types of all types in the type set of interface T,
+the core type of T is called bytestring.
+
+Examples of interfaces with bytestring core types:
+
+interface{ int } // int (same as ordinary core type)
+interface{ []byte | string } // bytestring
+interface{ ~[]byte | myString } // bytestring
+
+
+
+Note that bytestring is not a real type; it cannot be used to declare
+variables are compose other types. It exists solely to describe the behavior of some
+operations that read from a sequence of bytes, which may be a byte slice or a string.
+
@@ -3837,7 +3862,8 @@ a[low : high]
constructs a substring or slice. The core type of
-a must be a string, array, pointer to array, or slice.
+a must be a string, array, pointer to array, slice, or a
+bytestring.
The indices low and
high select which elements of operand a appear
in the result. The result has indices starting at 0 and length equal to
@@ -5469,7 +5495,7 @@ string(runes{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔"
type myRune rune
string([]myRune{0x266b, 0x266c}) // "\u266b\u266c" == "♫♬"
-myString([]myRune{0x1F30E}) // "\U0001f30e" == "🌎"
+myString([]myRune{0x1f30e}) // "\U0001f30e" == "🌎"
@@ -7197,8 +7223,9 @@ The values x are passed to a parameter of type ...E
and the respective parameter
passing rules apply.
As a special case, if the core type of s is []byte,
-append also accepts a second argument with core type string
-followed by .... This form appends the bytes of the string.
+append also accepts a second argument with core type
+bytestring followed by ....
+This form appends the bytes of the byte slice or string.
@@ -7235,8 +7262,9 @@ with identical element type. The number of elements copied is the minimum oflen(src)andlen(dst). As a special case, if the destination's core type is[]byte, -copyalso accepts a source argument with core typestring. -This form copies the bytes from the string into the byte slice. +copyalso accepts a source argument with core type +bytestring. +This form copies the bytes from the byte slice or string into the byte slice.@@ -7550,7 +7578,7 @@ and the Unicode replacement character U+FFFD.-Assume we have compiled a package containing the package clause +Consider a compiled a package containing the package clause
+package math, which exports functionSin, and installed the compiled package in the file identified by"lib/math". diff --git a/misc/cgo/test/testdata/issue52611.go b/misc/cgo/test/testdata/issue52611.go new file mode 100644 index 0000000000..32d22403ab --- /dev/null +++ b/misc/cgo/test/testdata/issue52611.go @@ -0,0 +1,13 @@ +// 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 52611: inconsistent compiler behaviour when compiling a C.struct. +// No runtime test; just make sure it compiles. + +package cgotest + +import ( + _ "cgotest/issue52611a" + _ "cgotest/issue52611b" +) diff --git a/misc/cgo/test/testdata/issue52611a/a.go b/misc/cgo/test/testdata/issue52611a/a.go new file mode 100644 index 0000000000..0764688ec4 --- /dev/null +++ b/misc/cgo/test/testdata/issue52611a/a.go @@ -0,0 +1,16 @@ +// 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 issue52611a + +/* +typedef struct Foo { + int X; +} Foo; +*/ +import "C" + +func GetX1(foo *C.struct_Foo) int32 { + return int32(foo.X) +} diff --git a/misc/cgo/test/testdata/issue52611a/b.go b/misc/cgo/test/testdata/issue52611a/b.go new file mode 100644 index 0000000000..74a50c5dea --- /dev/null +++ b/misc/cgo/test/testdata/issue52611a/b.go @@ -0,0 +1,11 @@ +// 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 issue52611a + +import "C" + +func GetX2(foo *C.struct_Foo) int32 { + return int32(foo.X) +} diff --git a/misc/cgo/test/testdata/issue52611b/a.go b/misc/cgo/test/testdata/issue52611b/a.go new file mode 100644 index 0000000000..730b52f5e9 --- /dev/null +++ b/misc/cgo/test/testdata/issue52611b/a.go @@ -0,0 +1,11 @@ +// 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 issue52611b + +import "C" + +func GetX1(bar *C.struct_Bar) int32 { + return int32(bar.X) +} diff --git a/misc/cgo/test/testdata/issue52611b/b.go b/misc/cgo/test/testdata/issue52611b/b.go new file mode 100644 index 0000000000..d304175395 --- /dev/null +++ b/misc/cgo/test/testdata/issue52611b/b.go @@ -0,0 +1,16 @@ +// 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 issue52611b + +/* +typedef struct Bar { + int X; +} Bar; +*/ +import "C" + +func GetX2(bar *C.struct_Bar) int32 { + return int32(bar.X) +} diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 4c62c5d70e..7fb6179e26 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -753,6 +753,16 @@ presented to cmd/link as part of a larger program, contains: _go_.o # gc-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go _all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c +If there is an error generating the _cgo_import.go file, then, instead +of adding _cgo_import.go to the package, the go tool adds an empty +file named dynimportfail. The _cgo_import.go file is only needed when +using internal linking mode, which is not the default when linking +programs that use cgo (as described below). If the linker sees a file +named dynimportfail it reports an error if it has been told to use +internal linking mode. This approach is taken because generating +_cgo_import.go requires doing a full C link of the package, which can +fail for reasons that are irrelevant when using external linking mode. + The final program will be a dynamic executable, so that cmd/link can avoid needing to process arbitrary .o files. It only needs to process the .o files generated from C files that cgo writes, and those are much more diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 4dff5e2b1c..3cb01ba382 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -2551,6 +2551,11 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ t.Go = name // publish before recursive calls goIdent[name.Name] = name if dt.ByteSize < 0 { + // Don't override old type + if _, ok := typedef[name.Name]; ok { + break + } + // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown), // so execute the basic things that the struct case would do // other than try to determine a Go representation. diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index c9667bd04a..0a95aaabd7 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -78,6 +78,8 @@ func storeByType(t *types.Type) obj.As { return x86.AMOVL case 8: return x86.AMOVQ + case 16: + return x86.AMOVUPS } } panic(fmt.Sprintf("bad store type %v", t)) diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index f84368ece3..4bbc04826a 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -91,6 +91,11 @@ func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope, continue } apdecls = append(apdecls, n) + if n.Type().Kind() == types.TSSA { + // Can happen for TypeInt128 types. This only happens for + // spill locations, so not a huge deal. + continue + } fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type())) } } diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3f12aa3cbd..89869c77d6 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -208,9 +208,15 @@ func (g *genInst) scanForGenCalls(decl ir.Node) { st := g.getInstantiation(gf, targs, true).fun dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) - // We have to be using a subdictionary, since this is - // a generic method call. - assert(usingSubdict) + if hasShapeTypes(targs) { + // We have to be using a subdictionary, since this is + // a generic method call. + assert(usingSubdict) + } else { + // We should use main dictionary, because the receiver is + // an instantiation already, see issue #53406. + assert(!usingSubdict) + } // Transform to a function call, by appending the // dictionary and the receiver to the args. @@ -721,11 +727,12 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe // Struct containing info needed for doing the substitution as we create the // instantiation of a generic function with specified type arguments. type subster struct { - g *genInst - isMethod bool // If a method is being instantiated - newf *ir.Func // Func node for the new stenciled function - ts typecheck.Tsubster - info *instInfo // Place to put extra info in the instantiation + g *genInst + isMethod bool // If a method is being instantiated + newf *ir.Func // Func node for the new stenciled function + ts typecheck.Tsubster + info *instInfo // Place to put extra info in the instantiation + skipClosure bool // Skip substituting closures // Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n defnMap map[ir.Node][]**ir.Name @@ -978,7 +985,20 @@ func (subst *subster) node(n ir.Node) ir.Node { } } + old := subst.skipClosure + // For unsafe.{Alignof,Offsetof,Sizeof}, subster will transform them to OLITERAL nodes, + // and discard their arguments. However, their children nodes were already process before, + // thus if they contain any closure, the closure was still be added to package declarations + // queue for processing later. Thus, genInst will fail to generate instantiation for the + // closure because of lacking dictionary information, see issue #53390. + if call, ok := m.(*ir.CallExpr); ok && call.X.Op() == ir.ONAME { + switch call.X.Name().BuiltinOp { + case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: + subst.skipClosure = true + } + } ir.EditChildren(m, edit) + subst.skipClosure = old m.SetTypecheck(1) @@ -1123,6 +1143,9 @@ func (subst *subster) node(n ir.Node) ir.Node { } case ir.OCLOSURE: + if subst.skipClosure { + break + } // We're going to create a new closure from scratch, so clear m // to avoid using the ir.Copy by accident until we reassign it. m = nil @@ -1326,7 +1349,7 @@ func (g *genInst) dictPass(info *instInfo) { mce := m.(*ir.ConvExpr) // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. - if mce.X.Type().HasShape() || m.Type().HasShape() { + if mce.X.Type().HasShape() || (m.Type().HasShape() && !m.Type().IsEmptyInterface()) { m = convertUsingDictionary(info, info.dictParam, m.Pos(), mce.X, m, m.Type()) } case ir.ODOTTYPE, ir.ODOTTYPE2: @@ -1423,7 +1446,7 @@ func findDictType(info *instInfo, t *types.Type) int { // instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the // conversion. func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node { - assert(v.Type().HasShape() || in.Type().HasShape()) + assert(v.Type().HasShape() || (in.Type().HasShape() && !in.Type().IsEmptyInterface())) assert(dst.IsInterface()) if v.Type().IsInterface() { diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index a5a5c0b5b1..68b9ac3ff3 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -590,6 +590,12 @@ func PtrDataSize(t *Type) int64 { } return 0 + case TSSA: + if t != TypeInt128 { + base.Fatalf("PtrDataSize: unexpected ssa type %v", t) + } + return 0 + default: base.Fatalf("PtrDataSize: unexpected type, %v", t) return 0 diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 1ea239ea32..9e229a59c6 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1705,6 +1705,11 @@ var ( TypeResultMem = newResults([]*Type{TypeMem}) ) +func init() { + TypeInt128.width = 16 + TypeInt128.align = 8 +} + // NewNamed returns a new named type for the given type name. obj should be an // ir.Name. The new type is incomplete (marked as TFORW kind), and the underlying // type should be set later via SetUnderlying(). References to the type are diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 0bc5f9f3e1..1db28fc002 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -5,6 +5,7 @@ package types2 import ( + "bytes" "cmd/compile/internal/syntax" "fmt" "go/constant" @@ -303,11 +304,23 @@ loop: // cycleError reports a declaration cycle starting with // the object in cycle that is "first" in the source. func (check *Checker) cycleError(cycle []Object) { + // name returns the (possibly qualified) object name. + // This is needed because with generic types, cycles + // may refer to imported types. See issue #50788. + // TODO(gri) Thus functionality is used elsewhere. Factor it out. + name := func(obj Object) string { + var buf bytes.Buffer + writePackage(&buf, obj.Pkg(), check.qualifier) + buf.WriteString(obj.Name()) + return buf.String() + } + // TODO(gri) Should we start with the last (rather than the first) object in the cycle // since that is the earliest point in the source where we start seeing the // cycle? That would be more consistent with other error messages. i := firstInSrc(cycle) obj := cycle[i] + objName := name(obj) // If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors. tname, _ := obj.(*TypeName) if tname != nil && tname.IsAlias() { @@ -315,19 +328,20 @@ func (check *Checker) cycleError(cycle []Object) { } var err error_ if tname != nil && check.conf.CompilerErrorMessages { - err.errorf(obj, "invalid recursive type %s", obj.Name()) + err.errorf(obj, "invalid recursive type %s", objName) } else { - err.errorf(obj, "illegal cycle in declaration of %s", obj.Name()) + err.errorf(obj, "illegal cycle in declaration of %s", objName) } for range cycle { - err.errorf(obj, "%s refers to", obj.Name()) + err.errorf(obj, "%s refers to", objName) i++ if i >= len(cycle) { i = 0 } obj = cycle[i] + objName = name(obj) } - err.errorf(obj, "%s", obj.Name()) + err.errorf(obj, "%s", objName) check.report(&err) } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index b0c6a4fcea..8425cd6034 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -128,11 +128,8 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // named and unnamed types are passed to parameters with identical type, different types // (named vs underlying) may be inferred depending on the order of the arguments. // By ensuring that named types are seen first, order dependence is avoided and unification - // succeeds where it can. - // - // This code is disabled for now pending decision whether we want to address cases like - // these and make the spec on type inference more complicated (see issue #43056). - const enableArgSorting = false + // succeeds where it can (issue #43056). + const enableArgSorting = true if m := len(args); m >= 2 && enableArgSorting { // Determine indices of arguments with named and unnamed types. var named, unnamed []int diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index f7b5b16204..c4d11dcac4 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -147,7 +147,17 @@ func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, . } return true case *Interface: - return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) + if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) { + return true + } + if reportf != nil { + if t.typeSet().IsEmpty() { + reportf("empty type set") + } else { + reportf("incomparable types in type set") + } + } + // fallthrough } return false } diff --git a/src/cmd/compile/internal/types2/testdata/examples/functions.go b/src/cmd/compile/internal/types2/testdata/examples/functions.go index ef8953cb43..d50f79d11f 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/functions.go +++ b/src/cmd/compile/internal/types2/testdata/examples/functions.go @@ -182,7 +182,7 @@ func _() { type myString string var s1 string g3(nil, "1", myString("2"), "3") - g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3") + g3(& /* ERROR does not match */ s1, "1", myString("2"), "3") _ = s1 type myStruct struct{x int} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go index 35c7ef592d..8ff4e7f9b4 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go @@ -14,7 +14,7 @@ func _() { var j func(F) f(i, j) - // f(j, i) // disabled for now + f(j, i) } // example from issue @@ -27,5 +27,5 @@ func _() { var j interface{ Equal(I) bool } g(i, j) - // g(j, i) // disabled for now + g(j, i) } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go index ab397560a8..63ce7bc510 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go @@ -23,18 +23,18 @@ func _[P comparable](x P, y any) { } func _[P any](x, y P) { - _ = x /* ERROR type parameter P is not comparable with == */ == x - _ = x /* ERROR type parameter P is not comparable with == */ == y - _ = y /* ERROR type parameter P is not comparable with == */ == x - _ = y /* ERROR type parameter P is not comparable with == */ == y + _ = x /* ERROR incomparable types in type set */ == x + _ = x /* ERROR incomparable types in type set */ == y + _ = y /* ERROR incomparable types in type set */ == x + _ = y /* ERROR incomparable types in type set */ == y _ = x /* ERROR type parameter P is not comparable with < */ < y } func _[P any](x P, y any) { - _ = x /* ERROR type parameter P is not comparable with == */ == x - _ = x /* ERROR type parameter P is not comparable with == */ == y - _ = y == x // ERROR type parameter P is not comparable with == + _ = x /* ERROR incomparable types in type set */ == x + _ = x /* ERROR incomparable types in type set */ == y + _ = y == x // ERROR incomparable types in type set _ = y == y _ = x /* ERROR type parameter P is not comparable with < */ < y diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51525.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51525.go new file mode 100644 index 0000000000..af1d1e6063 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51525.go @@ -0,0 +1,16 @@ +// 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 + +func _[T interface { + int + string +}](x T) { + _ = x /* ERROR empty type set */ == x +} + +func _[T interface{ int | []byte }](x T) { + _ = x /* ERROR incomparable types in type set */ == x +} diff --git a/src/cmd/compile/internal/types2/testdata/spec/comparisons.go b/src/cmd/compile/internal/types2/testdata/spec/comparisons.go index 62c95d47d7..2a7598a581 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/comparisons.go +++ b/src/cmd/compile/internal/types2/testdata/spec/comparisons.go @@ -40,7 +40,7 @@ func _() { _ = m /* ERROR map can only be compared to nil */ == m _ = c == c - _ = b /* ERROR mismatched types */ == nil + _ = b /* ERROR mismatched types */ == nil _ = a /* ERROR mismatched types */ == nil _ = l == nil _ = s /* ERROR mismatched types */ == nil @@ -73,7 +73,7 @@ func _[ J comparable, M map[string]int, C chan int, -] ( +]( b B, a A, l L, @@ -86,14 +86,14 @@ func _[ c C, ) { _ = b == b - _ = a /* ERROR type parameter A is not comparable with == */ == a - _ = l /* ERROR type parameter L is not comparable with == */ == l - _ = s /* ERROR type parameter S is not comparable with == */ == s + _ = a /* ERROR incomparable types in type set */ == a + _ = l /* ERROR incomparable types in type set */ == l + _ = s /* ERROR incomparable types in type set */ == s _ = p == p - _ = f /* ERROR type parameter F is not comparable with == */ == f - _ = i /* ERROR type parameter I is not comparable with == */ == i + _ = f /* ERROR incomparable types in type set */ == f + _ = i /* ERROR incomparable types in type set */ == i _ = j == j - _ = m /* ERROR type parameter M is not comparable with == */ == m + _ = m /* ERROR incomparable types in type set */ == m _ = c == c _ = b /* ERROR mismatched types */ == nil diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 26d7fe0f73..846d0c0d85 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -766,7 +766,7 @@ func (t *tester) registerTests() { name: "swig_stdio", heading: "../misc/swig/stdio", fn: func(dt *distTest) error { - t.addCmd(dt, "misc/swig/stdio", t.goTest()) + t.addCmd(dt, "misc/swig/stdio", t.goTest(), ".") return nil }, }) @@ -776,7 +776,7 @@ func (t *tester) registerTests() { name: "swig_callback", heading: "../misc/swig/callback", fn: func(dt *distTest) error { - t.addCmd(dt, "misc/swig/callback", t.goTest()) + t.addCmd(dt, "misc/swig/callback", t.goTest(), ".") return nil }, }, @@ -784,7 +784,7 @@ func (t *tester) registerTests() { name: "swig_callback_lto", heading: "../misc/swig/callback", fn: func(dt *distTest) error { - cmd := t.addCmd(dt, "misc/swig/callback", t.goTest()) + cmd := t.addCmd(dt, "misc/swig/callback", t.goTest(), ".") setEnv(cmd, "CGO_CFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") setEnv(cmd, "CGO_CXXFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") setEnv(cmd, "CGO_LDFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") @@ -1185,11 +1185,11 @@ func (t *tester) runHostTest(dir, pkg string) error { } func (t *tester) cgoTest(dt *distTest) error { - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto") if t.internalLink() { - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal") + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal", ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=internal") } @@ -1201,15 +1201,15 @@ func (t *tester) cgoTest(dt *distTest) error { if !t.extLink() { break } - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external") - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s", ".") if t.supportedBuildmode("pie") { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", ".") if t.internalLink() && t.internalLinkPIE() { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie", ".") } } @@ -1221,14 +1221,14 @@ func (t *tester) cgoTest(dt *distTest) error { "netbsd-386", "netbsd-amd64", "openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64": - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external") // cgo should be able to cope with both -g arguments and colored // diagnostics. setEnv(cmd, "CGO_CFLAGS", "-g0 -fdiagnostics-color") - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto") - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external") + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto", ".") + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external", ".") switch pair { case "aix-ppc64", "netbsd-386", "netbsd-amd64": @@ -1247,28 +1247,28 @@ func (t *tester) cgoTest(dt *distTest) error { fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.") } else { if goos != "android" { - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".") } - t.addCmd(dt, "misc/cgo/nocgo", t.goTest()) - t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`) + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), ".") + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`, ".") if goos != "android" { - t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".") // -static in CGO_LDFLAGS triggers a different code path // than -static in -extldflags, so test both. // See issue #16651. - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static") + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", ".") setEnv(cmd, "CGO_LDFLAGS", "-static -pthread") } } if t.supportedBuildmode("pie") { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", ".") if t.internalLink() && t.internalLinkPIE() { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie", ".") } - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie") - t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie") + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie", ".") + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie", ".") } } } diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 04c2523a09..8230a3e453 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,7 +7,7 @@ require ( golang.org/x/arch v0.0.0-20220412001346-fc48f9fe4c15 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 - golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a + golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index fc81e159e5..435c3cce3b 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -10,8 +10,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVD golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA= +golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8= golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567 h1:MksUZ/zlU+pMbsq1Sw16gK6E1aWzD0rLE+eS2SxF24Y= diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index d770ad82e5..fdb7a085b0 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -930,19 +930,20 @@ // applied to a Go struct, but now a Module struct: // // type Module struct { -// Path string // module path -// Version string // module version -// Versions []string // available module versions (with -versions) -// Replace *Module // replaced by this module -// Time *time.Time // time version was created -// Update *Module // available update, if any (with -u) -// Main bool // is this the main module? -// Indirect bool // is this module only an indirect dependency of main module? -// Dir string // directory holding files for this module, if any -// GoMod string // path to go.mod file used when loading this module, if any -// GoVersion string // go version used in module -// Retracted string // retraction information, if any (with -retracted or -u) -// Error *ModuleError // error loading module +// Path string // module path +// Version string // module version +// Versions []string // available module versions +// Replace *Module // replaced by this module +// Time *time.Time // time version was created +// Update *Module // available update (with -u) +// Main bool // is this the main module? +// Indirect bool // module is only indirectly needed by main module +// Dir string // directory holding local copy of files, if any +// GoMod string // path to go.mod file describing module, if any +// GoVersion string // go version used in module +// Retracted []string // retraction information, if any (with -retracted or -u) +// Deprecated string // deprecation message, if any (with -u) +// Error *ModuleError // error loading module // } // // type ModuleError struct { diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 770127c1cd..9c651f2bf3 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -222,19 +222,20 @@ When listing modules, the -f flag still specifies a format template applied to a Go struct, but now a Module struct: type Module struct { - Path string // module path - Version string // module version - Versions []string // available module versions (with -versions) - Replace *Module // replaced by this module - Time *time.Time // time version was created - Update *Module // available update, if any (with -u) - Main bool // is this the main module? - Indirect bool // is this module only an indirect dependency of main module? - Dir string // directory holding files for this module, if any - GoMod string // path to go.mod file used when loading this module, if any - GoVersion string // go version used in module - Retracted string // retraction information, if any (with -retracted or -u) - Error *ModuleError // error loading module + Path string // module path + Version string // module version + Versions []string // available module versions + Replace *Module // replaced by this module + Time *time.Time // time version was created + Update *Module // available update (with -u) + Main bool // is this the main module? + Indirect bool // module is only indirectly needed by main module + Dir string // directory holding local copy of files, if any + GoMod string // path to go.mod file describing module, if any + GoVersion string // go version used in module + Retracted []string // retraction information, if any (with -retracted or -u) + Deprecated string // deprecation message, if any (with -u) + Error *ModuleError // error loading module } type ModuleError struct { diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index fe4a82472d..95a06a325d 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -686,6 +686,9 @@ func LoadImport(ctx context.Context, opts PackageOpts, path, srcDir string, pare } func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { + ctx, span := trace.StartSpan(ctx, "modload.loadImport "+path) + defer span.Done() + if path == "" { panic("LoadImport called with empty package path") } @@ -801,6 +804,9 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi // loadPackageData returns a boolean, loaded, which is true if this is the // first time the package was loaded. Callers may preload imports in this case. func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) { + ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path) + defer span.Done() + if path == "" { panic("loadPackageData called with empty package path") } @@ -872,8 +878,8 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo buildMode = build.ImportComment } if modroot := modload.PackageModRoot(ctx, r.path); modroot != "" { - if mi, err := modindex.Get(modroot); err == nil { - data.p, data.err = mi.Import(cfg.BuildContext, mi.RelPath(r.dir), buildMode) + if rp, err := modindex.GetPackage(modroot, r.dir); err == nil { + data.p, data.err = rp.Import(cfg.BuildContext, buildMode) goto Happy } else if !errors.Is(err, modindex.ErrNotIndexed) { base.Fatalf("go: %v", err) diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index a7c8c2c769..2e8c4c8aca 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -242,7 +242,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e // contents of the file (by hashing it) before we commit it. Because the file // is zip-compressed, we need an actual file — or at least an io.ReaderAt — to // validate it: we can't just tee the stream as we write it. - f, err := os.CreateTemp(filepath.Dir(zipfile), tmpPattern) + f, err := tempFile(filepath.Dir(zipfile), filepath.Base(zipfile), 0666) if err != nil { return err } @@ -833,6 +833,7 @@ Outer: for _, m := range mods { list := goSum.m[m] sort.Strings(list) + str.Uniq(&list) for _, h := range list { st := goSum.status[modSum{m, h}] if (!st.dirty || (st.used && keep[m])) && !sumInWorkspaceModulesLocked(m) { diff --git a/src/cmd/go/internal/modindex/index_format.txt b/src/cmd/go/internal/modindex/index_format.txt index 3768eea6c7..c74b1d458b 100644 --- a/src/cmd/go/internal/modindex/index_format.txt +++ b/src/cmd/go/internal/modindex/index_format.txt @@ -7,6 +7,8 @@ Strings are written into the string table at the end of the file. Each string is null-terminated. String offsets are relative to the start of the string table. Bools are written as uint32s: 0 for false and 1 for true. +The following is the format for a full module: + “go index v0\n” str uint32 - offset of string table n uint32 - number of packages @@ -40,7 +42,16 @@ for each RawPackage: position - file, offset, line, column - uint32 [string table] -// parseError struct +The following is the format for a single indexed package: + +“go index v0\n” +str uint32 - offset of string table +for the single RawPackage: + [same RawPackage format as above] +[string table] + +The following is the definition of the json-serialized parseError struct: + type parseError struct { ErrorList *scanner.ErrorList // non-nil if the error was an ErrorList, nil otherwise ErrorString string // non-empty for all other cases diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go index ffa091df41..65a1ecf6dc 100644 --- a/src/cmd/go/internal/modindex/read.go +++ b/src/cmd/go/internal/modindex/read.go @@ -12,11 +12,10 @@ import ( "go/build" "go/build/constraint" "go/token" + "internal/godebug" "internal/goroot" "internal/unsafeheader" - "io/fs" "math" - "os" "path" "path/filepath" "runtime" @@ -24,6 +23,7 @@ import ( "sort" "strings" "sync" + "time" "unsafe" "cmd/go/internal/base" @@ -39,79 +39,79 @@ import ( // It will be removed before the release. // TODO(matloob): Remove enabled once we have more confidence on the // module index. -var enabled = func() bool { - debug := strings.Split(os.Getenv("GODEBUG"), ",") - for _, f := range debug { - if f == "goindex=0" { - return false - } - } - return true -}() +var enabled bool = godebug.Get("goindex") != "0" -// ModuleIndex represents and encoded module index file. It is used to +// Module represents and encoded module index file. It is used to // do the equivalent of build.Import of packages in the module and answer other // questions based on the index file's data. -type ModuleIndex struct { +type Module struct { modroot string od offsetDecoder packages map[string]int // offsets of each package packagePaths []string // paths to package directories relative to modroot; these are the keys of packages } -var fcache par.Cache - +// moduleHash returns an ActionID corresponding to the state of the module +// located at filesystem path modroot. func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) { // We expect modules stored within the module cache to be checksummed and - // immutable, and we expect released Go modules to change only infrequently - // (when the Go version changes). - if !ismodcache || !str.HasFilePathPrefix(modroot, cfg.GOROOT) { + // immutable, and we expect released modules within GOROOT to change only + // infrequently (when the Go version changes). + if !ismodcache { + // The contents of this module may change over time. We don't want to pay + // the cost to detect changes and re-index whenever they occur, so just + // don't index it at all. + // + // Note that this is true even for modules in GOROOT/src: non-release builds + // of the Go toolchain may have arbitrary development changes on top of the + // commit reported by runtime.Version, or could be completly artificial due + // to lacking a `git` binary (like "devel gomote.XXXXX", as synthesized by + // "gomote push" as of 2022-06-15). (Release builds shouldn't have + // modifications, but we don't want to use a behavior for releases that we + // haven't tested during development.) return cache.ActionID{}, ErrNotIndexed } h := cache.NewHash("moduleIndex") fmt.Fprintf(h, "module index %s %s %v\n", runtime.Version(), indexVersion, modroot) + return h.Sum(), nil +} - if strings.HasPrefix(runtime.Version(), "devel ") { - // This copy of the standard library is a development version, not a - // release. It could be based on a Git commit (like "devel go1.19-2a78e8afc0 - // Wed Jun 15 00:06:24 2022 +0000") with or without changes on top of that - // commit, or it could be completly artificial due to lacking a `git` binary - // (like "devel gomote.XXXXX", as synthesized by "gomote push" as of - // 2022-06-15). Compute an inexpensive hash of its files using mtimes so - // that during development we can continue to exercise the logic for cached - // GOROOT indexes. - // - // mtimes may be granular, imprecise, and loosely updated (see - // https://apenwarr.ca/log/20181113), but we don't expect Go contributors to - // be mucking around with the import graphs in GOROOT often enough for mtime - // collisions to matter essentially ever. - // - // Note that fsys.Walk walks paths in deterministic order, so this hash - // should be completely deterministic if the files are unchanged. - err := fsys.Walk(modroot, func(path string, info fs.FileInfo, err error) error { - if err := moduleWalkErr(modroot, path, info, err); err != nil { - return err - } +const modTimeCutoff = 2 * time.Second - if info.IsDir() { - return nil - } - fmt.Fprintf(h, "file %v %v\n", info.Name(), info.ModTime()) - if info.Mode()&fs.ModeSymlink != 0 { - targ, err := fsys.Stat(path) - if err != nil { - return err - } - fmt.Fprintf(h, "target %v %v\n", targ.Name(), targ.ModTime()) - } - return nil - }) - if err != nil { - return cache.ActionID{}, err - } +// dirHash returns an ActionID corresponding to the state of the package +// located at filesystem path pkgdir. +func dirHash(pkgdir string) (cache.ActionID, error) { + h := cache.NewHash("moduleIndex") + fmt.Fprintf(h, "package %s %s %v\n", runtime.Version(), indexVersion, pkgdir) + entries, err := fsys.ReadDir(pkgdir) + if err != nil { + // pkgdir might not be a directory. give up on hashing. + return cache.ActionID{}, ErrNotIndexed } + cutoff := time.Now().Add(-modTimeCutoff) + for _, info := range entries { + if info.IsDir() { + continue + } + if !info.Mode().IsRegular() { + return cache.ActionID{}, ErrNotIndexed + } + // To avoid problems for very recent files where a new + // write might not change the mtime due to file system + // mtime precision, reject caching if a file was read that + // is less than modTimeCutoff old. + // + // This is the same strategy used for hashing test inputs. + // See hashOpen in cmd/go/internal/test/test.go for the + // corresponding code. + if info.ModTime().After(cutoff) { + return cache.ActionID{}, ErrNotIndexed + } + + fmt.Fprintf(h, "file %v %v %v\n", info.Name(), info.ModTime(), info.Size()) + } return h.Sum(), nil } @@ -119,31 +119,61 @@ var modrootCache par.Cache var ErrNotIndexed = errors.New("not in module index") -// Get returns the ModuleIndex for the module rooted at modroot. +var ( + errDisabled = fmt.Errorf("%w: module indexing disabled", ErrNotIndexed) + errNotFromModuleCache = fmt.Errorf("%w: not from module cache", ErrNotIndexed) +) + +// GetPackage returns the IndexPackage for the package at the given path. // It will return ErrNotIndexed if the directory should be read without // using the index, for instance because the index is disabled, or the packgae // is not in a module. -func Get(modroot string) (*ModuleIndex, error) { - if !enabled || cache.DefaultDir() == "off" || cfg.BuildMod == "vendor" { - return nil, ErrNotIndexed +func GetPackage(modroot, pkgdir string) (*IndexPackage, error) { + mi, err := GetModule(modroot) + if err == nil { + return mi.Package(relPath(pkgdir, modroot)), nil } - if modroot == "" { - panic("modindex.Get called with empty modroot") + if !errors.Is(err, errNotFromModuleCache) { + return nil, err } - modroot = filepath.Clean(modroot) - isModCache := str.HasFilePathPrefix(modroot, cfg.GOMODCACHE) - return openIndex(modroot, isModCache) + return openIndexPackage(modroot, pkgdir) } -// openIndex returns the module index for modPath. +// GetModule returns the Module for the given modroot. +// It will return ErrNotIndexed if the directory should be read without +// using the index, for instance because the index is disabled, or the packgae +// is not in a module. +func GetModule(modroot string) (*Module, error) { + if !enabled || cache.DefaultDir() == "off" { + return nil, errDisabled + } + if modroot == "" { + panic("modindex.GetPackage called with empty modroot") + } + if cfg.BuildMod == "vendor" { + // Even if the main module is in the module cache, + // its vendored dependencies are not loaded from their + // usual cached locations. + return nil, errNotFromModuleCache + } + modroot = filepath.Clean(modroot) + if !str.HasFilePathPrefix(modroot, cfg.GOMODCACHE) { + return nil, errNotFromModuleCache + } + return openIndexModule(modroot, true) +} + +var mcache par.Cache + +// openIndexModule returns the module index for modPath. // It will return ErrNotIndexed if the module can not be read // using the index because it contains symlinks. -func openIndex(modroot string, ismodcache bool) (*ModuleIndex, error) { +func openIndexModule(modroot string, ismodcache bool) (*Module, error) { type result struct { - mi *ModuleIndex + mi *Module err error } - r := fcache.Do(modroot, func() any { + r := mcache.Do(modroot, func() any { id, err := moduleHash(modroot, ismodcache) if err != nil { return result{nil, err} @@ -169,8 +199,38 @@ func openIndex(modroot string, ismodcache bool) (*ModuleIndex, error) { return r.mi, r.err } -// fromBytes returns a *ModuleIndex given the encoded representation. -func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) { +var pcache par.Cache + +func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) { + type result struct { + pkg *IndexPackage + err error + } + r := pcache.Do(pkgdir, func() any { + id, err := dirHash(pkgdir) + if err != nil { + return result{nil, err} + } + data, _, err := cache.Default().GetMmap(id) + if err != nil { + // Couldn't read from index. Assume we couldn't read from + // the index because the package hasn't been indexed yet. + data = indexPackage(modroot, pkgdir) + if err = cache.Default().PutBytes(id, data); err != nil { + return result{nil, err} + } + } + pkg, err := packageFromBytes(modroot, data) + if err != nil { + return result{nil, err} + } + return result{pkg, nil} + }).(result) + return r.pkg, r.err +} + +// fromBytes returns a *Module given the encoded representation. +func fromBytes(moddir string, data []byte) (mi *Module, err error) { if !enabled { panic("use of index") } @@ -220,7 +280,7 @@ func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) { packages[packagePaths[i]] = packageOffsets[i] } - return &ModuleIndex{ + return &Module{ moddir, offsetDecoder{data, st}, packages, @@ -228,21 +288,60 @@ func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) { }, nil } +// packageFromBytes returns a *IndexPackage given the encoded representation. +func packageFromBytes(modroot string, data []byte) (p *IndexPackage, err error) { + if !enabled { + panic("use of package index when not enabled") + } + + // SetPanicOnFault's errors _may_ satisfy this interface. Even though it's not guaranteed + // that all its errors satisfy this interface, we'll only check for these errors so that + // we don't suppress panics that could have been produced from other sources. + type addrer interface { + Addr() uintptr + } + + // set PanicOnFault to true so that we can catch errors on the initial reads of the slice, + // in case it's mmapped (the common case). + old := debug.SetPanicOnFault(true) + defer func() { + debug.SetPanicOnFault(old) + if e := recover(); e != nil { + if _, ok := e.(addrer); ok { + // This panic was almost certainly caused by SetPanicOnFault. + err = fmt.Errorf("error reading module index: %v", e) + return + } + // The panic was likely not caused by SetPanicOnFault. + panic(e) + } + }() + + gotVersion, unread, _ := bytes.Cut(data, []byte{'\n'}) + if string(gotVersion) != indexVersion { + return nil, fmt.Errorf("bad index version string: %q", gotVersion) + } + stringTableOffset, unread := binary.LittleEndian.Uint32(unread[:4]), unread[4:] + st := newStringTable(data[stringTableOffset:]) + d := &decoder{unread, st} + p = decodePackage(d, offsetDecoder{data, st}) + p.modroot = modroot + return p, nil +} + // Returns a list of directory paths, relative to the modroot, for // packages contained in the module index. -func (mi *ModuleIndex) Packages() []string { +func (mi *Module) Packages() []string { return mi.packagePaths } -// RelPath returns the path relative to the module's root. -func (mi *ModuleIndex) RelPath(path string) string { - return str.TrimFilePathPrefix(filepath.Clean(path), mi.modroot) // mi.modroot is already clean +// relPath returns the path relative to the module's root. +func relPath(path, modroot string) string { + return str.TrimFilePathPrefix(filepath.Clean(path), filepath.Clean(modroot)) } -// ImportPackage is the equivalent of build.Import given the information in ModuleIndex. -func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.ImportMode) (p *build.Package, err error) { - rp := mi.indexPackage(relpath) - +// Import is the equivalent of build.Import given the information in Module. +func (rp *IndexPackage) Import(bctxt build.Context, mode build.ImportMode) (p *build.Package, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("error reading module index: %v", e) @@ -254,7 +353,7 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im p = &build.Package{} p.ImportPath = "." - p.Dir = filepath.Join(mi.modroot, rp.dir) + p.Dir = filepath.Join(rp.modroot, rp.dir) var pkgerr error switch ctxt.Compiler { @@ -272,7 +371,7 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im inTestdata := func(sub string) bool { return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || str.HasPathPrefix(sub, "testdata") } - if !inTestdata(relpath) { + if !inTestdata(rp.dir) { // In build.go, p.Root should only be set in the non-local-import case, or in // GOROOT or GOPATH. Since module mode only calls Import with path set to "." // and the module index doesn't apply outside modules, the GOROOT case is @@ -284,8 +383,8 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im if ctxt.GOROOT != "" && str.HasFilePathPrefix(p.Dir, cfg.GOROOTsrc) && p.Dir != cfg.GOROOTsrc { p.Root = ctxt.GOROOT p.Goroot = true - modprefix := str.TrimFilePathPrefix(mi.modroot, cfg.GOROOTsrc) - p.ImportPath = relpath + modprefix := str.TrimFilePathPrefix(rp.modroot, cfg.GOROOTsrc) + p.ImportPath = rp.dir if modprefix != "" { p.ImportPath = filepath.Join(modprefix, p.ImportPath) } @@ -557,20 +656,21 @@ func IsStandardPackage(goroot_, compiler, path string) bool { reldir = str.TrimFilePathPrefix(reldir, "cmd") modroot = filepath.Join(modroot, "cmd") } - mod, err := Get(modroot) - if err != nil { + if _, err := GetPackage(modroot, filepath.Join(modroot, reldir)); err == nil { + // Note that goroot.IsStandardPackage doesn't check that the directory + // actually contains any go files-- merely that it exists. GetPackage + // returning a nil error is enough for us to know the directory exists. + return true + } else if errors.Is(err, ErrNotIndexed) { + // Fall back because package isn't indexable. (Probably because + // a file was modified recently) return goroot.IsStandardPackage(goroot_, compiler, path) } - - pkgs := mod.Packages() - i := sort.SearchStrings(pkgs, reldir) - return i != len(pkgs) && pkgs[i] == reldir + return false } // IsDirWithGoFiles is the equivalent of fsys.IsDirWithGoFiles using the information in the index. -func (mi *ModuleIndex) IsDirWithGoFiles(relpath string) (_ bool, err error) { - rp := mi.indexPackage(relpath) - +func (rp *IndexPackage) IsDirWithGoFiles() (_ bool, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("error reading module index: %v", e) @@ -585,9 +685,7 @@ func (mi *ModuleIndex) IsDirWithGoFiles(relpath string) (_ bool, err error) { } // ScanDir implements imports.ScanDir using the information in the index. -func (mi *ModuleIndex) ScanDir(path string, tags map[string]bool) (sortedImports []string, sortedTestImports []string, err error) { - rp := mi.indexPackage(path) - +func (rp *IndexPackage) ScanDir(tags map[string]bool) (sortedImports []string, sortedTestImports []string, err error) { // TODO(matloob) dir should eventually be relative to indexed directory // TODO(matloob): skip reading raw package and jump straight to data we need? @@ -675,20 +773,22 @@ func shouldBuild(sf *sourceFile, tags map[string]bool) bool { return true } -// index package holds the information needed to access information in the -// index about a package. -type indexPackage struct { +// IndexPackage holds the information needed to access information in the +// index needed to load a package in a specific directory. +type IndexPackage struct { error error dir string // directory of the package relative to the modroot + modroot string + // Source files sourceFiles []*sourceFile } var errCannotFindPackage = errors.New("cannot find package") -// indexPackage returns an indexPackage constructed using the information in the ModuleIndex. -func (mi *ModuleIndex) indexPackage(path string) *indexPackage { +// Package returns an IndexPackage constructed using the information in the Module. +func (mi *Module) Package(path string) *IndexPackage { defer func() { if e := recover(); e != nil { base.Fatalf("error reading module index: %v", e) @@ -696,12 +796,18 @@ func (mi *ModuleIndex) indexPackage(path string) *indexPackage { }() offset, ok := mi.packages[path] if !ok { - return &indexPackage{error: fmt.Errorf("%w %q in:\n\t%s", errCannotFindPackage, path, filepath.Join(mi.modroot, path))} + return &IndexPackage{error: fmt.Errorf("%w %q in:\n\t%s", errCannotFindPackage, path, filepath.Join(mi.modroot, path))} } // TODO(matloob): do we want to lock on the module index? d := mi.od.decoderAt(offset) - rp := new(indexPackage) + p := decodePackage(d, mi.od) + p.modroot = mi.modroot + return p +} + +func decodePackage(d *decoder, od offsetDecoder) *IndexPackage { + rp := new(IndexPackage) if errstr := d.string(); errstr != "" { rp.error = errors.New(errstr) } @@ -711,7 +817,7 @@ func (mi *ModuleIndex) indexPackage(path string) *indexPackage { for i := uint32(0); i < numSourceFiles; i++ { offset := d.uint32() rp.sourceFiles[i] = &sourceFile{ - od: mi.od.offsetDecoderAt(offset), + od: od.offsetDecoderAt(offset), } } return rp diff --git a/src/cmd/go/internal/modindex/scan.go b/src/cmd/go/internal/modindex/scan.go index d1f73dbb53..eb84bf8d89 100644 --- a/src/cmd/go/internal/modindex/scan.go +++ b/src/cmd/go/internal/modindex/scan.go @@ -65,7 +65,15 @@ func indexModule(modroot string) ([]byte, error) { if err != nil { return nil, err } - return encodeModule(packages), nil + return encodeModuleBytes(packages), nil +} + +// indexModule indexes the package at the given directory and returns its +// encoded representation. It returns ErrNotIndexed if the package can't +// be indexed. +func indexPackage(modroot, pkgdir string) []byte { + p := importRaw(modroot, relPath(pkgdir, modroot)) + return encodePackageBytes(p) } // rawPackage holds the information from each package that's needed to diff --git a/src/cmd/go/internal/modindex/write.go b/src/cmd/go/internal/modindex/write.go index 0c3123a46f..3408248bd9 100644 --- a/src/cmd/go/internal/modindex/write.go +++ b/src/cmd/go/internal/modindex/write.go @@ -11,9 +11,9 @@ import ( const indexVersion = "go index v0" -// encodeModule produces the encoded representation of the module index. -// encodeModule may modify the packages slice. -func encodeModule(packages []*rawPackage) []byte { +// encodeModuleBytes produces the encoded representation of the module index. +// encodeModuleBytes may modify the packages slice. +func encodeModuleBytes(packages []*rawPackage) []byte { e := newEncoder() e.Bytes([]byte(indexVersion)) e.Bytes([]byte{'\n'}) @@ -39,6 +39,18 @@ func encodeModule(packages []*rawPackage) []byte { return e.b } +func encodePackageBytes(p *rawPackage) []byte { + e := newEncoder() + e.Bytes([]byte(indexVersion)) + e.Bytes([]byte{'\n'}) + stringTableOffsetPos := e.Pos() // fill this at the end + e.Uint32(0) // string table offset + encodePackage(e, p) + e.IntAt(e.Pos(), stringTableOffsetPos) + e.Bytes(e.stringTable) + return e.b +} + func encodePackage(e *encoder, p *rawPackage) { e.String(p.error) e.String(p.dir) diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index f7810ca5c6..f2c7592a28 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -657,11 +657,11 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile // We don't care about build tags, not even "+build ignore". // We're just looking for a plausible directory. res := haveGoFilesCache.Do(dir, func() any { - // modindex.Get will return ErrNotIndexed for any directories which + // modindex.GetPackage will return ErrNotIndexed for any directories which // are reached through a symlink, so that they will be handled by // fsys.IsDirWithGoFiles below. - if mi, err := modindex.Get(mdir); err == nil { - isDirWithGoFiles, err := mi.IsDirWithGoFiles(mi.RelPath(dir)) + if ip, err := modindex.GetPackage(mdir, dir); err == nil { + isDirWithGoFiles, err := ip.IsDirWithGoFiles() return goFilesEntry{isDirWithGoFiles, err} } else if !errors.Is(err, modindex.ErrNotIndexed) { return goFilesEntry{err: err} diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index b2c3ba2633..ba85dc2438 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -2102,8 +2102,8 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) // may see these legacy imports. We drop them so that the module // search does not look for modules to try to satisfy them. func scanDir(modroot string, dir string, tags map[string]bool) (imports_, testImports []string, err error) { - if mi, mierr := modindex.Get(modroot); mierr == nil { - imports_, testImports, err = mi.ScanDir(mi.RelPath(dir), tags) + if ip, mierr := modindex.GetPackage(modroot, dir); mierr == nil { + imports_, testImports, err = ip.ScanDir(tags) goto Happy } else if !errors.Is(mierr, modindex.ErrNotIndexed) { return nil, nil, mierr diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 27af78d99e..69e5fbd93b 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -74,6 +74,9 @@ import ( // If path is the path of the main module and the query is "latest", // Query returns Target.Version as the version. func Query(ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) { + ctx, span := trace.StartSpan(ctx, "modload.Query "+path) + defer span.Done() + var info *modfetch.RevInfo err := modfetch.TryProxies(func(proxy string) (err error) { info, err = queryProxy(ctx, proxy, path, query, current, allowed) diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go index 4b90392d94..856390a0f2 100644 --- a/src/cmd/go/internal/modload/search.go +++ b/src/cmd/go/internal/modload/search.go @@ -23,6 +23,7 @@ import ( "cmd/go/internal/modindex" "cmd/go/internal/par" "cmd/go/internal/search" + "cmd/go/internal/trace" "golang.org/x/mod/module" ) @@ -38,6 +39,9 @@ const ( // a global) for tags, can include or exclude packages in the standard library, // and is restricted to the given list of modules. func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) { + ctx, span := trace.StartSpan(ctx, "modload.matchPackages") + defer span.Done() + m.Pkgs = []string{} isMatch := func(string) bool { return true } @@ -69,6 +73,9 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f q := par.NewQueue(runtime.GOMAXPROCS(0)) walkPkgs := func(root, importPathRoot string, prune pruning) { + _, span := trace.StartSpan(ctx, "walkPkgs "+root) + defer span.Done() + root = filepath.Clean(root) err := fsys.Walk(root, func(path string, fi fs.FileInfo, err error) error { if err != nil { @@ -188,7 +195,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } modPrefix = mod.Path } - if mi, err := modindex.Get(root); err == nil { + if mi, err := modindex.GetModule(root); err == nil { walkFromIndex(mi, modPrefix, isMatch, treeCanMatch, tags, have, addPkg) continue } else if !errors.Is(err, modindex.ErrNotIndexed) { @@ -206,9 +213,9 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } // walkFromIndex matches packages in a module using the module index. modroot -// is the module's root directory on disk, index is the ModuleIndex for the +// is the module's root directory on disk, index is the modindex.Module for the // module, and importPathRoot is the module's path prefix. -func walkFromIndex(index *modindex.ModuleIndex, importPathRoot string, isMatch, treeCanMatch func(string) bool, tags, have map[string]bool, addPkg func(string)) { +func walkFromIndex(index *modindex.Module, importPathRoot string, isMatch, treeCanMatch func(string) bool, tags, have map[string]bool, addPkg func(string)) { loopPackages: for _, reldir := range index.Packages() { // Avoid .foo, _foo, and testdata subdirectory trees. @@ -245,7 +252,7 @@ loopPackages: if !have[name] { have[name] = true if isMatch(name) { - if _, _, err := index.ScanDir(reldir, tags); err != imports.ErrNoGo { + if _, _, err := index.Package(reldir).ScanDir(tags); err != imports.ErrNoGo { addPkg(name) } } diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 846e2c8b77..a5b5570e05 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -164,13 +164,16 @@ func (b *Builder) toolID(name string) string { cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - base.Fatalf("%s: %v\n%s%s", desc, err, stdout.Bytes(), stderr.Bytes()) + if stderr.Len() > 0 { + os.Stderr.Write(stderr.Bytes()) + } + base.Fatalf("go: error obtaining buildID for %s: %v", desc, err) } line := stdout.String() f := strings.Fields(line) if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") { - base.Fatalf("%s -V=full: unexpected output:\n\t%s", desc, line) + base.Fatalf("go: parsing buildID from %s -V=full: unexpected output:\n\t%s", desc, line) } if f[2] == "devel" { // On the development branch, use the content ID part of the build ID. diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 2becc6d946..c88b315d2c 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -2405,6 +2405,7 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s } // gccld runs the gcc linker to create an executable from a set of object files. +// Any error output is only displayed for BuildN or BuildX. func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flags []string, objs []string) error { var cmd []string if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 { @@ -2450,11 +2451,8 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag save = append(save, line) } out = bytes.Join(save, nil) - if len(out) > 0 { + if len(out) > 0 && (cfg.BuildN || cfg.BuildX) { b.showOutput(nil, dir, p.ImportPath, b.processOutput(out)) - if err != nil { - err = errPrintedOutput - } } } return err @@ -2913,10 +2911,16 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo switch cfg.BuildToolchainName { case "gc": importGo := objdir + "_cgo_import.go" - if err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil { + dynOutGo, dynOutObj, err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj) + if err != nil { return nil, nil, err } - outGo = append(outGo, importGo) + if dynOutGo != "" { + outGo = append(outGo, dynOutGo) + } + if dynOutObj != "" { + outObj = append(outObj, dynOutObj) + } case "gccgo": defunC := objdir + "_cgo_defun.c" @@ -3011,11 +3015,13 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo // dynimport creates a Go source file named importGo containing // //go:cgo_import_dynamic directives for each symbol or library // dynamically imported by the object files outObj. -func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error { +// dynOutGo, if not empty, is a new Go file to build as part of the package. +// dynOutObj, if not empty, is a new file to add to the generated archive. +func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) (dynOutGo, dynOutObj string, err error) { cfile := objdir + "_cgo_main.c" ofile := objdir + "_cgo_main.o" if err := b.gcc(a, p, objdir, ofile, cflags, cfile); err != nil { - return err + return "", "", err } // Gather .syso files from this package and all (transitive) dependencies. @@ -3060,7 +3066,22 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe } } if err := b.gccld(a, p, objdir, dynobj, ldflags, linkobj); err != nil { - return err + // We only need this information for internal linking. + // If this link fails, mark the object as requiring + // external linking. This link can fail for things like + // syso files that have unexpected dependencies. + // cmd/link explicitly looks for the name "dynimportfail". + // See issue #52863. + fail := objdir + "dynimportfail" + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "echo > %s", fail) + } + if !cfg.BuildN { + if err := os.WriteFile(fail, nil, 0666); err != nil { + return "", "", err + } + } + return "", fail, nil } // cgo -dynimport @@ -3068,7 +3089,11 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = []string{"-dynlinker"} // record path to dynamic linker } - return b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + err = b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + if err != nil { + return "", "", err + } + return importGo, "", nil } // Run SWIG on all SWIG input files. diff --git a/src/cmd/go/testdata/script/cgo_undef.txt b/src/cmd/go/testdata/script/cgo_undef.txt new file mode 100644 index 0000000000..30034fbac1 --- /dev/null +++ b/src/cmd/go/testdata/script/cgo_undef.txt @@ -0,0 +1,68 @@ +# Issue 52863. + +# We manually create a .syso and a .a file in package a, +# such that the .syso file only works when linked against the .a file. +# Package a has #cgo LDFLAGS to make this happen. +# +# Package c imports package a, and uses cgo itself. +# The generation of the _cgo_import.go for package c will fail, +# because it won't know that it has to link against a/libb.a +# (because we don't gather the #cgo LDFLAGS from all transitively +# imported packages). +# +# The _cgo_import.go file is only needed for internal linking. +# When generating _cgo_import.go for package c fails, an ordinary +# external link should still work. But an internal link is expected +# to fail, because the failure to create _cgo_import.go should cause +# the linker to report an inability to internally link. + +[short] skip +[!cgo] skip +[!exec:ar] skip + +cc -c -o a/b.syso b/b.c +cc -c -o b/lib.o b/lib.c +exec ar rc a/libb.a b/lib.o +go build +! go build -ldflags=-linkmode=internal +stderr 'some packages could not be built to support internal linking.*m/c|requires external linking|does not support internal cgo' + +-- go.mod -- +module m + +-- a/a.go -- +package a + +// #cgo LDFLAGS: -L. -lb +// extern int CFn(int); +import "C" + +func GoFn(v int) int { return int(C.CFn(C.int(v))) } + +-- b/b.c -- +extern int LibFn(int); +int CFn(int i) { return LibFn(i); } + +-- b/lib.c -- +int LibFn(int i) { return i; } + +-- c/c.go -- +package c + +// static int D(int i) { return i; } +import "C" + +import "m/a" + +func Fn(i int) (int, int) { + return a.GoFn(i), int(C.D(C.int(i))) +} + +-- main.go -- +package main + +import "m/c" + +func main() { + println(c.Fn(0)) +} diff --git a/src/cmd/go/testdata/script/mod_tidy_duplicates.txt b/src/cmd/go/testdata/script/mod_tidy_duplicates.txt new file mode 100644 index 0000000000..d454c8dc82 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_tidy_duplicates.txt @@ -0,0 +1,38 @@ +env GO111MODULE=on + +# Regression test for golang.org/issue/28456: +# 'go mod tidy' should not leave duplicate lines when re-writing the file. + +go mod tidy +cmp go.sum golden.sum + +-- go.mod -- +module use + +go 1.16 + +require rsc.io/quote v1.5.2 + +-- go.sum -- +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= +-- golden.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= +-- main.go -- +package use + +import _ "rsc.io/quote" diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 6d19b8b5bb..4dd43a16ab 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -246,6 +246,15 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { return true, "some input objects have an unrecognized file format" } + if len(dynimportfail) > 0 { + // This error means that we were unable to generate + // the _cgo_import.go file for some packages. + // This typically means that there are some dependencies + // that the cgo tool could not figure out. + // See issue #52863. + return true, fmt.Sprintf("some packages could not be built to support internal linking (%v)", dynimportfail) + } + return false, "" } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 9a5d89a6f7..a3d8202e2c 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -344,6 +344,11 @@ var ( // to support internal linking mode. externalobj = false + // dynimportfail is a list of packages for which generating + // the dynimport file, _cgo_import.go, failed. If there are + // any of these objects, we must link externally. Issue 52863. + dynimportfail []string + // unknownObjFormat is set to true if we see an object whose // format we don't recognize. unknownObjFormat = false @@ -1030,6 +1035,10 @@ func loadobjfile(ctxt *Link, lib *sym.Library) { continue } + if arhdr.name == "dynimportfail" { + dynimportfail = append(dynimportfail, lib.Pkg) + } + // Skip other special (non-object-file) sections that // build tools may have added. Such sections must have // short names so that the suffix is not truncated. diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index a30db9a012..11804d0b90 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -185,23 +185,195 @@ func httpMain(w http.ResponseWriter, r *http.Request) { var templMain = template.Must(template.New("").Parse(` +cmd/trace: the Go trace event viewer
++ This web server provides various visualizations of an event log gathered during + the execution of a Go program that uses the runtime/trace package. +
+ +Event timelines for running goroutines
{{if $}} ++ Large traces are split into multiple sections of equal data size + (not duration) to avoid overwhelming the visualizer. +
+
+ This view displays a timeline for each of the GOMAXPROCS logical + processors, showing which goroutine (if any) was running on that + logical processor at each moment. + + Each goroutine has an identifying number (e.g. G123), main function, + and color. + + A colored bar represents an uninterrupted span of execution. + + Execution of a goroutine may migrate from one logical processor to another, + causing a single colored bar to be horizontally continuous but + vertically displaced. +
++ Clicking on a span reveals information about it, such as its + duration, its causal predecessors and successors, and the stack trace + at the final moment when it yielded the logical processor, for example + because it made a system call or tried to acquire a mutex. + + Directly underneath each bar, a smaller bar or more commonly a fine + vertical line indicates an event occuring during its execution. + Some of these are related to garbage collection; most indicate that + a goroutine yielded its logical processor but then immediately resumed execution + on the same logical processor. Clicking on the event displays the stack trace + at the moment it occurred. +
++ The causal relationships between spans of goroutine execution + can be displayed by clicking the Flow Events button at the top. +
++ At the top ("STATS"), there are three additional timelines that + display statistical information. + + "Goroutines" is a time series of the count of existing goroutines; + clicking on it displays their breakdown by state at that moment: + running, runnable, or waiting. + + "Heap" is a time series of the amount of heap memory allocated (in orange) + and (in green) the allocation limit at which the next GC cycle will begin. + + "Threads" shows the number of kernel threads in existence: there is + always one kernel thread per logical processor, and additional threads + are created for calls to non-Go code such as a system call or a + function written in C. +
++ Above the event trace for the first logical processor are + traces for various runtime-internal events. + + The "GC" bar shows when the garbage collector is running, and in which stage. + Garbage collection may temporarily affect all the logical processors + and the other metrics. + + The "Network", "Timers", and "Syscalls" traces indicate events in + the runtime that cause goroutines to wake up. +
++ The visualization allows you to navigate events at scales ranging from several + seconds to a handful of nanoseconds. + + Consult the documentation for the Chromium Trace Event Profiling Tool + for help navigating the view. +
+ + ++ This view displays information about each set of goroutines that + shares the same main function. + + Clicking on a main function shows links to the four types of + blocking profile (see below) applied to that subset of goroutines. + + It also shows a table of specific goroutine instances, with various + execution statistics and a link to the event timeline for each one. + + The timeline displays only the selected goroutine and any others it + interacts with via block/unblock events. (The timeline is + goroutine-oriented rather than logical processor-oriented.) +
+ ++ Each link below displays a global profile in zoomable graph form as + produced by pprof's "web" command. + + In addition there is a link to download the profile for offline + analysis with pprof. + + All four profiles represent causes of delay that prevent a goroutine + from running on a logical processor: because it was waiting for the network, + for a synchronization operation on a mutex or channel, for a system call, + or for a logical processor to become available. +
++ The trace API allows a target program to annotate a region of code + within a goroutine, such as a key function, so that its performance + can be analyzed. + + Log events may be + associated with a region to record progress and relevant values. + + The API also allows annotation of higher-level + tasks, + which may involve work across many goroutines. +
++ The links below display, for each region and task, a histogram of its execution times. + + Each histogram bucket contains a sample trace that records the + sequence of events such as goroutine creations, log events, and + subregion start/end times. + + For each task, you can click through to a logical-processor or + goroutine-oriented view showing the tasks and regions on the + timeline. + + Such information may help uncover which steps in a region are + unexpectedly slow, or reveal relationships between the data values + logged in a request and its running time. +
+ + ++ This chart indicates the maximum GC pause time (the largest x value + for which y is zero), and more generally, the fraction of time that + the processors are available to application goroutines ("mutators"), + for any time window of a specified size, in the worst case. +
`)) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s index 6abd48eef0..565357288a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s @@ -30,7 +30,7 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48 MOVV trap+0(FP), R11 // syscall entry SYSCALL MOVV R4, r1+32(FP) - MOVV R5, r2+40(FP) + MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 JAL runtime·exitsyscall(SB) RET @@ -50,5 +50,5 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48 MOVV trap+0(FP), R11 // syscall entry SYSCALL MOVV R4, r1+32(FP) - MOVV R5, r2+40(FP) + MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 RET diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go index 934af313c3..15721a5104 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -8,7 +8,6 @@ package unix import ( - "bytes" "unsafe" ) @@ -45,13 +44,7 @@ func NewIfreq(name string) (*Ifreq, error) { // Name returns the interface name associated with the Ifreq. func (ifr *Ifreq) Name() string { - // BytePtrToString requires a NULL terminator or the program may crash. If - // one is not present, just return the empty string. - if !bytes.Contains(ifr.raw.Ifrn[:], []byte{0x00}) { - return "" - } - - return BytePtrToString(&ifr.raw.Ifrn[0]) + return ByteSliceToString(ifr.raw.Ifrn[:]) } // According to netdevice(7), only AF_INET addresses are returned for numerous diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go index 5c2003cec6..932996c75b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -618,6 +618,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Getpriority(which int, who int) (n int, err error) //sysnb Getrlimit(which int, lim *Rlimit) (err error) //sysnb Getrusage(who int, rusage *Rusage) (err error) +//sysnb Getsid(pid int) (sid int, err error) //sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Getuid() (uid int) //sys Kill(pid int, signum syscall.Signal) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 234fd4a5d1..1b305fab1b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -5,7 +5,7 @@ // +build 386,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 58619b7589..6bcdef5dd6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -5,7 +5,7 @@ // +build amd64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 3a64ff59dc..e65df0f8d1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -5,7 +5,7 @@ // +build arm,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index abe0b92578..c7021115aa 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -5,7 +5,7 @@ // +build arm64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index ebc5f3218e..0d83a1cd45 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -5,7 +5,7 @@ // +build loong64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 14d7a84399..7f44a495b7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -5,7 +5,7 @@ // +build mips,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 99e7c4ac0b..2f92b4e48e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -5,7 +5,7 @@ // +build mips64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 496364c33c..f5367a966b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -5,7 +5,7 @@ // +build mips64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 3e40830857..2e22337d7c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -5,7 +5,7 @@ // +build mipsle,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 1151a7dfab..858c4f30f5 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -5,7 +5,7 @@ // +build ppc,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index ed17f249e7..af2a7ba6e6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -5,7 +5,7 @@ // +build ppc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index d84a37c1ac..eaa2eb8e24 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -5,7 +5,7 @@ // +build ppc64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 5cafba83f6..faaa9f0637 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -5,7 +5,7 @@ // +build riscv64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 6d122da41c..0d161f0b75 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -5,7 +5,7 @@ // +build s390x,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 6bd19e51db..4fd497a3e3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -5,7 +5,7 @@ // +build sparc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index d12f4fbfea..fdf53f8daf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -66,6 +66,7 @@ import ( //go:cgo_import_dynamic libc_getpriority getpriority "libc.so" //go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" //go:cgo_import_dynamic libc_getrusage getrusage "libc.so" +//go:cgo_import_dynamic libc_getsid getsid "libc.so" //go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" //go:cgo_import_dynamic libc_getuid getuid "libc.so" //go:cgo_import_dynamic libc_kill kill "libc.so" @@ -202,6 +203,7 @@ import ( //go:linkname procGetpriority libc_getpriority //go:linkname procGetrlimit libc_getrlimit //go:linkname procGetrusage libc_getrusage +//go:linkname procGetsid libc_getsid //go:linkname procGettimeofday libc_gettimeofday //go:linkname procGetuid libc_getuid //go:linkname procKill libc_kill @@ -339,6 +341,7 @@ var ( procGetpriority, procGetrlimit, procGetrusage, + procGetsid, procGettimeofday, procGetuid, procKill, @@ -1044,6 +1047,17 @@ func Getrusage(who int, rusage *Rusage) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getsid(pid int) (sid int, err error) { + r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetsid)), 1, uintptr(pid), 0, 0, 0, 0, 0) + sid = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Gettimeofday(tv *Timeval) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGettimeofday)), 1, uintptr(unsafe.Pointer(tv)), 0, 0, 0, 0, 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 5314092568..4948362f2c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index b02ab83dbd..f64345e0e2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 9e6871d2e0..72469c79e7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index b732d12559..68f072283a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 61fbb24f8d..090ae46c67 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 5310f71ea5..03604cca13 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 219bbb1267..fe57a7b265 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index be9432da54..3f0db4da81 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index d0155a42e6..70ecd3b239 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 01c17bcc6f..4e700120db 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 944a9c3c78..34a57c6992 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 5d2c90e1ce..6b84a47296 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index e173cb5157..c4a305fe2e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 6106715d5c..a1f1e4c9e1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index ca7b37b4b5..df95ebf3a1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index baf5fe6504..2ed718ca06 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -94,10 +94,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte Pad_cgo_0 [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index e21ae8ecfa..b4fb97ebe6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -96,10 +96,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index f190651cd9..2c4675040e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -98,10 +98,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go index 84747c582c..ddee045147 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go @@ -94,10 +94,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go index ac5c8b6370..eb13d4e8bf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go @@ -94,10 +94,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 1280a9e701..4e4b5b6343 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -40,7 +40,7 @@ golang.org/x/mod/zip # golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 ## explicit golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a +# golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 diff --git a/src/compress/gzip/example_test.go b/src/compress/gzip/example_test.go index 27aae152d4..1ba4080ea0 100644 --- a/src/compress/gzip/example_test.go +++ b/src/compress/gzip/example_test.go @@ -160,6 +160,10 @@ func Example_compressingReader() { // httpWriter is the body of the HTTP request, as an io.Writer. bodyReader, httpWriter := io.Pipe() + // Make sure that bodyReader is always closed, so that the + // goroutine below will always exit. + defer bodyReader.Close() + // gzipWriter compresses data to httpWriter. gzipWriter := gzip.NewWriter(httpWriter) @@ -197,7 +201,6 @@ func Example_compressingReader() { // Note that passing req to http.Client.Do promises that it // will close the body, in this case bodyReader. - // That ensures that the goroutine will exit. resp, err := ts.Client().Do(req) if err != nil { log.Fatal(err) diff --git a/src/debug/dwarf/line.go b/src/debug/dwarf/line.go index bb281fbdd9..4df4a1751f 100644 --- a/src/debug/dwarf/line.go +++ b/src/debug/dwarf/line.go @@ -215,7 +215,11 @@ func (r *LineReader) readHeader(compDir string) error { } else { headerLength = Offset(buf.uint32()) } - r.programOffset = buf.off + headerLength + programOffset := buf.off + headerLength + if programOffset > r.endOffset { + return DecodeError{"line", hdrOffset, fmt.Sprintf("malformed line table: program offset %d exceeds end offset %d", programOffset, r.endOffset)} + } + r.programOffset = programOffset r.minInstructionLength = int(buf.uint8()) if r.version >= 4 { // [DWARF4 6.2.4] diff --git a/src/embed/embed.go b/src/embed/embed.go index cbe2d398fb..c54b961d15 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -91,6 +91,7 @@ // It can only be used with variables at package scope, not with local variables. // // Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links. +// Patterns must not match files whose names include the special punctuation characters " * < > ? ` ' | / \ and :. // Matches for empty directories are ignored. After that, each pattern in a //go:embed line // must match at least one file or non-empty directory. // diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index 565d9a8bea..257591262f 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -148,6 +148,10 @@ func (d *Decoder) DecodeElement(v any, start *StartElement) error { if val.Kind() != reflect.Pointer { return errors.New("non-pointer passed to Unmarshal") } + + if val.IsNil() { + return errors.New("nil pointer passed to Unmarshal") + } return d.unmarshal(val.Elem(), start) } diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go index 391fe731a8..6ef55de77b 100644 --- a/src/encoding/xml/read_test.go +++ b/src/encoding/xml/read_test.go @@ -1079,3 +1079,18 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) { t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } } + +// golang.org/issues/53350 +func TestUnmarshalIntoNil(t *testing.T) { + type T struct { + A int `xml:"A"` + } + + var nilPointer *T + err := Unmarshal([]byte("