From e0c76d95abfc1621259864adb3d101cf6f1f90fc Mon Sep 17 00:00:00 2001
From: Kir Kolyshkin Types
-Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" . -TypeName = identifier | QualifiedIdent . -TypeArgs = "[" TypeList [ "," ] "]" . -TypeList = Type { "," Type } . -TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | - SliceType | MapType | ChannelType . +Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" . +TypeName = identifier | QualifiedIdent . +TypeArgs = "[" TypeList [ "," ] "]" . +TypeList = Type { "," Type } . +TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | + SliceType | MapType | ChannelType .
@@ -1222,12 +1222,12 @@
-FunctionType = "func" Signature . -Signature = Parameters [ Result ] . -Result = Parameters | Type . -Parameters = "(" [ ParameterList [ "," ] ] ")" . -ParameterList = ParameterDecl { "," ParameterDecl } . -ParameterDecl = [ IdentifierList ] [ "..." ] Type . +FunctionType = "func" Signature . +Signature = Parameters [ Result ] . +Result = Parameters | Type . +Parameters = "(" [ ParameterList [ "," ] ] ")" . +ParameterList = ParameterDecl { "," ParameterDecl } . +ParameterDecl = [ IdentifierList ] [ "..." ] Type .
@@ -1634,8 +1634,8 @@
-MapType = "map" "[" KeyType "]" ElementType . -KeyType = Type . +MapType = "map" "[" KeyType "]" ElementType . +KeyType = Type .
@@ -2176,7 +2176,7 @@
-Block = "{" StatementList "}" . +Block = "{" StatementList "}" . StatementList = { Statement ";" } .@@ -2233,8 +2233,8 @@
-Declaration = ConstDecl | TypeDecl | VarDecl . -TopLevelDecl = Declaration | FunctionDecl | MethodDecl . +Declaration = ConstDecl | TypeDecl | VarDecl . +TopLevelDecl = Declaration | FunctionDecl | MethodDecl .
@@ -2679,9 +2679,9 @@
-TypeParameters = "[" TypeParamList [ "," ] "]" . -TypeParamList = TypeParamDecl { "," TypeParamDecl } . -TypeParamDecl = IdentifierList TypeConstraint . +TypeParameters = "[" TypeParamList [ "," ] "]" . +TypeParamList = TypeParamDecl { "," TypeParamDecl } . +TypeParamDecl = IdentifierList TypeConstraint .
@@ -2869,8 +2869,8 @@
-VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) . -VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) . +VarDecl = "var" ( VarSpec | "(" { VarSpec ";" } ")" ) . +VarSpec = IdentifierList ( Type [ "=" ExpressionList ] | "=" ExpressionList ) .
@@ -3210,15 +3210,15 @@Composite literals
-CompositeLit = LiteralType LiteralValue . -LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | - SliceType | MapType | TypeName [ TypeArgs ] . -LiteralValue = "{" [ ElementList [ "," ] ] "}" . -ElementList = KeyedElement { "," KeyedElement } . -KeyedElement = [ Key ":" ] Element . -Key = FieldName | Expression | LiteralValue . -FieldName = identifier . -Element = Expression | LiteralValue . +CompositeLit = LiteralType LiteralValue . +LiteralType = StructType | ArrayType | "[" "..." "]" ElementType | + SliceType | MapType | TypeName [ TypeArgs ] . +LiteralValue = "{" [ ElementList [ "," ] ] "}" . +ElementList = KeyedElement { "," KeyedElement } . +KeyedElement = [ Key ":" ] Element . +Key = FieldName | Expression | LiteralValue . +FieldName = identifier . +Element = Expression | LiteralValue .@@ -3450,22 +3450,21 @@
Primary expressions
-PrimaryExpr = - Operand | - Conversion | - MethodExpr | - PrimaryExpr Selector | - PrimaryExpr Index | - PrimaryExpr Slice | - PrimaryExpr TypeAssertion | - PrimaryExpr Arguments . +PrimaryExpr = Operand | + Conversion | + MethodExpr | + PrimaryExpr Selector | + PrimaryExpr Index | + PrimaryExpr Slice | + PrimaryExpr TypeAssertion | + PrimaryExpr Arguments . -Selector = "." identifier . -Index = "[" Expression [ "," ] "]" . -Slice = "[" [ Expression ] ":" [ Expression ] "]" | - "[" [ Expression ] ":" Expression ":" Expression "]" . -TypeAssertion = "." "(" Type ")" . -Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" . +Selector = "." identifier . +Index = "[" Expression [ "," ] "]" . +Slice = "[" [ Expression ] ":" [ Expression ] "]" | + "[" [ Expression ] ":" Expression ":" Expression "]" . +TypeAssertion = "." "(" Type ")" . +Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .@@ -3638,8 +3637,8 @@Method expressions
-MethodExpr = ReceiverType "." MethodName . -ReceiverType = Type . +MethodExpr = ReceiverType "." MethodName . +ReceiverType = Type .@@ -5916,11 +5915,10 @@
Statements
-Statement = - Declaration | LabeledStmt | SimpleStmt | - GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | - FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | - DeferStmt . +Statement = Declaration | LabeledStmt | SimpleStmt | + GoStmt | ReturnStmt | BreakStmt | ContinueStmt | GotoStmt | + FallthroughStmt | Block | IfStmt | SwitchStmt | SelectStmt | ForStmt | + DeferStmt . SimpleStmt = EmptyStmt | ExpressionStmt | SendStmt | IncDecStmt | Assignment | ShortVarDecl .@@ -6132,7 +6130,7 @@Assignment statements
Assignment = ExpressionList assign_op ExpressionList . -assign_op = [ add_op | mul_op ] "=" . +assign_op = [ add_op | mul_op ] "=" .@@ -6548,7 +6546,7 @@
For statements
-ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . +ForStmt = "for" [ Condition | ForClause | RangeClause ] Block . Condition = Expression .@@ -6580,8 +6578,8 @@For statements with
for
clauseForClause = [ InitStmt ] ";" [ Condition ] ";" [ PostStmt ] . -InitStmt = SimpleStmt . -PostStmt = SimpleStmt . +InitStmt = SimpleStmt . +PostStmt = SimpleStmt .@@ -7909,7 +7907,7 @@Source file organization
-SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . +SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .Package clause
@@ -7920,8 +7918,8 @@Package clause
-PackageClause = "package" PackageName . -PackageName = identifier . +PackageClause = "package" PackageName . +PackageName = identifier .@@ -7950,9 +7948,9 @@
Import declarations
-ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . -ImportSpec = [ "." | PackageName ] ImportPath . -ImportPath = string_lit . +ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) . +ImportSpec = [ "." | PackageName ] ImportPath . +ImportPath = string_lit .From 8391579ecea7dede2f2c1dc79954131e1eae1ade Mon Sep 17 00:00:00 2001 From: Michael Pratt
Date: Fri, 13 Dec 2024 10:26:50 -0500 Subject: [PATCH 019/397] runtime: migrate missing map linkname allowlists The swissmap implementation forgot to copy some of the linkname allowlists from the old implementation. Copy them from map_noswiss.go. Some were missing linkname entirely; others were linknamed but missing the hall of shame comment. For #54766. Change-Id: Icc715384123e73d868b4cb729ab639abcd6bbfd7 Reviewed-on: https://go-review.googlesource.com/c/go/+/635995 Reviewed-by: Cherry Mui Auto-Submit: Michael Pratt LUCI-TryBot-Result: Go LUCI --- src/runtime/map_swiss.go | 158 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/src/runtime/map_swiss.go b/src/runtime/map_swiss.go index 75c72b20f5771c..e6e29bcfb800bb 100644 --- a/src/runtime/map_swiss.go +++ b/src/runtime/map_swiss.go @@ -39,6 +39,16 @@ func makemap64(t *abi.SwissMapType, hint int64, m *maps.Map) *maps.Map { // makemap_small implements Go map creation for make(map[k]v) and // make(map[k]v, hint) when hint is known to be at most abi.SwissMapGroupSlots // at compile time and the map needs to be allocated on the heap. +// +// makemap_small should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/bytedance/sonic +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// +//go:linkname makemap_small func makemap_small() *maps.Map { return maps.NewEmptyMap() } @@ -48,6 +58,16 @@ func makemap_small() *maps.Map { // can be created on the stack, m and optionally m.dirPtr may be non-nil. // If m != nil, the map can be created directly in m. // If m.dirPtr != nil, it points to a group usable for a small map. +// +// makemap should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/ugorji/go/codec +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// +//go:linkname makemap func makemap(t *abi.SwissMapType, hint int, m *maps.Map) *maps.Map { if hint < 0 { hint = 0 @@ -68,6 +88,15 @@ func makemap(t *abi.SwissMapType, hint int, m *maps.Map) *maps.Map { //go:linkname mapaccess1 func mapaccess1(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer +// mapaccess2 should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/ugorji/go/codec +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// +//go:linkname mapaccess2 func mapaccess2(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) (unsafe.Pointer, bool) func mapaccess1_fat(t *abi.SwissMapType, m *maps.Map, key, zero unsafe.Pointer) unsafe.Pointer { @@ -89,9 +118,29 @@ func mapaccess2_fat(t *abi.SwissMapType, m *maps.Map, key, zero unsafe.Pointer) // mapassign is pushed from internal/runtime/maps. We could just call it, but // we want to avoid one layer of call. // +// mapassign should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/bytedance/sonic +// - github.com/RomiChan/protobuf +// - github.com/segmentio/encoding +// - github.com/ugorji/go/codec +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname mapassign func mapassign(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer +// mapdelete should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/ugorji/go/codec +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// +//go:linkname mapdelete func mapdelete(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) { if raceenabled && m != nil { callerpc := sys.GetCallerPC() @@ -113,6 +162,21 @@ func mapdelete(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) { // The Iter struct pointed to by 'it' is allocated on the stack // by the compilers order pass or on the heap by reflect_mapiterinit. // Both need to have zeroed hiter since the struct contains pointers. +// +// mapiterinit should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/bytedance/sonic +// - github.com/goccy/go-json +// - github.com/RomiChan/protobuf +// - github.com/segmentio/encoding +// - github.com/ugorji/go/codec +// - github.com/wI2L/jettison +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// +//go:linkname mapiterinit func mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { if raceenabled && m != nil { callerpc := sys.GetCallerPC() @@ -123,6 +187,19 @@ func mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { it.Next() } +// mapiternext should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/bytedance/sonic +// - github.com/RomiChan/protobuf +// - github.com/segmentio/encoding +// - github.com/ugorji/go/codec +// - gonum.org/v1/gonum +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// +//go:linkname mapiternext func mapiternext(it *maps.Iter) { if raceenabled { callerpc := sys.GetCallerPC() @@ -145,6 +222,19 @@ func mapclear(t *abi.SwissMapType, m *maps.Map) { // Reflect stubs. Called from ../reflect/asm_*.s +// reflect_makemap is for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - gitee.com/quant1x/gox +// - github.com/modern-go/reflect2 +// - github.com/goccy/go-json +// - github.com/RomiChan/protobuf +// - github.com/segmentio/encoding +// - github.com/v2pro/plz +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname reflect_makemap reflect.makemap func reflect_makemap(t *abi.SwissMapType, cap int) *maps.Map { // Check invariants and reflects math. @@ -156,6 +246,16 @@ func reflect_makemap(t *abi.SwissMapType, cap int) *maps.Map { return makemap(t, cap, nil) } +// reflect_mapaccess is for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - gitee.com/quant1x/gox +// - github.com/modern-go/reflect2 +// - github.com/v2pro/plz +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname reflect_mapaccess reflect.mapaccess func reflect_mapaccess(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer) unsafe.Pointer { elem, ok := mapaccess2(t, m, key) @@ -176,6 +276,14 @@ func reflect_mapaccess_faststr(t *abi.SwissMapType, m *maps.Map, key string) uns return elem } +// reflect_mapassign is for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - gitee.com/quant1x/gox +// - github.com/v2pro/plz +// +// Do not remove or change the type signature. +// //go:linkname reflect_mapassign reflect.mapassign0 func reflect_mapassign(t *abi.SwissMapType, m *maps.Map, key unsafe.Pointer, elem unsafe.Pointer) { p := mapassign(t, m, key) @@ -198,26 +306,76 @@ func reflect_mapdelete_faststr(t *abi.SwissMapType, m *maps.Map, key string) { mapdelete_faststr(t, m, key) } +// reflect_mapiterinit is for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/modern-go/reflect2 +// - gitee.com/quant1x/gox +// - github.com/v2pro/plz +// - github.com/wI2L/jettison +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname reflect_mapiterinit reflect.mapiterinit func reflect_mapiterinit(t *abi.SwissMapType, m *maps.Map, it *maps.Iter) { mapiterinit(t, m, it) } +// reflect_mapiternext is for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - gitee.com/quant1x/gox +// - github.com/modern-go/reflect2 +// - github.com/goccy/go-json +// - github.com/v2pro/plz +// - github.com/wI2L/jettison +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname reflect_mapiternext reflect.mapiternext func reflect_mapiternext(it *maps.Iter) { mapiternext(it) } +// reflect_mapiterkey was for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/goccy/go-json +// - gonum.org/v1/gonum +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname reflect_mapiterkey reflect.mapiterkey func reflect_mapiterkey(it *maps.Iter) unsafe.Pointer { return it.Key() } +// reflect_mapiterelem was for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/goccy/go-json +// - gonum.org/v1/gonum +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname reflect_mapiterelem reflect.mapiterelem func reflect_mapiterelem(it *maps.Iter) unsafe.Pointer { return it.Elem() } +// reflect_maplen is for package reflect, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/goccy/go-json +// - github.com/wI2L/jettison +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// //go:linkname reflect_maplen reflect.maplen func reflect_maplen(m *maps.Map) int { if m == nil { From 1cbfe8c482a0ca0eb59daa89b92a10b7052d1a0f Mon Sep 17 00:00:00 2001 From: thepudds Date: Tue, 19 Sep 2023 14:44:08 -0400 Subject: [PATCH 020/397] fmt: add more function and allocation tests This is part of a series of CLs that aim to reduce how often interface arguments escape for the print functions in fmt. Currently, method values are one of two reasons reflect.Value.Interface always escapes its reflect.Value. Our later CLs modify behavior around method values, so we add some tests of function formatting (including method values) to help reduce the chances of breaking behavior later. We also add in some allocation tests focused on interface arguments for the print functions. These currently do not show any improvements compared to Go 1.21. These tests were originally in a later CL in our stack (CL 528538), but we split them out into this CL and moved them earlier in the stack. Updates #8618 Change-Id: Iec51abc3b7f86a2711e7497fc2fb7a678b9f8f73 Reviewed-on: https://go-review.googlesource.com/c/go/+/529575 Reviewed-by: Carlos Amedee Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- src/fmt/fmt_test.go | 68 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/src/fmt/fmt_test.go b/src/fmt/fmt_test.go index b7f9ccd494d099..82daf627717814 100644 --- a/src/fmt/fmt_test.go +++ b/src/fmt/fmt_test.go @@ -11,7 +11,6 @@ import ( "io" "math" "reflect" - "runtime" "strings" "testing" "time" @@ -112,6 +111,19 @@ func (p *P) String() string { return "String(p)" } +// Fn is a function type with a String method. +type Fn func() int + +func (fn Fn) String() string { return "String(fn)" } + +var fnValue Fn + +// U is a type with two unexported function fields. +type U struct { + u func() string + fn Fn +} + var barray = [5]renamedUint8{1, 2, 3, 4, 5} var bslice = barray[:] @@ -714,7 +726,6 @@ var fmtTests = []struct { // go syntax {"%#v", A{1, 2, "a", []int{1, 2}}, `fmt_test.A{i:1, j:0x2, s:"a", x:[]int{1, 2}}`}, {"%#v", new(byte), "(*uint8)(0xPTR)"}, - {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, {"%#v", make(chan int), "(chan int)(0xPTR)"}, {"%#v", uint64(1<<64 - 1), "0xffffffffffffffff"}, {"%#v", 1000000000, "1000000000"}, @@ -737,6 +748,54 @@ var fmtTests = []struct { {"%#v", 1.2345678, "1.2345678"}, {"%#v", float32(1.2345678), "1.2345678"}, + // functions + {"%v", TestFmtInterface, "0xPTR"}, // simple function + {"%v", reflect.ValueOf(TestFmtInterface), "0xPTR"}, + {"%v", G.GoString, "0xPTR"}, // method expression + {"%v", reflect.ValueOf(G.GoString), "0xPTR"}, + {"%v", G(23).GoString, "0xPTR"}, // method value + {"%v", reflect.ValueOf(G(23).GoString), "0xPTR"}, + {"%v", reflect.ValueOf(G(23)).Method(0), "0xPTR"}, + {"%v", Fn.String, "0xPTR"}, // method of function type + {"%v", reflect.ValueOf(Fn.String), "0xPTR"}, + {"%v", fnValue, "String(fn)"}, // variable of function type with String method + {"%v", reflect.ValueOf(fnValue), "String(fn)"}, + {"%v", [1]Fn{fnValue}, "[String(fn)]"}, // array of function type with String method + {"%v", reflect.ValueOf([1]Fn{fnValue}), "[String(fn)]"}, + {"%v", fnValue.String, "0xPTR"}, // method value from function type + {"%v", reflect.ValueOf(fnValue.String), "0xPTR"}, + {"%v", reflect.ValueOf(fnValue).Method(0), "0xPTR"}, + {"%v", U{}.u, " "}, // unexported function field + {"%v", reflect.ValueOf(U{}.u), " "}, + {"%v", reflect.ValueOf(U{}).Field(0), " "}, + {"%v", U{fn: fnValue}.fn, "String(fn)"}, // unexported field of function type with String method + {"%v", reflect.ValueOf(U{fn: fnValue}.fn), "String(fn)"}, + {"%v", reflect.ValueOf(U{fn: fnValue}).Field(1), " "}, + + // functions with go syntax + {"%#v", TestFmtInterface, "(func(*testing.T))(0xPTR)"}, // simple function + {"%#v", reflect.ValueOf(TestFmtInterface), "(func(*testing.T))(0xPTR)"}, + {"%#v", G.GoString, "(func(fmt_test.G) string)(0xPTR)"}, // method expression + {"%#v", reflect.ValueOf(G.GoString), "(func(fmt_test.G) string)(0xPTR)"}, + {"%#v", G(23).GoString, "(func() string)(0xPTR)"}, // method value + {"%#v", reflect.ValueOf(G(23).GoString), "(func() string)(0xPTR)"}, + {"%#v", reflect.ValueOf(G(23)).Method(0), "(func() string)(0xPTR)"}, + {"%#v", Fn.String, "(func(fmt_test.Fn) string)(0xPTR)"}, // method of function type + {"%#v", reflect.ValueOf(Fn.String), "(func(fmt_test.Fn) string)(0xPTR)"}, + {"%#v", fnValue, "(fmt_test.Fn)(nil)"}, // variable of function type with String method + {"%#v", reflect.ValueOf(fnValue), "(fmt_test.Fn)(nil)"}, + {"%#v", [1]Fn{fnValue}, "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"}, // array of function type with String method + {"%#v", reflect.ValueOf([1]Fn{fnValue}), "[1]fmt_test.Fn{(fmt_test.Fn)(nil)}"}, + {"%#v", fnValue.String, "(func() string)(0xPTR)"}, // method value from function type + {"%#v", reflect.ValueOf(fnValue.String), "(func() string)(0xPTR)"}, + {"%#v", reflect.ValueOf(fnValue).Method(0), "(func() string)(0xPTR)"}, + {"%#v", U{}.u, "(func() string)(nil)"}, // unexported function field + {"%#v", reflect.ValueOf(U{}.u), "(func() string)(nil)"}, + {"%#v", reflect.ValueOf(U{}).Field(0), "(func() string)(nil)"}, + {"%#v", U{fn: fnValue}.fn, "(fmt_test.Fn)(nil)"}, // unexported field of function type with String method + {"%#v", reflect.ValueOf(U{fn: fnValue}.fn), "(fmt_test.Fn)(nil)"}, + {"%#v", reflect.ValueOf(U{fn: fnValue}).Field(1), "(fmt_test.Fn)(nil)"}, + // Whole number floats are printed without decimals. See Issue 27634. {"%#v", 1.0, "1"}, {"%#v", 1000000.0, "1e+06"}, @@ -1438,6 +1497,9 @@ var mallocTest = []struct { {0, `Fprintf(buf, "%s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%s", "hello") }}, {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 7) }}, {0, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%x", 1<<16) }}, + {1, `Fprintf(buf, "%x")`, func() { mallocBuf.Reset(); i := 1 << 16; Fprintf(&mallocBuf, "%x", i) }}, // not constant + {4, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); s := []int{1, 2}; Fprintf(&mallocBuf, "%v", s) }}, + {1, `Fprintf(buf, "%v")`, func() { mallocBuf.Reset(); type P struct{ x, y int }; Fprintf(&mallocBuf, "%v", P{1, 2}) }}, {2, `Fprintf(buf, "%80000s")`, func() { mallocBuf.Reset(); Fprintf(&mallocBuf, "%80000s", "hello") }}, // large buffer (>64KB) // If the interface value doesn't need to allocate, amortized allocation overhead should be zero. {0, `Fprintf(buf, "%x %x %x")`, func() { @@ -1452,8 +1514,6 @@ func TestCountMallocs(t *testing.T) { switch { case testing.Short(): t.Skip("skipping malloc count in short mode") - case runtime.GOMAXPROCS(0) > 1: - t.Skip("skipping; GOMAXPROCS>1") case race.Enabled: t.Skip("skipping malloc count under race detector") } From 08725f9de28726b52c2e62a37cd378d10f10c110 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 13 Dec 2024 17:16:44 +0100 Subject: [PATCH 021/397] crypto/internal/cryptotest: skip TestAllocations on s390x TestXAESAllocations fails like #70448, and crypto/rand's fails in FIPS mode. We can't keep chasing these without even a LUCI builder. Updates #67307 Change-Id: I5d0edddf470180a321dec55cabfb018db62eb940 Reviewed-on: https://go-review.googlesource.com/c/go/+/636055 Auto-Submit: Filippo Valsorda Reviewed-by: Roland Shoemaker LUCI-TryBot-Result: Go LUCI Reviewed-by: Carlos Amedee --- src/crypto/internal/cryptotest/allocations.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/crypto/internal/cryptotest/allocations.go b/src/crypto/internal/cryptotest/allocations.go index 0194c2f89dc77e..70055af70b42ec 100644 --- a/src/crypto/internal/cryptotest/allocations.go +++ b/src/crypto/internal/cryptotest/allocations.go @@ -32,6 +32,12 @@ func SkipTestAllocations(t *testing.T) { t.Skip("skipping allocations test on plan9") } + // s390x deviates from other assembly implementations and is very hard to + // test due to the lack of LUCI builders. See #67307. + if runtime.GOARCH == "s390x" { + t.Skip("skipping allocations test on s390x") + } + // Some APIs rely on inliner and devirtualization to allocate on the stack. testenv.SkipIfOptimizationOff(t) } From c4f356dd863c449835248c24f6dc653323010a1c Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 13 Dec 2024 16:59:20 +0100 Subject: [PATCH 022/397] crypto/ecdsa: fix s390x assembly with P-521 I had incorrectly assumed that the blocksize was always the same as the curve field size. This is true of P-256 and P-384, but not P-521. Fixes #70660 Fixes #70771 Change-Id: Idb6b510fcd3dd42d9b1e6cf42c1bb92e0ce8bd07 Reviewed-on: https://go-review.googlesource.com/c/go/+/636015 Run-TryBot: Filippo Valsorda Reviewed-by: Carlos Amedee LUCI-TryBot-Result: Go LUCI Auto-Submit: Filippo Valsorda TryBot-Result: Gopher Robot Reviewed-by: Roland Shoemaker --- src/crypto/internal/fips140/ecdsa/ecdsa.go | 4 +- .../internal/fips140/ecdsa/ecdsa_s390x.go | 53 +++++++++++++++---- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/crypto/internal/fips140/ecdsa/ecdsa.go b/src/crypto/internal/fips140/ecdsa/ecdsa.go index 9459b03de76484..11389e8210bc68 100644 --- a/src/crypto/internal/fips140/ecdsa/ecdsa.go +++ b/src/crypto/internal/fips140/ecdsa/ecdsa.go @@ -21,7 +21,7 @@ import ( type PrivateKey struct { pub PublicKey - d []byte // bigmod.(*Nat).Bytes output (fixed length) + d []byte // bigmod.(*Nat).Bytes output (same length as the curve order) } func (priv *PrivateKey) Bytes() []byte { @@ -262,7 +262,7 @@ func randomPoint[P Point[P]](c *Curve[P], generate func([]byte) error) (k *bigmo var testingOnlyRejectionSamplingLooped func() // Signature is an ECDSA signature, where r and s are represented as big-endian -// fixed-length byte slices. +// byte slices of the same length as the curve order. type Signature struct { R, S []byte } diff --git a/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go b/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go index 01379f998f10e2..271a35897f8c8f 100644 --- a/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go +++ b/src/crypto/internal/fips140/ecdsa/ecdsa_s390x.go @@ -47,15 +47,34 @@ func canUseKDSA(c curveID) (functionCode uint64, blockSize int, ok bool) { case p384: return 2, 48, true case p521: + // Note that the block size doesn't match the field size for P-521. return 3, 80, true } return 0, 0, false // A mismatch } -func hashToBytes[P Point[P]](c *Curve[P], dst, hash []byte) { +func hashToBytes[P Point[P]](c *Curve[P], hash []byte) []byte { e := bigmod.NewNat() hashToNat(c, e, hash) - copy(dst, e.Bytes(c.N)) + return e.Bytes(c.N) +} + +func appendBlock(p []byte, blocksize int, b []byte) []byte { + if len(b) > blocksize { + panic("ecdsa: internal error: appendBlock input larger than block") + } + padding := blocksize - len(b) + p = append(p, make([]byte, padding)...) + return append(p, b...) +} + +func trimBlock(p []byte, size int) ([]byte, error) { + for _, b := range p[:len(p)-size] { + if b != 0 { + return nil, errors.New("ecdsa: internal error: KDSA produced invalid signature") + } + } + return p[len(p)-size:], nil } func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte) (*Signature, error) { @@ -95,17 +114,27 @@ func sign[P Point[P]](c *Curve[P], priv *PrivateKey, drbg *hmacDRBG, hash []byte // Copy content into the parameter block. In the sign case, // we copy hashed message, private key and random number into - // the parameter block. - hashToBytes(c, params[2*blockSize:3*blockSize], hash) - copy(params[3*blockSize+blockSize-len(priv.d):], priv.d) - copy(params[4*blockSize:5*blockSize], k.Bytes(c.N)) + // the parameter block. We skip the signature slots. + p := params[:2*blockSize] + p = appendBlock(p, blockSize, hashToBytes(c, hash)) + p = appendBlock(p, blockSize, priv.d) + p = appendBlock(p, blockSize, k.Bytes(c.N)) // Convert verify function code into a sign function code by adding 8. // We also need to set the 'deterministic' bit in the function code, by // adding 128, in order to stop the instruction using its own random number // generator in addition to the random number we supply. switch kdsa(functionCode+136, ¶ms) { case 0: // success - return &Signature{R: params[:blockSize], S: params[blockSize : 2*blockSize]}, nil + elementSize := (c.N.BitLen() + 7) / 8 + r, err := trimBlock(params[:blockSize], elementSize) + if err != nil { + return nil, err + } + s, err := trimBlock(params[blockSize:2*blockSize], elementSize) + if err != nil { + return nil, err + } + return &Signature{R: r, S: s}, nil case 1: // error return nil, errors.New("zero parameter") case 2: // retry @@ -149,10 +178,12 @@ func verify[P Point[P]](c *Curve[P], pub *PublicKey, hash []byte, sig *Signature // Copy content into the parameter block. In the verify case, // we copy signature (r), signature(s), hashed message, public key x component, // and public key y component into the parameter block. - copy(params[0*blockSize+blockSize-len(r):], r) - copy(params[1*blockSize+blockSize-len(s):], s) - hashToBytes(c, params[2*blockSize:3*blockSize], hash) - copy(params[3*blockSize:5*blockSize], pub.q[1:]) // strip 0x04 prefix + p := params[:0] + p = appendBlock(p, blockSize, r) + p = appendBlock(p, blockSize, s) + p = appendBlock(p, blockSize, hashToBytes(c, hash)) + p = appendBlock(p, blockSize, pub.q[1:1+len(pub.q)/2]) + p = appendBlock(p, blockSize, pub.q[1+len(pub.q)/2:]) if kdsa(functionCode, ¶ms) != 0 { return errors.New("invalid signature") } From 08770a5b944ba1cf4f62f075bfd94cd36a061bdb Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 13 Dec 2024 15:05:27 -0500 Subject: [PATCH 023/397] cmd/link: make dwarf name slice index self-describing cmd/compile/internal/dwarfgen.createComplexVar does it this way, which has the nice property of documenting the expected prefix. This is primarily for newtype, since defgotype checks for the prefix immediately prior, but I changed both for consistency. Change-Id: I49fa7c6166bdcbd19aaf91fe3dc20537080afcfc Reviewed-on: https://go-review.googlesource.com/c/go/+/635177 Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI Auto-Submit: Michael Pratt --- src/cmd/link/internal/ld/dwarf.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 14c0b687d853a3..b653e09a3c1b91 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -520,7 +520,7 @@ func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym { d.linkctxt.Errorf(gotype, "dwarf: type name doesn't start with \"type:\"") return d.mustFind(" ") } - name := sn[5:] // could also decode from Type.string + name := sn[len("type:"):] // could also decode from Type.string sdie := d.find(name) if sdie != 0 { @@ -534,7 +534,7 @@ func (d *dwctxt) defgotype(gotype loader.Sym) loader.Sym { func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie { sn := d.ldr.SymName(gotype) - name := sn[5:] // could also decode from Type.string + name := sn[len("type:"):] // could also decode from Type.string tdata := d.ldr.Data(gotype) if len(tdata) == 0 { d.linkctxt.Errorf(gotype, "missing type") From e39e965e0e0cce65ca977fd0da35f5bfb68dc2b8 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Fri, 13 Dec 2024 15:36:47 -0500 Subject: [PATCH 024/397] cmd/go: drop FailedBuild field if gotestjsonbuildtext=1 go test -json has two new effects in Go 1.24: it implies go build -json, and it adds a FailedBuild field in test events. For compatibility, CL 629335 added gotestjsonbuildtext=1, which disables the implicit go build -json, but that CL didn't affect the FailedBuild field. In principle this shouldn't matter because it's just another JSON field, but just so we don't have to worry about some intermediate behavior, this CL makes gotestjsonbuildtext=1 disable the FailedBuild field as well. Updates #62067 Updates #70402 Change-Id: I006d1ea0468980ee2564495324e8b4ed082898af Reviewed-on: https://go-review.googlesource.com/c/go/+/635899 Auto-Submit: Austin Clements Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov --- src/cmd/go/internal/test/test.go | 14 ++++++++++++-- src/cmd/go/testdata/script/test_json_build.txt | 5 +++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 41ddb2f5d01e77..b530d027dff4e0 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -1009,7 +1009,13 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { json.Exited(err) json.Close() }() - json.SetFailedBuild(perr.Desc()) + if gotestjsonbuildtext.Value() == "1" { + // While this flag is about go build -json, the other effect + // of that change was to include "FailedBuild" in the test JSON. + gotestjsonbuildtext.IncNonDefault() + } else { + json.SetFailedBuild(perr.Desc()) + } stdout = json } fmt.Fprintf(stdout, "FAIL\t%s [setup failed]\n", p.ImportPath) @@ -1437,7 +1443,11 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action) if a.Failed != nil { // We were unable to build the binary. if json != nil && a.Failed.Package != nil { - json.SetFailedBuild(a.Failed.Package.Desc()) + if gotestjsonbuildtext.Value() == "1" { + gotestjsonbuildtext.IncNonDefault() + } else { + json.SetFailedBuild(a.Failed.Package.Desc()) + } } a.Failed = nil fmt.Fprintf(stdout, "FAIL\t%s [build failed]\n", a.Package.ImportPath) diff --git a/src/cmd/go/testdata/script/test_json_build.txt b/src/cmd/go/testdata/script/test_json_build.txt index a3f0c37923faf5..0a40649dcce8df 100644 --- a/src/cmd/go/testdata/script/test_json_build.txt +++ b/src/cmd/go/testdata/script/test_json_build.txt @@ -58,8 +58,9 @@ stderr '# m/builderror \[m/builderror.test\]\n' stderr 'builderror'${/}'main_test.go:3:11: undefined: y\n' stdout '"Action":"start","Package":"m/builderror"' stdout '"Action":"output","Package":"m/builderror","Output":"FAIL\\tm/builderror \[build failed\]\\n"' -stdout '"Action":"fail","Package":"m/builderror","Elapsed":.*,"FailedBuild":"m/builderror \[m/builderror\.test\]"' - +stdout '"Action":"fail","Package":"m/builderror","Elapsed":[0-9.]+\}' +# FailedBuild should NOT appear in the output in this mode. +! stdout '"FailedBuild"' -- go.mod -- module m From 090748d6c7973e9bb8f5efe069135c8ea0f0d89c Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 12 Dec 2024 15:43:37 -0500 Subject: [PATCH 025/397] testing: improve B.Loop docs, use B.Loop in examples This updates the testing documentation to frame B.Loop as the canonical way to write benchmarks. We retain documentation on b.N benchmarks because people will definitely continue to see them (and write them), but it's demoted to clearly second class. This also attempts to clarify and refine the B.Loop documentation itself. Updates #61515 Fixes #70787 Change-Id: If5123435bfe3a5883a753119ecdf7bbc41afd499 Reviewed-on: https://go-review.googlesource.com/c/go/+/635895 Reviewed-by: Junyang Shao Reviewed-by: Caleb Spare LUCI-TryBot-Result: Go LUCI Auto-Submit: Austin Clements --- src/testing/benchmark.go | 54 +++++++++++++++++++++-------------- src/testing/benchmark_test.go | 4 +-- src/testing/testing.go | 46 +++++++++++++++++++++++------ 3 files changed, 71 insertions(+), 33 deletions(-) diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index 78e1b2de6d1247..8b84444f3824f0 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -78,7 +78,7 @@ type InternalBenchmark struct { } // B is a type passed to [Benchmark] functions to manage benchmark -// timing and to specify the number of iterations to run. +// timing and control the number of iterations. // // A benchmark ends when its Benchmark function returns or calls any of the methods // FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called @@ -133,8 +133,7 @@ func (b *B) StartTimer() { } // StopTimer stops timing a test. This can be used to pause the timer -// while performing complex initialization that you don't -// want to measure. +// while performing steps that you don't want to measure. func (b *B) StopTimer() { if b.timerOn { b.duration += highPrecisionTimeSince(b.start) @@ -387,7 +386,7 @@ func (b *B) loopSlowPath() bool { b.ResetTimer() return true } - // Handles fixed time case + // Handles fixed iterations case if b.benchTime.n > 0 { if b.N < b.benchTime.n { b.N = b.benchTime.n @@ -396,31 +395,42 @@ func (b *B) loopSlowPath() bool { } return false } - // Handles fixed iteration count case + // Handles fixed time case return b.stopOrScaleBLoop() } -// Loop returns true until b.N calls has been made to it. -// -// A benchmark should either use Loop or contain an explicit loop from 0 to b.N, but not both. -// After the benchmark finishes, b.N will contain the total number of calls to op, so the benchmark -// may use b.N to compute other average metrics. +// Loop returns true as long as the benchmark should continue running. // -// The parameters and results of function calls inside the body of "for b.Loop() {...}" are guaranteed -// not to be optimized away. -// Also, the local loop scaling for b.Loop ensures the benchmark function containing the loop will only -// be executed once, i.e. for such construct: +// A typical benchmark is structured like: // -// testing.Benchmark(func(b *testing.B) { -// ...(setup) -// for b.Loop() { -// ...(benchmark logic) -// } -// ...(clean-up) +// func Benchmark(b *testing.B) { +// ... setup ... +// for b.Loop() { +// ... code to measure ... +// } +// ... cleanup ... // } // -// The ...(setup) and ...(clean-up) logic will only be executed once. -// Also benchtime=Nx (N>1) will result in exactly N executions instead of N+1 for b.N style loops. +// Loop resets the benchmark timer the first time it is called in a benchmark, +// so any setup performed prior to starting the benchmark loop does not count +// toward the benchmark measurement. +// +// The compiler never optimizes away calls to functions within the body of a +// "for b.Loop() { ... }" loop. This prevents surprises that can otherwise occur +// if the compiler determines that the result of a benchmarked function is +// unused. The loop must be written in exactly this form, and this only applies +// to calls syntactically between the curly braces of the loop. Optimizations +// are performed as usual in any functions called by the loop. +// +// After Loop returns false, b.N contains the total number of iterations that +// ran, so the benchmark may use b.N to compute other average metrics. +// +// Prior to the introduction of Loop, benchmarks were expected to contain an +// explicit loop from 0 to b.N. Benchmarks should either use Loop or contain a +// loop to b.N, but not both. Loop offers more automatic management of the +// benchmark timer, and runs each benchmark function only once per measurement, +// whereas b.N-based benchmarks must run the benchmark function (and any +// associated setup and cleanup) several times. func (b *B) Loop() bool { if b.loopN != 0 && b.loopN < b.N { b.loopN++ diff --git a/src/testing/benchmark_test.go b/src/testing/benchmark_test.go index 259b70ed4c95e0..b3089b311991c2 100644 --- a/src/testing/benchmark_test.go +++ b/src/testing/benchmark_test.go @@ -155,7 +155,7 @@ func ExampleB_Loop() { } n := 0 testing.Benchmark(func(b *testing.B) { - // Unlike "for i := range N {...}" style loops, this + // Unlike "for i := range b.N {...}" style loops, this // setup logic will only be executed once, so simpleFunc // will always get argument 1. n++ @@ -219,7 +219,7 @@ func ExampleB_ReportMetric() { // specific algorithm (in this case, sorting). testing.Benchmark(func(b *testing.B) { var compares int64 - for i := 0; i < b.N; i++ { + for b.Loop() { s := []int{5, 4, 3, 2, 1} slices.SortFunc(s, func(a, b int) int { compares++ diff --git a/src/testing/testing.go b/src/testing/testing.go index e353ceb74119a3..8b4bdfbc39828e 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -72,27 +72,24 @@ // A sample benchmark function looks like this: // // func BenchmarkRandInt(b *testing.B) { -// for range b.N { +// for b.Loop() { // rand.Int() // } // } // -// The benchmark function must run the target code b.N times. -// It is called multiple times with b.N adjusted until the -// benchmark function lasts long enough to be timed reliably. // The output // // BenchmarkRandInt-8 68453040 17.8 ns/op // -// means that the loop ran 68453040 times at a speed of 17.8 ns per loop. +// means that the body of the loop ran 68453040 times at a speed of 17.8 ns per loop. // -// If a benchmark needs some expensive setup before running, the timer -// may be reset: +// Only the body of the loop is timed, so benchmarks may do expensive +// setup before calling b.Loop, which will not be counted toward the +// benchmark measurement: // // func BenchmarkBigLen(b *testing.B) { // big := NewBig() -// b.ResetTimer() -// for range b.N { +// for b.Loop() { // big.Len() // } // } @@ -120,6 +117,37 @@ // In particular, https://golang.org/x/perf/cmd/benchstat performs // statistically robust A/B comparisons. // +// # b.N-style benchmarks +// +// Prior to the introduction of [B.Loop], benchmarks were written in a +// different style using [B.N]. For example: +// +// func BenchmarkRandInt(b *testing.B) { +// for range b.N { +// rand.Int() +// } +// } +// +// In this style of benchmark, the benchmark function must run +// the target code b.N times. The benchmark function is called +// multiple times with b.N adjusted until the benchmark function +// lasts long enough to be timed reliably. This also means any setup +// done before the loop may be run several times. +// +// If a benchmark needs some expensive setup before running, the timer +// should be explicitly reset: +// +// func BenchmarkBigLen(b *testing.B) { +// big := NewBig() +// b.ResetTimer() +// for range b.N { +// big.Len() +// } +// } +// +// New benchmarks should prefer using [B.Loop], which is more robust +// and more efficient. +// // # Examples // // The package also runs and verifies example code. Example functions may From 6bd56fcaebde61eb6bd21906a7d7136d009be4a6 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 12 Dec 2024 18:19:43 -0500 Subject: [PATCH 026/397] testing: improve b.Loop example The current b.Loop example doesn't focus on the basic usage of b.Loop. Replace this with a new example that uses (slightly) more realistic things to demonstrate the most salient points of b.Loop. We also move the example into an example file so that we can write a real Benchmark function and a real function to be benchmarks, which makes this much closer to what a user would actually write. Updates #61515. Change-Id: I4d830b3bfe3eb3cd8cdecef469fea0541baebb43 Reviewed-on: https://go-review.googlesource.com/c/go/+/635896 Auto-Submit: Austin Clements Reviewed-by: Junyang Shao Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/testing/benchmark_test.go | 30 -------------------- src/testing/example_loop_test.go | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 30 deletions(-) create mode 100644 src/testing/example_loop_test.go diff --git a/src/testing/benchmark_test.go b/src/testing/benchmark_test.go index b3089b311991c2..239e7300211f5e 100644 --- a/src/testing/benchmark_test.go +++ b/src/testing/benchmark_test.go @@ -149,36 +149,6 @@ func TestBLoopHasResults(t *testing.T) { } } -func ExampleB_Loop() { - simpleFunc := func(i int) int { - return i + 1 - } - n := 0 - testing.Benchmark(func(b *testing.B) { - // Unlike "for i := range b.N {...}" style loops, this - // setup logic will only be executed once, so simpleFunc - // will always get argument 1. - n++ - // It behaves just like "for i := range N {...}", except with keeping - // function call parameters and results alive. - for b.Loop() { - // This function call, if was in a normal loop, will be optimized away - // completely, first by inlining, then by dead code elimination. - // In a b.Loop loop, the compiler ensures that this function is not optimized away. - simpleFunc(n) - } - // This clean-up will only be executed once, so after the benchmark, the user - // will see n == 2. - n++ - // Use b.ReportMetric as usual just like what a user may do after - // b.N loop. - }) - // We can expect n == 2 here. - - // The return value of the above Benchmark could be used just like - // a b.N loop benchmark as well. -} - func ExampleB_RunParallel() { // Parallel benchmark for text/template.Template.Execute on a single object. testing.Benchmark(func(b *testing.B) { diff --git a/src/testing/example_loop_test.go b/src/testing/example_loop_test.go new file mode 100644 index 00000000000000..eff8bab352058f --- /dev/null +++ b/src/testing/example_loop_test.go @@ -0,0 +1,48 @@ +// Copyright 2024 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 testing_test + +import ( + "math/rand/v2" + "testing" +) + +// ExBenchmark shows how to use b.Loop in a benchmark. +// +// (If this were a real benchmark, not an example, this would be named +// BenchmarkSomething.) +func ExBenchmark(b *testing.B) { + // Generate a large random slice to use as an input. + // Since this is done before the first call to b.Loop(), + // it doesn't count toward the benchmark time. + input := make([]int, 128<<10) + for i := range input { + input[i] = rand.Int() + } + + // Perform the benchmark. + for b.Loop() { + // Normally, the compiler would be allowed to optimize away the call + // to sum because it has no side effects and the result isn't used. + // However, inside a b.Loop loop, the compiler ensures function calls + // aren't optimized away. + sum(input) + } + + // Outside the loop, the timer is stopped, so we could perform + // cleanup if necessary without affecting the result. +} + +func sum(data []int) int { + total := 0 + for _, value := range data { + total += value + } + return total +} + +func ExampleB_Loop() { + testing.Benchmark(ExBenchmark) +} From c1f2542c8bef27872a95efd7904afeeee36fe976 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 12 Dec 2024 21:17:04 -0500 Subject: [PATCH 027/397] testing: improve B.Loop test This moves the B.Loop test from package testing_test to package testing, where it can check on more of the internals of the benchmark state. Updates #61515. Change-Id: Ia32d7104526125c5e8a1e35dab7660008afcbf80 Reviewed-on: https://go-review.googlesource.com/c/go/+/635897 Auto-Submit: Austin Clements LUCI-TryBot-Result: Go LUCI Reviewed-by: Junyang Shao --- src/testing/benchmark_test.go | 22 --------------- src/testing/loop_test.go | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 src/testing/loop_test.go diff --git a/src/testing/benchmark_test.go b/src/testing/benchmark_test.go index 239e7300211f5e..a195e4c5766813 100644 --- a/src/testing/benchmark_test.go +++ b/src/testing/benchmark_test.go @@ -127,28 +127,6 @@ func TestRunParallelSkipNow(t *testing.T) { }) } -func TestBLoopHasResults(t *testing.T) { - // Verify that b.N and the b.Loop() iteration count match. - var nIterated int - bRet := testing.Benchmark(func(b *testing.B) { - i := 0 - for b.Loop() { - i++ - } - nIterated = i - }) - if nIterated == 0 { - t.Fatalf("Iteration count zero") - } - if bRet.N != nIterated { - t.Fatalf("Benchmark result N incorrect, got %d want %d", bRet.N, nIterated) - } - // We only need to check duration to make sure benchmark result is written. - if bRet.T == 0 { - t.Fatalf("Benchmark result duration unset") - } -} - func ExampleB_RunParallel() { // Parallel benchmark for text/template.Template.Execute on a single object. testing.Benchmark(func(b *testing.B) { diff --git a/src/testing/loop_test.go b/src/testing/loop_test.go new file mode 100644 index 00000000000000..ae1a5e019b080d --- /dev/null +++ b/src/testing/loop_test.go @@ -0,0 +1,51 @@ +// Copyright 2024 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 testing + +func TestBenchmarkBLoop(t *T) { + var initialStart highPrecisionTime + var firstStart highPrecisionTime + var lastStart highPrecisionTime + runs := 0 + iters := 0 + finalBN := 0 + bRet := Benchmark(func(b *B) { + initialStart = b.start + runs++ + for b.Loop() { + if iters == 0 { + firstStart = b.start + } + lastStart = b.start + iters++ + } + finalBN = b.N + }) + // Verify that a b.Loop benchmark is invoked just once. + if runs != 1 { + t.Errorf("want runs == 1, got %d", runs) + } + // Verify that at least one iteration ran. + if iters == 0 { + t.Fatalf("no iterations ran") + } + // Verify that b.N, bRet.N, and the b.Loop() iteration count match. + if finalBN != iters || bRet.N != iters { + t.Errorf("benchmark iterations mismatch: %d loop iterations, final b.N=%d, bRet.N=%d", iters, finalBN, bRet.N) + } + // Make sure the benchmark ran for an appropriate amount of time. + if bRet.T < benchTime.d { + t.Fatalf("benchmark ran for %s, want >= %s", bRet.T, benchTime.d) + } + // Verify that the timer is reset on the first loop, and then left alone. + if firstStart == initialStart { + t.Errorf("b.Loop did not reset the timer") + } + if lastStart != firstStart { + t.Errorf("timer was reset during iteration") + } +} + +// See also TestBenchmarkBLoop* in other files. From 18b5435fc84225ca303da7a110c7e8065dc4bbda Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 12 Dec 2024 21:18:44 -0500 Subject: [PATCH 028/397] testing: don't measure cleanup time after B.Loop B.Loop resets the timer on the first iteration so that setup code isn't measured, but it currently leaves the timer running after the last iteration, meaning that cleanup code will still be measured. Fix this by stopping the timer when B.Loop returns false to indicate the end of the benchmark. Updates #61515 Change-Id: I0e0502cb2ce3c24cf872682b88d74e8be2c4529b Reviewed-on: https://go-review.googlesource.com/c/go/+/635898 Reviewed-by: Junyang Shao Auto-Submit: Austin Clements LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui --- src/testing/benchmark.go | 6 +++++- src/testing/loop_test.go | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index 8b84444f3824f0..2660c9bba06f3d 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -366,6 +366,8 @@ func (b *B) ReportMetric(n float64, unit string) { func (b *B) stopOrScaleBLoop() bool { timeElapsed := highPrecisionTimeSince(b.start) if timeElapsed >= b.benchTime.d { + // Stop the timer so we don't count cleanup time + b.StopTimer() return false } // Loop scaling @@ -393,6 +395,7 @@ func (b *B) loopSlowPath() bool { b.loopN++ return true } + b.StopTimer() return false } // Handles fixed time case @@ -413,7 +416,8 @@ func (b *B) loopSlowPath() bool { // // Loop resets the benchmark timer the first time it is called in a benchmark, // so any setup performed prior to starting the benchmark loop does not count -// toward the benchmark measurement. +// toward the benchmark measurement. Likewise, when it returns false, it stops +// the timer so cleanup code is not measured. // // The compiler never optimizes away calls to functions within the body of a // "for b.Loop() { ... }" loop. This prevents surprises that can otherwise occur diff --git a/src/testing/loop_test.go b/src/testing/loop_test.go index ae1a5e019b080d..7a1a93fceee7ea 100644 --- a/src/testing/loop_test.go +++ b/src/testing/loop_test.go @@ -8,6 +8,7 @@ func TestBenchmarkBLoop(t *T) { var initialStart highPrecisionTime var firstStart highPrecisionTime var lastStart highPrecisionTime + var runningEnd bool runs := 0 iters := 0 finalBN := 0 @@ -22,6 +23,7 @@ func TestBenchmarkBLoop(t *T) { iters++ } finalBN = b.N + runningEnd = b.timerOn }) // Verify that a b.Loop benchmark is invoked just once. if runs != 1 { @@ -46,6 +48,10 @@ func TestBenchmarkBLoop(t *T) { if lastStart != firstStart { t.Errorf("timer was reset during iteration") } + // Verify that it stopped the timer after the last loop. + if runningEnd { + t.Errorf("timer was still running after last iteration") + } } // See also TestBenchmarkBLoop* in other files. From 3bd08b97921826c1b0a5fbf0789f4b49d7619977 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 13 Dec 2024 23:18:59 +0000 Subject: [PATCH 029/397] runtime: usleep in TestWeakToStrongMarkTermination There's a subtle bug in this test (big surprise): time.Sleep allocates, so the time.Sleep(100*time.Millisecond) before unblocking gcMarkDone might itself end up in gcMarkDone. Work around this by using usleep here instead. Fixes #70532. Change-Id: I4c642ebb12f737cdb0d79ccff64b6059fc3d8b34 Reviewed-on: https://go-review.googlesource.com/c/go/+/636155 Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/runtime/gc_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go index 35cb634936a91e..00280ed1b53cab 100644 --- a/src/runtime/gc_test.go +++ b/src/runtime/gc_test.go @@ -834,7 +834,11 @@ func TestWeakToStrongMarkTermination(t *testing.T) { done <- struct{}{} }() go func() { - time.Sleep(100 * time.Millisecond) + // Usleep here instead of time.Sleep. time.Sleep + // can allocate, and if we get unlucky, then it + // can end up stuck in gcMarkDone with nothing to + // wake it. + runtime.Usleep(100000) // 100ms // Let mark termination continue. runtime.SetSpinInGCMarkDone(false) From d92c34a3870bace34724e69ec2516d59ae432d32 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 13 Dec 2024 17:33:16 -0500 Subject: [PATCH 030/397] cmd/go: don't create test actions for incomplete packages If a package is incomplete, don't create the actions for building and testing it. Instead report the errors for the package's dependencies and report a setup failed error (similar to what we'd to for a load error when producing the test packages). This produces similar errors to what were produced by load.CheckPackageErrors while still produing the test failure actions per package under test. (I wasn't sure what to do about the last test case in test_setup_error. I think it should be treated the same as other load errors?) Fixes #70820 Change-Id: Ie95e3c158c50ed35a1f27237ef3db40502719993 Reviewed-on: https://go-review.googlesource.com/c/go/+/635856 Reviewed-by: Sam Thanawalla LUCI-TryBot-Result: Go LUCI Auto-Submit: Michael Matloob Reviewed-by: Austin Clements --- src/cmd/go/internal/load/pkg.go | 21 ++++++++++--- src/cmd/go/internal/test/test.go | 22 ++++++++++++-- .../go/testdata/script/test_json_build.txt | 22 ++++++++++++++ .../go/testdata/script/test_setup_error.txt | 30 +++++++++++++++++-- 4 files changed, 86 insertions(+), 9 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index df790e1eaab616..15f6b2e87b916b 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -3068,7 +3068,15 @@ func setPGOProfilePath(pkgs []*Package) { // CheckPackageErrors prints errors encountered loading pkgs and their // dependencies, then exits with a non-zero status if any errors were found. func CheckPackageErrors(pkgs []*Package) { - var anyIncomplete bool + PackageErrors(pkgs, func(p *Package) { + DefaultPrinter().Errorf(p, "%v", p.Error) + }) + base.ExitIfErrors() +} + +// PackageErrors calls report for errors encountered loading pkgs and their dependencies. +func PackageErrors(pkgs []*Package, report func(*Package)) { + var anyIncomplete, anyErrors bool for _, pkg := range pkgs { if pkg.Incomplete { anyIncomplete = true @@ -3078,11 +3086,14 @@ func CheckPackageErrors(pkgs []*Package) { all := PackageList(pkgs) for _, p := range all { if p.Error != nil { - DefaultPrinter().Errorf(p, "%v", p.Error) + report(p) + anyErrors = true } } } - base.ExitIfErrors() + if anyErrors { + return + } // Check for duplicate loads of the same package. // That should be impossible, but if it does happen then @@ -3105,7 +3116,9 @@ func CheckPackageErrors(pkgs []*Package) { } seen[key] = true } - base.ExitIfErrors() + if len(reported) > 0 { + base.ExitIfErrors() + } } // mainPackagesOnly filters out non-main packages matched only by arguments diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index b530d027dff4e0..90f2d88d6b8a45 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -994,14 +994,15 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { // Prepare build + run + print actions for all packages being tested. for _, p := range pkgs { - buildTest, runTest, printTest, perr, err := builderTest(b, ctx, pkgOpts, p, allImports[p], writeCoverMetaAct) - if err != nil { + reportErr := func(perr *load.Package, err error) { str := err.Error() if p.ImportPath != "" { load.DefaultPrinter().Errorf(perr, "# %s\n%s", p.ImportPath, str) } else { load.DefaultPrinter().Errorf(perr, "%s", str) } + } + reportSetupFailed := func(perr *load.Package, err error) { var stdout io.Writer = os.Stdout if testJSON { json := test2json.NewConverter(stdout, p.ImportPath, test2json.Timestamp) @@ -1020,6 +1021,23 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { } fmt.Fprintf(stdout, "FAIL\t%s [setup failed]\n", p.ImportPath) base.SetExitStatus(1) + } + + var firstErrPkg *load.Package // arbitrarily report setup failed error for first error pkg reached in DFS + load.PackageErrors([]*load.Package{p}, func(p *load.Package) { + reportErr(p, p.Error) + if firstErrPkg == nil { + firstErrPkg = p + } + }) + if firstErrPkg != nil { + reportSetupFailed(firstErrPkg, firstErrPkg.Error) + continue + } + buildTest, runTest, printTest, perr, err := builderTest(b, ctx, pkgOpts, p, allImports[p], writeCoverMetaAct) + if err != nil { + reportErr(perr, err) + reportSetupFailed(perr, err) continue } builds = append(builds, buildTest) diff --git a/src/cmd/go/testdata/script/test_json_build.txt b/src/cmd/go/testdata/script/test_json_build.txt index 0a40649dcce8df..df8863ae03287f 100644 --- a/src/cmd/go/testdata/script/test_json_build.txt +++ b/src/cmd/go/testdata/script/test_json_build.txt @@ -40,6 +40,18 @@ stdout '"Action":"output","Package":"m/loaderror","Output":"FAIL\\tm/loaderror \ stdout '"Action":"fail","Package":"m/loaderror","Elapsed":.*,"FailedBuild":"x"' ! stderr '.' +# Test an import cycle loading error in a non test file. (#70820) +! go test -json -o=$devnull ./cycle/p +stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"# m/cycle/p\\n"' +stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"package m/cycle/p\\n"' +stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"\\timports m/cycle/q from p.go\\n"' +stdout '"ImportPath":"m/cycle/q","Action":"build-output","Output":"\\timports m/cycle/q from q.go: import cycle not allowed\\n"' +stdout '"ImportPath":"m/cycle/q","Action":"build-fail"' +stdout '"Action":"start","Package":"m/cycle/p"' +stdout '"Action":"output","Package":"m/cycle/p","Output":"FAIL\\tm/cycle/p \[setup failed\]\\n"' +stdout '"Action":"fail","Package":"m/cycle/p","Elapsed":.*,"FailedBuild":"m/cycle/q"' +! stderr '.' + # Test a vet error ! go test -json -o=$devnull ./veterror stdout '"ImportPath":"m/veterror \[m/veterror.test\]","Action":"build-output","Output":"# m/veterror\\n"' @@ -99,3 +111,13 @@ import ( func TestVetError(t *testing.T) { fmt.Printf("%s") } +-- cycle/p/p.go -- +package p + +import "m/cycle/q" +-- cycle/q/q.go -- +package q + +import ( + "m/cycle/q" +) diff --git a/src/cmd/go/testdata/script/test_setup_error.txt b/src/cmd/go/testdata/script/test_setup_error.txt index 2999067f2c93f3..bf566d4621f1a5 100644 --- a/src/cmd/go/testdata/script/test_setup_error.txt +++ b/src/cmd/go/testdata/script/test_setup_error.txt @@ -33,10 +33,23 @@ stderr '# m/t2/p\n.*package x is not in std' stdout 'FAIL m/t2/p \[setup failed\]' stdout 'ok m/t' -# Finally, this one is a build error, but produced by cmd/go directly +# Test that an import cycle error is reported. Test for #70820 +! go test -o=$devnull ./cycle/p ./t +stderr '# m/cycle/p\n.*package m/cycle/p\n\timports m/cycle/p from p\.go: import cycle not allowed' +stdout 'FAIL m/cycle/p \[setup failed\]' +stdout 'ok m/t' + +# Test that multiple errors for the same package under test are reported. +! go test -o=$devnull ./cycle/q ./t +stderr '# m/cycle/q\n.*package m/cycle/q\n\timports m/cycle/p from q\.go\n\timports m/cycle/p from p\.go: import cycle not allowed' +stdout 'FAIL m/cycle/q \[setup failed\]' +stdout 'ok m/t' + +# Finally, this one is a non-import-cycle load error that +# is produced for the package under test. ! go test -o=$devnull . ./t -stderr '^\.: no Go files in '$PWD'$' -stdout 'FAIL . \[build failed\]' +stderr '# \.\n.*no Go files in '$PWD'$' +stdout 'FAIL . \[setup failed\]' stdout 'ok m/t' -- go.mod -- @@ -68,6 +81,17 @@ package p package p import "m/bad" +-- cycle/p/p.go -- +package p + +import "m/cycle/p" +-- cycle/q/q.go -- +package q + +import ( + "m/bad" + "m/cycle/p" +) -- bad/bad.go -- package bad From 1218566fe5c90e2bd39693566453828e6fbb4c12 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 16 Dec 2024 17:06:35 -0500 Subject: [PATCH 031/397] cmd/link: update runtime dependency list There have been a number of internal packages that the runtime package depends on. Update the list. We should stop using a hard- coded list. Change-Id: I6f9338d6690d955b8200f3301addd0e133a1bfe2 Reviewed-on: https://go-review.googlesource.com/c/go/+/636478 LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Pratt --- src/cmd/link/internal/ld/data.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index b6eaf69ca48a95..5c4497cdd75b0f 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -55,17 +55,31 @@ import ( ) // isRuntimeDepPkg reports whether pkg is the runtime package or its dependency. +// TODO: just compute from the runtime package, and remove this hardcoded list. func isRuntimeDepPkg(pkg string) bool { switch pkg { case "runtime", - "sync/atomic", // runtime may call to sync/atomic, due to go:linkname - "internal/abi", // used by reflectcall (and maybe more) - "internal/bytealg", // for IndexByte + "sync/atomic", // runtime may call to sync/atomic, due to go:linkname // TODO: this is not true? + "internal/abi", // used by reflectcall (and maybe more) + "internal/asan", + "internal/bytealg", // for IndexByte + "internal/byteorder", "internal/chacha8rand", // for rand - "internal/cpu": // for cpu features + "internal/coverage/rtcov", + "internal/cpu", // for cpu features + "internal/goarch", + "internal/godebugs", + "internal/goexperiment", + "internal/goos", + "internal/msan", + "internal/profilerecord", + "internal/race", + "internal/stringslite", + "unsafe": return true } - return strings.HasPrefix(pkg, "runtime/internal/") && !strings.HasSuffix(pkg, "_test") + return (strings.HasPrefix(pkg, "runtime/internal/") || strings.HasPrefix(pkg, "internal/runtime/")) && + !strings.HasSuffix(pkg, "_test") } // Estimate the max size needed to hold any new trampolines created for this function. This From 75736cc169631dfaaa48ad46a00e1bf31d830ec8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 16 Dec 2024 15:38:43 -0800 Subject: [PATCH 032/397] fmt, strconv: document that exponent is always two digits Except for %b where it is only one. Fixes #70862 Change-Id: Ic423a799b73bfa534f4083f6544bb9cd639fef06 Reviewed-on: https://go-review.googlesource.com/c/go/+/636915 LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Rob Pike Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- src/fmt/doc.go | 3 +++ src/strconv/ftoa.go | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/fmt/doc.go b/src/fmt/doc.go index b90db7bedc684b..fa0ffa7f00ccc7 100644 --- a/src/fmt/doc.go +++ b/src/fmt/doc.go @@ -50,6 +50,9 @@ Floating-point and complex constituents: %x hexadecimal notation (with decimal power of two exponent), e.g. -0x1.23abcp+20 %X upper-case hexadecimal notation, e.g. -0X1.23ABCP+20 + The exponent is always a decimal integer. + For formats other than %b the exponent is at least two digits. + String and slice of bytes (treated equivalently with these verbs): %s the uninterpreted bytes of the string or slice diff --git a/src/strconv/ftoa.go b/src/strconv/ftoa.go index 6db0d47e0f7ae2..bfe26366e12c13 100644 --- a/src/strconv/ftoa.go +++ b/src/strconv/ftoa.go @@ -44,6 +44,8 @@ var float64info = floatInfo{52, 11, -1023} // zeros are removed). // The special precision -1 uses the smallest number of digits // necessary such that ParseFloat will return f exactly. +// The exponent is written as a decimal integer; +// for all formats other than 'b', it will be at least two digits. func FormatFloat(f float64, fmt byte, prec, bitSize int) string { return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize)) } From 427a2401af088716bf5b394156e45fb4de54dc5a Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 13 Dec 2024 17:33:16 -0500 Subject: [PATCH 033/397] cmd/go/testdata/script: update test_flags for new test output With CL 635856, an error for a package missing go files is now caught at load time rather than at build time, so it's reported differently. Update the test to check for the correct output unbreak the builders. For #70820 Change-Id: I91fcac17961635b9a92782caa58c9a6f057a7e02 Reviewed-on: https://go-review.googlesource.com/c/go/+/637115 Reviewed-by: Sam Thanawalla Auto-Submit: Michael Matloob LUCI-TryBot-Result: Go LUCI --- src/cmd/go/testdata/script/test_flags.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/testdata/script/test_flags.txt b/src/cmd/go/testdata/script/test_flags.txt index 7adf4e273c569a..afef08840df87a 100644 --- a/src/cmd/go/testdata/script/test_flags.txt +++ b/src/cmd/go/testdata/script/test_flags.txt @@ -15,8 +15,8 @@ stdout '\Aok\s+example.com/x\s+[0-9.s]+\n\z' # Even though ./x looks like a package path, the real package should be # the implicit '.'. ! go test --answer=42 ./x -stdout '^FAIL\t. \[build failed\]' -stderr '^\.: no Go files in '$PWD'$' +stdout '^FAIL\t. \[setup failed\]' +stderr '^# \.\nno Go files in '$PWD'$' # However, *flags* that appear after unrecognized flags should still be # interpreted as flags, under the (possibly-erroneous) assumption that From dd7a7ba38f36dd6abc1e14b8d0e8bf05a5383161 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 16 Dec 2024 19:24:20 +0100 Subject: [PATCH 034/397] crypto/internal/fips140/aes: mark AES-ECB as not approved NIST SP 800-131Ar3 ipd, scheduled for publication in 2025Q1, marks AES-ECB as disallowed for encryption, and legacy use for decryption. There are apparently no details on how the transition is going to work, so to avoid surprises we just mark direct use of the Block as non-approved. We need to use Encrypt from higher level modes without tripping the service indicator. Within the aes package, we just use the internal function. For the gcm package we could do something more clever, but this deep into the freeze, just make an exported function that we commit to use nowhere else. I could not figure out a decent way to block ECB on GODEBUG=fips140=only. For #69536 Change-Id: I972a4b5da8efd0a0ab68d7dd509bec73aa2d6b68 Reviewed-on: https://go-review.googlesource.com/c/go/+/636775 Reviewed-by: David Chase Reviewed-by: Roland Shoemaker Auto-Submit: Filippo Valsorda LUCI-TryBot-Result: Go LUCI --- src/crypto/internal/fips140/aes/aes.go | 13 +++++++++++-- src/crypto/internal/fips140/aes/cbc.go | 4 ++-- src/crypto/internal/fips140/aes/ctr.go | 2 +- src/crypto/internal/fips140/aes/gcm/cmac.go | 8 ++++---- src/crypto/internal/fips140/aes/gcm/gcm_asm.go | 4 ++-- src/crypto/internal/fips140/aes/gcm/gcm_generic.go | 8 ++++---- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/crypto/internal/fips140/aes/aes.go b/src/crypto/internal/fips140/aes/aes.go index 739f1a3dbe6599..62f6919eda8178 100644 --- a/src/crypto/internal/fips140/aes/aes.go +++ b/src/crypto/internal/fips140/aes/aes.go @@ -94,6 +94,8 @@ func newBlockExpanded(c *blockExpanded, key []byte) { func (c *Block) BlockSize() int { return BlockSize } func (c *Block) Encrypt(dst, src []byte) { + // AES-ECB is not approved in FIPS 140-3 mode. + fips140.RecordNonApproved() if len(src) < BlockSize { panic("crypto/aes: input not full block") } @@ -103,11 +105,12 @@ func (c *Block) Encrypt(dst, src []byte) { if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { panic("crypto/aes: invalid buffer overlap") } - fips140.RecordApproved() encryptBlock(c, dst, src) } func (c *Block) Decrypt(dst, src []byte) { + // AES-ECB is not approved in FIPS 140-3 mode. + fips140.RecordNonApproved() if len(src) < BlockSize { panic("crypto/aes: input not full block") } @@ -117,6 +120,12 @@ func (c *Block) Decrypt(dst, src []byte) { if alias.InexactOverlap(dst[:BlockSize], src[:BlockSize]) { panic("crypto/aes: invalid buffer overlap") } - fips140.RecordApproved() decryptBlock(c, dst, src) } + +// EncryptBlockInternal applies the AES encryption function to one block. +// +// It is an internal function meant only for the gcm package. +func EncryptBlockInternal(c *Block, dst, src []byte) { + encryptBlock(c, dst, src) +} diff --git a/src/crypto/internal/fips140/aes/cbc.go b/src/crypto/internal/fips140/aes/cbc.go index c7837b9d87d102..f92af23a2a5561 100644 --- a/src/crypto/internal/fips140/aes/cbc.go +++ b/src/crypto/internal/fips140/aes/cbc.go @@ -50,7 +50,7 @@ func cryptBlocksEncGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { for len(src) > 0 { // Write the xor to dst, then encrypt in place. subtle.XORBytes(dst[:BlockSize], src[:BlockSize], iv) - b.Encrypt(dst[:BlockSize], dst[:BlockSize]) + encryptBlock(b, dst[:BlockSize], dst[:BlockSize]) // Move to the next block with this block as the next iv. iv = dst[:BlockSize] @@ -111,7 +111,7 @@ func cryptBlocksDecGeneric(b *Block, civ *[BlockSize]byte, dst, src []byte) { copy(civ[:], src[start:end]) for start >= 0 { - b.Decrypt(dst[start:end], src[start:end]) + decryptBlock(b, dst[start:end], src[start:end]) if start > 0 { subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start]) diff --git a/src/crypto/internal/fips140/aes/ctr.go b/src/crypto/internal/fips140/aes/ctr.go index f612034d85ff1a..2b0ee44cddb66c 100644 --- a/src/crypto/internal/fips140/aes/ctr.go +++ b/src/crypto/internal/fips140/aes/ctr.go @@ -132,7 +132,7 @@ func ctrBlocks(b *Block, dst, src []byte, ivlo, ivhi uint64) { byteorder.BEPutUint64(buf[i:], ivhi) byteorder.BEPutUint64(buf[i+8:], ivlo) ivlo, ivhi = add128(ivlo, ivhi, 1) - b.Encrypt(buf[i:], buf[i:]) + encryptBlock(b, buf[i:], buf[i:]) } // XOR into buf first, in case src and dst overlap (see above). subtle.XORBytes(buf, src, buf) diff --git a/src/crypto/internal/fips140/aes/gcm/cmac.go b/src/crypto/internal/fips140/aes/gcm/cmac.go index e0a9dc43dede7e..3a979a5c70870f 100644 --- a/src/crypto/internal/fips140/aes/gcm/cmac.go +++ b/src/crypto/internal/fips140/aes/gcm/cmac.go @@ -28,7 +28,7 @@ func NewCMAC(b *aes.Block) *CMAC { } func (c *CMAC) deriveSubkeys() { - c.b.Encrypt(c.k1[:], c.k1[:]) + aes.EncryptBlockInternal(&c.b, c.k1[:], c.k1[:]) msb := shiftLeft(&c.k1) c.k1[len(c.k1)-1] ^= msb * 0b10000111 @@ -45,7 +45,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { // Special-cased as a single empty partial final block. x = c.k2 x[len(m)] ^= 0b10000000 - c.b.Encrypt(x[:], x[:]) + aes.EncryptBlockInternal(&c.b, x[:], x[:]) return x } for len(m) >= aes.BlockSize { @@ -54,7 +54,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { // Final complete block. subtle.XORBytes(x[:], c.k1[:], x[:]) } - c.b.Encrypt(x[:], x[:]) + aes.EncryptBlockInternal(&c.b, x[:], x[:]) m = m[aes.BlockSize:] } if len(m) > 0 { @@ -62,7 +62,7 @@ func (c *CMAC) MAC(m []byte) [aes.BlockSize]byte { subtle.XORBytes(x[:], m, x[:]) subtle.XORBytes(x[:], c.k2[:], x[:]) x[len(m)] ^= 0b10000000 - c.b.Encrypt(x[:], x[:]) + aes.EncryptBlockInternal(&c.b, x[:], x[:]) } return x } diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_asm.go b/src/crypto/internal/fips140/aes/gcm/gcm_asm.go index d513f77a2f342b..7924e457dee829 100644 --- a/src/crypto/internal/fips140/aes/gcm/gcm_asm.go +++ b/src/crypto/internal/fips140/aes/gcm/gcm_asm.go @@ -81,7 +81,7 @@ func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) } - g.cipher.Encrypt(tagMask[:], counter[:]) + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) var tagOut [gcmTagSize]byte gcmAesData(&g.productTable, data, &tagOut) @@ -114,7 +114,7 @@ func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { gcmAesFinish(&g.productTable, &tagMask, &counter, uint64(len(nonce)), uint64(0)) } - g.cipher.Encrypt(tagMask[:], counter[:]) + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) var expectedTag [gcmTagSize]byte gcmAesData(&g.productTable, data, &expectedTag) diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_generic.go b/src/crypto/internal/fips140/aes/gcm/gcm_generic.go index 778392661dae6e..385955ed77838b 100644 --- a/src/crypto/internal/fips140/aes/gcm/gcm_generic.go +++ b/src/crypto/internal/fips140/aes/gcm/gcm_generic.go @@ -12,7 +12,7 @@ import ( func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { var H, counter, tagMask [gcmBlockSize]byte - g.cipher.Encrypt(H[:], H[:]) + aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) deriveCounterGeneric(&H, &counter, nonce) gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) @@ -25,7 +25,7 @@ func sealGeneric(out []byte, g *GCM, nonce, plaintext, additionalData []byte) { func openGeneric(out []byte, g *GCM, nonce, ciphertext, additionalData []byte) error { var H, counter, tagMask [gcmBlockSize]byte - g.cipher.Encrypt(H[:], H[:]) + aes.EncryptBlockInternal(&g.cipher, H[:], H[:]) deriveCounterGeneric(&H, &counter, nonce) gcmCounterCryptGeneric(&g.cipher, tagMask[:], tagMask[:], &counter) @@ -70,7 +70,7 @@ func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSiz var mask [gcmBlockSize]byte for len(src) >= gcmBlockSize { - b.Encrypt(mask[:], counter[:]) + aes.EncryptBlockInternal(b, mask[:], counter[:]) gcmInc32(counter) subtle.XORBytes(out, src, mask[:]) @@ -79,7 +79,7 @@ func gcmCounterCryptGeneric(b *aes.Block, out, src []byte, counter *[gcmBlockSiz } if len(src) > 0 { - b.Encrypt(mask[:], counter[:]) + aes.EncryptBlockInternal(b, mask[:], counter[:]) gcmInc32(counter) subtle.XORBytes(out, src, mask[:]) } From b47ce8b0e997f09abd6e1e5c23eb59d6e9d5be2c Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 16 Dec 2024 19:30:58 +0100 Subject: [PATCH 035/397] crypto/cipher: block non-AES CTR and CBC in fips140=only mode Somehow I had missed these. For #69536 Change-Id: I5e60b6f052bbfb707742ad15f663517c6c5f68d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/636795 Auto-Submit: Filippo Valsorda Reviewed-by: Roland Shoemaker LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase --- src/crypto/cipher/cbc.go | 7 +++++++ src/crypto/cipher/ctr.go | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/crypto/cipher/cbc.go b/src/crypto/cipher/cbc.go index b4536aceb9c224..8e614062969954 100644 --- a/src/crypto/cipher/cbc.go +++ b/src/crypto/cipher/cbc.go @@ -15,6 +15,7 @@ import ( "bytes" "crypto/internal/fips140/aes" "crypto/internal/fips140/alias" + "crypto/internal/fips140only" "crypto/subtle" ) @@ -53,6 +54,9 @@ func NewCBCEncrypter(b Block, iv []byte) BlockMode { if b, ok := b.(*aes.Block); ok { return aes.NewCBCEncrypter(b, [16]byte(iv)) } + if fips140only.Enabled { + panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") + } if cbc, ok := b.(cbcEncAble); ok { return cbc.NewCBCEncrypter(iv) } @@ -129,6 +133,9 @@ func NewCBCDecrypter(b Block, iv []byte) BlockMode { if b, ok := b.(*aes.Block); ok { return aes.NewCBCDecrypter(b, [16]byte(iv)) } + if fips140only.Enabled { + panic("crypto/cipher: use of CBC with non-AES ciphers is not allowed in FIPS 140-only mode") + } if cbc, ok := b.(cbcDecAble); ok { return cbc.NewCBCDecrypter(iv) } diff --git a/src/crypto/cipher/ctr.go b/src/crypto/cipher/ctr.go index c868635b8a7a86..49512ca5dd8b8e 100644 --- a/src/crypto/cipher/ctr.go +++ b/src/crypto/cipher/ctr.go @@ -16,6 +16,7 @@ import ( "bytes" "crypto/internal/fips140/aes" "crypto/internal/fips140/alias" + "crypto/internal/fips140only" "crypto/subtle" ) @@ -41,6 +42,9 @@ func NewCTR(block Block, iv []byte) Stream { if block, ok := block.(*aes.Block); ok { return aesCtrWrapper{aes.NewCTR(block, iv)} } + if fips140only.Enabled { + panic("crypto/cipher: use of CTR with non-AES ciphers is not allowed in FIPS 140-only mode") + } if ctr, ok := block.(ctrAble); ok { return ctr.NewCTR(iv) } From 31e50af5f3366a9fc4e91a589f91ad579b7cba56 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 16 Dec 2024 17:33:50 +0100 Subject: [PATCH 036/397] crypto/rsa: revert minimum GenerateKey size to 32 bits No point in causing breakage even with GODEBUG=rsa1024min=0. Change-Id: I923254a8c8afaca77be551b19e3555c44ebdbb67 Reviewed-on: https://go-review.googlesource.com/c/go/+/636557 Reviewed-by: Roland Shoemaker Reviewed-by: David Chase Auto-Submit: Filippo Valsorda LUCI-TryBot-Result: Go LUCI Reviewed-by: Daniel McCarney --- src/crypto/internal/fips140/rsa/keygen.go | 8 ++++---- src/crypto/rsa/rsa_test.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/crypto/internal/fips140/rsa/keygen.go b/src/crypto/internal/fips140/rsa/keygen.go index df76772ef5878d..d8a282bcd44634 100644 --- a/src/crypto/internal/fips140/rsa/keygen.go +++ b/src/crypto/internal/fips140/rsa/keygen.go @@ -13,9 +13,9 @@ import ( ) // GenerateKey generates a new RSA key pair of the given bit size. -// bits must be at least 128. +// bits must be at least 32. func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { - if bits < 128 { + if bits < 32 { return nil, errors.New("rsa: key too small") } fips140.RecordApproved() @@ -93,8 +93,8 @@ func GenerateKey(rand io.Reader, bits int) (*PrivateKey, error) { // randomPrime returns a random prime number of the given bit size following // the process in FIPS 186-5, Appendix A.1.3. func randomPrime(rand io.Reader, bits int) ([]byte, error) { - if bits < 64 { - return nil, errors.New("rsa: prime size must be at least 32-bit") + if bits < 16 { + return nil, errors.New("rsa: prime size must be at least 16 bits") } b := make([]byte, (bits+7)/8) diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go index 2474ab82dfa207..2535661040273a 100644 --- a/src/crypto/rsa/rsa_test.go +++ b/src/crypto/rsa/rsa_test.go @@ -101,7 +101,7 @@ func TestImpossibleKeyGeneration(t *testing.T) { // This test ensures that trying to generate or validate toy RSA keys // doesn't enter an infinite loop or panic. t.Setenv("GODEBUG", "rsa1024min=0") - for i := 0; i < 128; i++ { + for i := 0; i < 32; i++ { GenerateKey(rand.Reader, i) GenerateMultiPrimeKey(rand.Reader, 3, i) GenerateMultiPrimeKey(rand.Reader, 4, i) @@ -184,7 +184,7 @@ func TestEverything(t *testing.T) { } t.Setenv("GODEBUG", "rsa1024min=0") - min := 128 + min := 32 max := 560 // any smaller than this and not all tests will run if *allFlag { max = 2048 From 0cd833d19823f84a1da7552c63d1be5b7dba332a Mon Sep 17 00:00:00 2001 From: qmuntal Date: Mon, 16 Dec 2024 11:07:02 +0100 Subject: [PATCH 037/397] go/build: remove nonexistent package from TestDependencies crypto/internal/boring/fips140tls is not a package in the Go standard library, so it should not be listed in TestDependencies. Change-Id: I6476da397b0204fcbd0a11b27a29112fca4b6023 Reviewed-on: https://go-review.googlesource.com/c/go/+/636415 Reviewed-by: Filippo Valsorda Auto-Submit: Quim Muntal Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov --- src/go/build/deps_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index cc7f4df7f388ea..15e2f1bbbf3ad3 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -498,7 +498,7 @@ var depsRules = ` FIPS, internal/godebug, hash < crypto/fips140, crypto/internal/fips140only; NONE < crypto/internal/boring/sig, crypto/internal/boring/syso; - sync/atomic < crypto/internal/boring/bcache, crypto/internal/boring/fips140tls; + sync/atomic < crypto/internal/boring/bcache; crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; # CRYPTO is core crypto algorithms - no cgo, fmt, net. From 9f806bb76c8eec08cad07a2e859c8dd35103432e Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 16 Dec 2024 15:52:47 +0100 Subject: [PATCH 038/397] go/build: streamline the crypto package graph in TestDependencies Change-Id: I975243b4897d5161b839f142afbd2a46bfa1fab0 Reviewed-on: https://go-review.googlesource.com/c/go/+/636555 Reviewed-by: Daniel McCarney Auto-Submit: Filippo Valsorda Reviewed-by: David Chase TryBot-Bypass: Filippo Valsorda Reviewed-by: Roland Shoemaker --- src/go/build/deps_test.go | 89 +++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 15e2f1bbbf3ad3..d9d985dca4ade4 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -444,6 +444,10 @@ var depsRules = ` NET, log < net/mail; + # FIPS is the FIPS 140 module. + # It must not depend on external crypto packages. + # See also fips140deps.AllowedInternalPackages. + io, math/rand/v2 < crypto/internal/randutil; STR < crypto/internal/impl; @@ -455,8 +459,6 @@ var depsRules = ` internal/cpu, internal/goarch < crypto/internal/fips140deps/cpu; internal/godebug < crypto/internal/fips140deps/godebug; - # FIPS is the FIPS 140 module. - # It must not depend on external crypto packages. STR, crypto/internal/impl, crypto/internal/entropy, crypto/internal/randutil, @@ -491,63 +493,49 @@ var depsRules = ` < crypto/internal/fips140/rsa < FIPS; - FIPS < crypto/internal/fips140/check/checktest; + FIPS, internal/godebug < crypto/fips140; - FIPS, sync/atomic < crypto/tls/internal/fips140tls; + crypto, hash !< FIPS; - FIPS, internal/godebug, hash < crypto/fips140, crypto/internal/fips140only; + # CRYPTO is core crypto algorithms - no cgo, fmt, net. + # Mostly wrappers around the FIPS module. NONE < crypto/internal/boring/sig, crypto/internal/boring/syso; sync/atomic < crypto/internal/boring/bcache; - crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; - # CRYPTO is core crypto algorithms - no cgo, fmt, net. - FIPS, crypto/internal/fips140only, + FIPS, internal/godebug, hash, embed, crypto/internal/boring/sig, crypto/internal/boring/syso, - golang.org/x/sys/cpu, - hash, embed + crypto/internal/boring/bcache + < crypto/internal/fips140only < crypto < crypto/subtle < crypto/cipher - < crypto/sha3; - - crypto/cipher, - crypto/internal/boring/bcache < crypto/internal/boring - < crypto/boring; - - crypto/boring - < crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4, - crypto/sha1, crypto/sha256, crypto/sha512, crypto/hkdf; - - crypto/boring, crypto/internal/fips140/edwards25519/field - < crypto/ecdh; - - crypto/hmac < crypto/pbkdf2; - - crypto/internal/fips140/mlkem < crypto/mlkem; - - crypto/aes, - crypto/des, - crypto/ecdh, - crypto/hmac, - crypto/md5, - crypto/rc4, - crypto/sha1, - crypto/sha256, - crypto/sha512, - crypto/sha3, - crypto/hkdf + < crypto/boring + < crypto/aes, + crypto/des, + crypto/rc4, + crypto/md5, + crypto/sha1, + crypto/sha256, + crypto/sha512, + crypto/sha3, + crypto/hmac, + crypto/hkdf, + crypto/pbkdf2, + crypto/ecdh, + crypto/mlkem < CRYPTO; CGO, fmt, net !< CRYPTO; - # CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok. + # CRYPTO-MATH is crypto that exposes math/big APIs - no cgo, net; fmt now ok. + CRYPTO, FMT, math/big < crypto/internal/boring/bbig < crypto/rand - < crypto/ed25519 + < crypto/ed25519 # depends on crypto/rand.Reader < encoding/asn1 < golang.org/x/crypto/cryptobyte/asn1 < golang.org/x/crypto/cryptobyte @@ -558,17 +546,23 @@ var depsRules = ` CGO, net !< CRYPTO-MATH; # TLS, Prince of Dependencies. - CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem + + FIPS, sync/atomic < crypto/tls/internal/fips140tls; + + crypto/internal/boring/sig, crypto/tls/internal/fips140tls < crypto/tls/fipsonly; + + CRYPTO, golang.org/x/sys/cpu, encoding/binary, reflect < golang.org/x/crypto/internal/alias < golang.org/x/crypto/internal/subtle < golang.org/x/crypto/chacha20 < golang.org/x/crypto/internal/poly1305 - < golang.org/x/crypto/chacha20poly1305 + < golang.org/x/crypto/chacha20poly1305; + + CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem, + golang.org/x/crypto/chacha20poly1305, crypto/tls/internal/fips140tls < crypto/internal/hpke < crypto/x509/internal/macos - < crypto/x509/pkix; - - crypto/tls/internal/fips140tls, crypto/x509/pkix + < crypto/x509/pkix < crypto/x509 < crypto/tls; @@ -666,7 +660,7 @@ var depsRules = ` < testing/slogtest; FMT, crypto/sha256, encoding/json, go/ast, go/parser, go/token, - internal/godebug, math/rand, encoding/hex, crypto/sha256 + internal/godebug, math/rand, encoding/hex < internal/fuzz; OS, flag, testing, internal/cfg, internal/platform, internal/goroot @@ -696,6 +690,9 @@ var depsRules = ` CGO, FMT < crypto/internal/sysrand/internal/seccomp; + FIPS + < crypto/internal/fips140/check/checktest; + # v2 execution trace parser. FMT < internal/trace/event; From 236a0b4ffb79854546b9f437499092cec23a5725 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 12 Dec 2024 11:31:49 -0800 Subject: [PATCH 039/397] spec: explain function invocation and passing of parameters more precisely - Describe that function invocation allocates space for a functions' variables. - Explain parameter passing in terms of assignments. Change-Id: Ia693d73a570f7d1aa2ac05e6095b4e602e4e9bf2 Reviewed-on: https://go-review.googlesource.com/c/go/+/635800 Reviewed-by: Robert Griesemer Reviewed-by: Ian Lance Taylor TryBot-Bypass: Robert Griesemer Auto-Submit: Robert Griesemer Reviewed-by: Rob Pike --- doc/go_spec.html | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index 282f6cde0c80b3..fff489c33ac55c 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -2819,7 +2819,7 @@ Satisfying a type constraint
A type argument
T
satisfies a type constraintC
-ifT
is an element of the type set defined byC
; i.e., +ifT
is an element of the type set defined byC
; in other words, ifT
implementsC
. As an exception, a strictly comparable type constraint may also be satisfied by a comparable @@ -4229,8 +4229,7 @@Calls
Except for one special case, arguments must be single-valued expressions assignable to the parameter types ofF
and are evaluated before the function is called. -The type of the expression is the result type -ofF
. +The type of the expression is the result type ofF
. A method invocation is similar but the method itself is specified as a selector upon a value of the receiver type for the method. @@ -4251,9 +4250,14 @@Calls
In a function call, the function value and arguments are evaluated in the usual order. -After they are evaluated, the parameters of the call are passed by value to the function +After they are evaluated, new storage is allocated for the function's +variables, which includes its parameters +and results. +Then, the arguments of the call are passed to the function, +which means that they are assigned +to their corresponding function parameters, and the called function begins execution. -The return parameters of the function are passed by value +The return parameters of the function are passed back to the caller when the function returns.
@@ -4267,9 +4271,9 @@Calls
g
are equal in number and individually assignable to the parameters of another function or methodf
, then the callf(g(parameters_of_g))
-will invokef
after binding the return values of -g
to the parameters off
in order. The call -off
must contain no parameters other than the call ofg
, +will invokef
after passing the return values of +g
to the parameters off
in order. +The call off
must contain no parameters other than the call ofg
, andg
must have at least one return value. Iff
has a final...
parameter, it is assigned the return values ofg
that remain after @@ -4315,7 +4319,7 @@Passing arguments to
...p
of type...T
, then withinf
the type ofp
is equivalent to type[]T
. Iff
is invoked with no actual arguments forp
, -the value passed top
isnil
. +the value passed top
isnil
. Otherwise, the value passed is a new slice of type[]T
with a new underlying array whose successive elements are the actual arguments, which all must be assignable From 4ac8f552e95521d292cc18ccc546739d41283b31 Mon Sep 17 00:00:00 2001 From: Damien NeilDate: Tue, 3 Dec 2024 12:22:49 -0800 Subject: [PATCH 040/397] syscall, internal/syscall/unix: fix fstatat on linux/mips64 On linux/mips64, the syscall.Stat_t struct does not match the kernel version of the struct. Functions that operate on a Stat_t translate between it and the kernel struct. The fstatat function was not doing this translation. Make it do so. Export a syscall.Fstatat on mips64 for usage by internal/syscall/unix. Perhaps we should just do this on all architectures, but this is the smaller change for now. Fixes #70659 Change-Id: I38e36473689be25861953b418c9abc5b270a7bcf Reviewed-on: https://go-review.googlesource.com/c/go/+/633280 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- src/internal/syscall/unix/at_fstatat.go | 2 +- src/internal/syscall/unix/at_fstatat2.go | 2 +- src/syscall/syscall_linux_mips64x.go | 13 +++++++++- src/syscall/zsyscall_linux_mips64.go | 30 ++++++++++++------------ src/syscall/zsyscall_linux_mips64le.go | 30 ++++++++++++------------ 5 files changed, 44 insertions(+), 33 deletions(-) diff --git a/src/internal/syscall/unix/at_fstatat.go b/src/internal/syscall/unix/at_fstatat.go index 25de336a8041c4..217e19a776d2b2 100644 --- a/src/internal/syscall/unix/at_fstatat.go +++ b/src/internal/syscall/unix/at_fstatat.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || (linux && !loong64) || netbsd || (openbsd && mips64) +//go:build dragonfly || (linux && !(loong64 || mips64)) || netbsd || (openbsd && mips64) package unix diff --git a/src/internal/syscall/unix/at_fstatat2.go b/src/internal/syscall/unix/at_fstatat2.go index 8d20e1a885bd13..b18098b7d36eb0 100644 --- a/src/internal/syscall/unix/at_fstatat2.go +++ b/src/internal/syscall/unix/at_fstatat2.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build freebsd || (linux && loong64) +//go:build freebsd || (linux && (loong64 || mips64)) package unix diff --git a/src/syscall/syscall_linux_mips64x.go b/src/syscall/syscall_linux_mips64x.go index 51f5ead472ef4f..e826e08615e6d1 100644 --- a/src/syscall/syscall_linux_mips64x.go +++ b/src/syscall/syscall_linux_mips64x.go @@ -16,7 +16,6 @@ const ( //sys Dup2(oldfd int, newfd int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) //sys Fstatfs(fd int, buf *Statfs_t) (err error) -//sys fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) = SYS_NEWFSTATAT //sys Ftruncate(fd int, length int64) (err error) //sysnb Getegid() (egid int) //sysnb Geteuid() (euid int) @@ -126,10 +125,22 @@ type stat_t struct { Blocks int64 } +//sys fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) = SYS_NEWFSTATAT //sys fstat(fd int, st *stat_t) (err error) //sys lstat(path string, st *stat_t) (err error) //sys stat(path string, st *stat_t) (err error) +func fstatat(fd int, path string, s *Stat_t, flags int) (err error) { + st := &stat_t{} + err = fstatatInternal(fd, path, st, flags) + fillStat_t(s, st) + return +} + +func Fstatat(fd int, path string, s *Stat_t, flags int) (err error) { + return fstatat(fd, path, s, flags) +} + func Fstat(fd int, s *Stat_t) (err error) { st := &stat_t{} err = fstat(fd, st) diff --git a/src/syscall/zsyscall_linux_mips64.go b/src/syscall/zsyscall_linux_mips64.go index 0352ea54202d1c..449088c815504a 100644 --- a/src/syscall/zsyscall_linux_mips64.go +++ b/src/syscall/zsyscall_linux_mips64.go @@ -1116,21 +1116,6 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ftruncate(fd int, length int64) (err error) { _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) if e1 != 0 { @@ -1638,6 +1623,21 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func fstat(fd int, st *stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) if e1 != 0 { diff --git a/src/syscall/zsyscall_linux_mips64le.go b/src/syscall/zsyscall_linux_mips64le.go index 1338b8c1c351c4..048298a39c910d 100644 --- a/src/syscall/zsyscall_linux_mips64le.go +++ b/src/syscall/zsyscall_linux_mips64le.go @@ -1116,21 +1116,6 @@ func Fstatfs(fd int, buf *Statfs_t) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func fstatat(dirfd int, path string, stat *Stat_t, flags int) (err error) { - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return - } - _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Ftruncate(fd int, length int64) (err error) { _, _, e1 := Syscall(SYS_FTRUNCATE, uintptr(fd), uintptr(length), 0) if e1 != 0 { @@ -1638,6 +1623,21 @@ func utimes(path string, times *[2]Timeval) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func fstatatInternal(dirfd int, path string, stat *stat_t, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_NEWFSTATAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(stat)), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func fstat(fd int, st *stat_t) (err error) { _, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(unsafe.Pointer(st)), 0) if e1 != 0 { From e977b83b320b3aedca218566c42ee94c5fad6bb0 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Tue, 17 Dec 2024 20:14:16 +0200 Subject: [PATCH 041/397] cmd/go/internal/help: use secure link to swig.org Change-Id: Ifd315128ceeddf92bc16647869c3ace77ed1f430 Reviewed-on: https://go-review.googlesource.com/c/go/+/637195 Reviewed-by: Michael Matloob Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/cmd/go/alldocs.go | 2 +- src/cmd/go/internal/help/helpdoc.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 3a4473902cb8f1..5edd93599e56d8 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -2250,7 +2250,7 @@ // // The second is the SWIG program, which is a general tool for // interfacing between languages. For information on SWIG see -// http://swig.org/. When running go build, any file with a .swig +// https://swig.org/. When running go build, any file with a .swig // extension will be passed to SWIG. Any file with a .swigcxx extension // will be passed to SWIG with the -c++ option. // diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index e1240de710b7a9..3db3ed06b2c9e3 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -17,7 +17,7 @@ information on how to use it see the cgo documentation (go doc cmd/cgo). The second is the SWIG program, which is a general tool for interfacing between languages. For information on SWIG see -http://swig.org/. When running go build, any file with a .swig +https://swig.org/. When running go build, any file with a .swig extension will be passed to SWIG. Any file with a .swigcxx extension will be passed to SWIG with the -c++ option. From b057b8872d8297ec9ccbfd9d29dad51dff795846 Mon Sep 17 00:00:00 2001 From: Oleksandr Redko Date: Tue, 17 Dec 2024 19:05:23 +0200 Subject: [PATCH 042/397] bytes, strings: add cross-references in docstrings For newly funcs SplitSeq, SplitAfterSeq, FieldsSeq, FieldsFuncSeq. Updates #61901. Change-Id: I3c97bfd9c2250de68aaea348c82a05635ee797af Reviewed-on: https://go-review.googlesource.com/c/go/+/637176 Auto-Submit: Ian Lance Taylor Reviewed-by: Robert Griesemer Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/bytes/iter.go | 10 +++++----- src/strings/iter.go | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bytes/iter.go b/src/bytes/iter.go index 1cf13a94ec263e..9890a478a8b2e8 100644 --- a/src/bytes/iter.go +++ b/src/bytes/iter.go @@ -68,7 +68,7 @@ func splitSeq(s, sep []byte, sepSave int) iter.Seq[[]byte] { } // SplitSeq returns an iterator over all substrings of s separated by sep. -// The iterator yields the same strings that would be returned by Split(s, sep), +// The iterator yields the same strings that would be returned by [Split](s, sep), // but without constructing the slice. // It returns a single-use iterator. func SplitSeq(s, sep []byte) iter.Seq[[]byte] { @@ -76,7 +76,7 @@ func SplitSeq(s, sep []byte) iter.Seq[[]byte] { } // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep. -// The iterator yields the same strings that would be returned by SplitAfter(s, sep), +// The iterator yields the same strings that would be returned by [SplitAfter](s, sep), // but without constructing the slice. // It returns a single-use iterator. func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] { @@ -84,8 +84,8 @@ func SplitAfterSeq(s, sep []byte) iter.Seq[[]byte] { } // FieldsSeq returns an iterator over substrings of s split around runs of -// whitespace characters, as defined by unicode.IsSpace. -// The iterator yields the same strings that would be returned by Fields(s), +// whitespace characters, as defined by [unicode.IsSpace]. +// The iterator yields the same strings that would be returned by [Fields](s), // but without constructing the slice. func FieldsSeq(s []byte) iter.Seq[[]byte] { return func(yield func([]byte) bool) { @@ -118,7 +118,7 @@ func FieldsSeq(s []byte) iter.Seq[[]byte] { // FieldsFuncSeq returns an iterator over substrings of s split around runs of // Unicode code points satisfying f(c). -// The iterator yields the same strings that would be returned by FieldsFunc(s), +// The iterator yields the same strings that would be returned by [FieldsFunc](s), // but without constructing the slice. func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] { return func(yield func([]byte) bool) { diff --git a/src/strings/iter.go b/src/strings/iter.go index b9620902bfedb7..3168e59687dc94 100644 --- a/src/strings/iter.go +++ b/src/strings/iter.go @@ -68,7 +68,7 @@ func splitSeq(s, sep string, sepSave int) iter.Seq[string] { } // SplitSeq returns an iterator over all substrings of s separated by sep. -// The iterator yields the same strings that would be returned by Split(s, sep), +// The iterator yields the same strings that would be returned by [Split](s, sep), // but without constructing the slice. // It returns a single-use iterator. func SplitSeq(s, sep string) iter.Seq[string] { @@ -76,7 +76,7 @@ func SplitSeq(s, sep string) iter.Seq[string] { } // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep. -// The iterator yields the same strings that would be returned by SplitAfter(s, sep), +// The iterator yields the same strings that would be returned by [SplitAfter](s, sep), // but without constructing the slice. // It returns a single-use iterator. func SplitAfterSeq(s, sep string) iter.Seq[string] { @@ -84,8 +84,8 @@ func SplitAfterSeq(s, sep string) iter.Seq[string] { } // FieldsSeq returns an iterator over substrings of s split around runs of -// whitespace characters, as defined by unicode.IsSpace. -// The iterator yields the same strings that would be returned by Fields(s), +// whitespace characters, as defined by [unicode.IsSpace]. +// The iterator yields the same strings that would be returned by [Fields](s), // but without constructing the slice. func FieldsSeq(s string) iter.Seq[string] { return func(yield func(string) bool) { @@ -118,7 +118,7 @@ func FieldsSeq(s string) iter.Seq[string] { // FieldsFuncSeq returns an iterator over substrings of s split around runs of // Unicode code points satisfying f(c). -// The iterator yields the same strings that would be returned by FieldsFunc(s), +// The iterator yields the same strings that would be returned by [FieldsFunc](s), // but without constructing the slice. func FieldsFuncSeq(s string, f func(rune) bool) iter.Seq[string] { return func(yield func(string) bool) { From 8790372a8d7e777d23d6b77d248318d01f4d7c4d Mon Sep 17 00:00:00 2001 From: wangshuo Date: Tue, 17 Dec 2024 12:50:44 +0000 Subject: [PATCH 043/397] cmd, go: fix some typos Change-Id: I0fd54ae5294eb4ef30cdef05adb8825f69077b14 GitHub-Last-Rev: ccfa48cbe4525dc2bd60e9ac7e2c150e480ba13f GitHub-Pull-Request: golang/go#70823 Reviewed-on: https://go-review.googlesource.com/c/go/+/635915 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/cmd/compile/internal/types2/README.md | 2 +- src/cmd/compile/internal/types2/signature.go | 2 +- src/cmd/go/testdata/script/build_version_stamping_git.txt | 4 ++-- src/cmd/vet/vet_test.go | 2 +- src/go/types/signature.go | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/README.md b/src/cmd/compile/internal/types2/README.md index 3d70cdbcf484dd..73253b49207aac 100644 --- a/src/cmd/compile/internal/types2/README.md +++ b/src/cmd/compile/internal/types2/README.md @@ -56,7 +56,7 @@ The tests are in: Tests are .go files annotated with `/* ERROR "msg" */` or `/* ERRORx "msg" */` comments (or the respective line comment form). For each such error comment, typechecking the respective file is expected to -report an error at the position of the syntactic token _immediately preceeding_ +report an error at the position of the syntactic token _immediately preceding_ the comment. For `ERROR`, the `"msg"` string must be a substring of the error message reported by the typechecker; diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index d3169630eaa0bd..de4f1eaa207fdc 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -174,7 +174,7 @@ func (check *Checker) collectRecv(rparam *syntax.Field, scopePos syntax.Pos) (*V } else { // If there are type parameters, rbase must denote a generic base type. // Important: rbase must be resolved before declaring any receiver type - // parameters (wich may have the same name, see below). + // parameters (which may have the same name, see below). var baseType *Named // nil if not valid var cause string if t := check.genericType(rbase, &cause); isValid(t) { diff --git a/src/cmd/go/testdata/script/build_version_stamping_git.txt b/src/cmd/go/testdata/script/build_version_stamping_git.txt index ed07e00c7b192a..db804b38479960 100644 --- a/src/cmd/go/testdata/script/build_version_stamping_git.txt +++ b/src/cmd/go/testdata/script/build_version_stamping_git.txt @@ -51,7 +51,7 @@ go version -m example$GOEXE stdout '\s+mod\s+example\s+v1.0.1\s+' rm example$GOEXE -# Use tag+dirty when there are uncomitted changes present. +# Use tag+dirty when there are uncommitted changes present. cp $WORK/copy/README $WORK/repo/README go build go version -m example$GOEXE @@ -82,7 +82,7 @@ go version -m example$GOEXE stdout '\s+mod\s+example\s+v1.0.3-0.20220719150702-deaeab06f7fe\s+' rm example$GOEXE -# Use pseudo+dirty when uncomitted changes are present. +# Use pseudo+dirty when uncommitted changes are present. mv README2 README3 go build go version -m example$GOEXE diff --git a/src/cmd/vet/vet_test.go b/src/cmd/vet/vet_test.go index f1450dcbd28d2c..3860895a0ae96c 100644 --- a/src/cmd/vet/vet_test.go +++ b/src/cmd/vet/vet_test.go @@ -108,7 +108,7 @@ func TestVet(t *testing.T) { // is a no-op for files whose version >= go1.22, so we use a // go.mod file in the rangeloop directory to "downgrade". // - // TOOD(adonovan): delete when go1.21 goes away. + // TODO(adonovan): delete when go1.21 goes away. t.Run("loopclosure", func(t *testing.T) { cmd := testenv.Command(t, testenv.GoToolPath(t), "vet", "-vettool="+vetPath(t), ".") cmd.Env = append(os.Environ(), "GOWORK=off") diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 681eb85fd70b8f..ff405318ee4ca8 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -195,7 +195,7 @@ func (check *Checker) collectRecv(rparam *ast.Field, scopePos token.Pos) (*Var, } else { // If there are type parameters, rbase must denote a generic base type. // Important: rbase must be resolved before declaring any receiver type - // parameters (wich may have the same name, see below). + // parameters (which may have the same name, see below). var baseType *Named // nil if not valid var cause string if t := check.genericType(rbase, &cause); isValid(t) { From b9e2ffdcd2520c136c4e98f67f0c714f989d31ab Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 16 Dec 2024 17:44:21 +0100 Subject: [PATCH 044/397] crypto/internal/fips140: add Name and Version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per ISO/IEC 19790:2012, Section 7.4.3.1. > A cryptographic module shall [04.12] provide the following services to > operators. > > a) Show module’s versioning information. The cryptographic module > shall [04.13] output the name or module identifier and the versioning > information that can be correlated with a validation record (e.g. > hardware, software and/or firmware versioning information)." For #69536 Change-Id: I8061f64e4ae60a4666f6abd892cb1301d6bf2452 Reviewed-on: https://go-review.googlesource.com/c/go/+/636558 Auto-Submit: Filippo Valsorda Reviewed-by: Daniel McCarney Reviewed-by: Roland Shoemaker Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- src/crypto/internal/fips140/fips140.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/crypto/internal/fips140/fips140.go b/src/crypto/internal/fips140/fips140.go index cec9d13e35bb82..d30433debfcd29 100644 --- a/src/crypto/internal/fips140/fips140.go +++ b/src/crypto/internal/fips140/fips140.go @@ -19,3 +19,11 @@ func init() { debug = true } } + +func Name() string { + return "Go Cryptographic Module" +} + +func Version() string { + return "v1.0" +} From b2c0168893a7f27927630198cdf63911374035c3 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 17 Dec 2024 17:55:01 +0100 Subject: [PATCH 045/397] crypto/internal/fips140/aes/gcm: use aes.EncryptBlockInternal on ppc64x and s390x Left them out of CL 636775 because I did a search by reference, which does not span architectures. Fixes crypto/cipher.TestFIPSServiceIndicator failure on ppc64x and s390x. For #69536 Change-Id: I34b49705a7099066e8c3871a7a34b394a9298e98 Reviewed-on: https://go-review.googlesource.com/c/go/+/637175 Reviewed-by: David Chase Reviewed-by: Roland Shoemaker Auto-Submit: Filippo Valsorda Reviewed-by: Daniel McCarney LUCI-TryBot-Result: Go LUCI --- src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go | 6 +++--- src/crypto/internal/fips140/aes/gcm/gcm_s390x.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go b/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go index 5084835e88d315..8d44c75745d9b8 100644 --- a/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go +++ b/src/crypto/internal/fips140/aes/gcm/gcm_ppc64x.go @@ -51,7 +51,7 @@ func initGCM(g *GCM) { } hle := make([]byte, gcmBlockSize) - g.cipher.Encrypt(hle, hle) + aes.EncryptBlockInternal(&g.cipher, hle, hle) // Reverse the bytes in each 8 byte chunk // Load little endian, store big endian @@ -133,7 +133,7 @@ func seal(out []byte, g *GCM, nonce, plaintext, data []byte) { var counter, tagMask [gcmBlockSize]byte deriveCounter(&counter, nonce, &g.productTable) - g.cipher.Encrypt(tagMask[:], counter[:]) + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) gcmInc32(&counter) counterCrypt(&g.cipher, out, plaintext, &counter) @@ -151,7 +151,7 @@ func open(out []byte, g *GCM, nonce, ciphertext, data []byte) error { var counter, tagMask [gcmBlockSize]byte deriveCounter(&counter, nonce, &g.productTable) - g.cipher.Encrypt(tagMask[:], counter[:]) + aes.EncryptBlockInternal(&g.cipher, tagMask[:], counter[:]) gcmInc32(&counter) var expectedTag [gcmTagSize]byte diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go b/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go index 6d88e1824083be..526f3f9d4a2019 100644 --- a/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go +++ b/src/crypto/internal/fips140/aes/gcm/gcm_s390x.go @@ -55,7 +55,7 @@ func initGCM(g *GCM) { return } // Note that hashKey is also used in the KMA codepath to hash large nonces. - g.cipher.Encrypt(g.hashKey[:], g.hashKey[:]) + aes.EncryptBlockInternal(&g.cipher, g.hashKey[:], g.hashKey[:]) } // ghashAsm uses the GHASH algorithm to hash data with the given key. The initial @@ -115,7 +115,7 @@ func counterCrypt(g *GCM, dst, src []byte, cnt *[gcmBlockSize]byte) { } if len(src) > 0 { var x [16]byte - g.cipher.Encrypt(x[:], cnt[:]) + aes.EncryptBlockInternal(&g.cipher, x[:], cnt[:]) for i := range src { dst[i] = src[i] ^ x[i] } From 95b433eed428afbb4ab32f0f2541774e939989c7 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 17 Dec 2024 11:31:17 -0800 Subject: [PATCH 046/397] debug/elf: adjust version API per issue discussion This updates the new version API for the discussion on #63952. Note that the current tests do not have symbols with hidden versions. Leaving that for later. For #63952 Change-Id: I1ad4b1e485429a216ba8e5b68f7f4299d120628f Reviewed-on: https://go-review.googlesource.com/c/go/+/637235 Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Reviewed-by: Austin Clements LUCI-TryBot-Result: Go LUCI Commit-Queue: Ian Lance Taylor --- api/go1.24.txt | 18 +- src/debug/elf/file.go | 94 ++++---- src/debug/elf/file_test.go | 384 ++++++++++++++--------------- src/debug/elf/symbols_test.go | 439 +++++++++++++++++----------------- 4 files changed, 468 insertions(+), 467 deletions(-) diff --git a/api/go1.24.txt b/api/go1.24.txt index 795a70e3547695..05e2006e0747bb 100644 --- a/api/go1.24.txt +++ b/api/go1.24.txt @@ -106,16 +106,6 @@ pkg debug/elf, const VER_FLG_INFO = 4 #63952 pkg debug/elf, const VER_FLG_INFO DynamicVersionFlag #63952 pkg debug/elf, const VER_FLG_WEAK = 2 #63952 pkg debug/elf, const VER_FLG_WEAK DynamicVersionFlag #63952 -pkg debug/elf, const VersionScopeGlobal = 2 #63952 -pkg debug/elf, const VersionScopeGlobal SymbolVersionScope #63952 -pkg debug/elf, const VersionScopeHidden = 4 #63952 -pkg debug/elf, const VersionScopeHidden SymbolVersionScope #63952 -pkg debug/elf, const VersionScopeLocal = 1 #63952 -pkg debug/elf, const VersionScopeLocal SymbolVersionScope #63952 -pkg debug/elf, const VersionScopeNone = 0 #63952 -pkg debug/elf, const VersionScopeNone SymbolVersionScope #63952 -pkg debug/elf, const VersionScopeSpecific = 3 #63952 -pkg debug/elf, const VersionScopeSpecific SymbolVersionScope #63952 pkg debug/elf, method (*File) DynamicVersionNeeds() ([]DynamicVersionNeed, error) #63952 pkg debug/elf, method (*File) DynamicVersions() ([]DynamicVersion, error) #63952 pkg debug/elf, type DynamicVersion struct #63952 @@ -131,9 +121,11 @@ pkg debug/elf, type DynamicVersionFlag uint16 #63952 pkg debug/elf, type DynamicVersionNeed struct #63952 pkg debug/elf, type DynamicVersionNeed struct, Name string #63952 pkg debug/elf, type DynamicVersionNeed struct, Needs []DynamicVersionDep #63952 -pkg debug/elf, type Symbol struct, VersionScope SymbolVersionScope #63952 -pkg debug/elf, type Symbol struct, VersionIndex int16 #63952 -pkg debug/elf, type SymbolVersionScope uint8 #63952 +pkg debug/elf, type Symbol struct, HasVersion bool #63952 +pkg debug/elf, type Symbol struct, VersionIndex VersionIndex #63952 +pkg debug/elf, method (VersionIndex) Index() uint16 #63952 +pkg debug/elf, method (VersionIndex) IsHidden() bool #63952 +pkg debug/elf, type VersionIndex uint16 #63952 pkg encoding, type BinaryAppender interface { AppendBinary } #62384 pkg encoding, type BinaryAppender interface, AppendBinary([]uint8) ([]uint8, error) #62384 pkg encoding, type TextAppender interface { AppendText } #62384 diff --git a/src/debug/elf/file.go b/src/debug/elf/file.go index 958ed9971d070b..89bd70b5b2a87c 100644 --- a/src/debug/elf/file.go +++ b/src/debug/elf/file.go @@ -209,22 +209,13 @@ type Symbol struct { Name string Info, Other byte - // VersionScope describes the version in which the symbol is defined. - // This is only set for the dynamic symbol table. - // When no symbol versioning information is available, - // this is VersionScopeNone. - VersionScope SymbolVersionScope - // VersionIndex is the version index. - // This is only set if VersionScope is VersionScopeSpecific or - // VersionScopeHidden. This is only set for the dynamic symbol table. - // This index will match either [DynamicVersion.Index] - // in the slice returned by [File.DynamicVersions], - // or [DynamicVersiondep.Index] in the Needs field - // of the elements of the slice returned by [File.DynamicVersionNeeds]. - // In general, a defined symbol will have an index referring - // to DynamicVersions, and an undefined symbol will have an index - // referring to some version in DynamicVersionNeeds. - VersionIndex int16 + // HasVersion reports whether the symbol has any version information. + // This will only be true for the dynamic symbol table. + HasVersion bool + // VersionIndex is the symbol's version index. + // Use the methods of the [VersionIndex] type to access it. + // This field is only meaningful if HasVersion is true. + VersionIndex VersionIndex Section SectionIndex Value, Size uint64 @@ -678,7 +669,6 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { symbols[i].Name = str symbols[i].Info = sym.Info symbols[i].Other = sym.Other - symbols[i].VersionIndex = -1 symbols[i].Section = SectionIndex(sym.Shndx) symbols[i].Value = uint64(sym.Value) symbols[i].Size = uint64(sym.Size) @@ -726,7 +716,6 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { symbols[i].Name = str symbols[i].Info = sym.Info symbols[i].Other = sym.Other - symbols[i].VersionIndex = -1 symbols[i].Section = SectionIndex(sym.Shndx) symbols[i].Value = sym.Value symbols[i].Size = sym.Size @@ -1473,7 +1462,7 @@ func (f *File) DynamicSymbols() ([]Symbol, error) { } if hasVersions { for i := range sym { - sym[i].VersionIndex, sym[i].Version, sym[i].Library, sym[i].VersionScope = f.gnuVersion(i) + sym[i].HasVersion, sym[i].VersionIndex, sym[i].Version, sym[i].Library = f.gnuVersion(i) } } return sym, nil @@ -1502,23 +1491,37 @@ func (f *File) ImportedSymbols() ([]ImportedSymbol, error) { if ST_BIND(s.Info) == STB_GLOBAL && s.Section == SHN_UNDEF { all = append(all, ImportedSymbol{Name: s.Name}) sym := &all[len(all)-1] - _, sym.Version, sym.Library, _ = f.gnuVersion(i) + _, _, sym.Version, sym.Library = f.gnuVersion(i) } } return all, nil } -// SymbolVersionScope describes the version in which a [Symbol] is defined. -// This is only used for the dynamic symbol table. -type SymbolVersionScope byte +// VersionIndex is the type of a [Symbol] version index. +type VersionIndex uint16 -const ( - VersionScopeNone SymbolVersionScope = iota // no symbol version available - VersionScopeLocal // symbol has local scope - VersionScopeGlobal // symbol has global scope and is in the base version - VersionScopeSpecific // symbol has global scope and is in the version given by VersionIndex - VersionScopeHidden // symbol is in the version given by VersionIndex, and is hidden -) +// IsHidden reports whether the symbol is hidden within the version. +// This means that the symbol can only be seen by specifying the exact version. +func (vi VersionIndex) IsHidden() bool { + return vi&0x8000 != 0 +} + +// Index returns the version index. +// If this is the value 0, it means that the symbol is local, +// and is not visible externally. +// If this is the value 1, it means that the symbol is in the base version, +// and has no specific version; it may or may not match a +// [DynamicVersion.Index] in the slice returned by [File.DynamicVersions]. +// Other values will match either [DynamicVersion.Index] +// in the slice returned by [File.DynamicVersions], +// or [DynamicVersionDep.Index] in the Needs field +// of the elements of the slice returned by [File.DynamicVersionNeeds]. +// In general, a defined symbol will have an index referring +// to DynamicVersions, and an undefined symbol will have an index +// referring to some version in DynamicVersionNeeds. +func (vi VersionIndex) Index() uint16 { + return uint16(vi & 0x7fff) +} // DynamicVersion is a version defined by a dynamic object. // This describes entries in the ELF SHT_GNU_verdef section. @@ -1752,45 +1755,38 @@ func (f *File) gnuVersionInit(str []byte) (bool, error) { // gnuVersion adds Library and Version information to sym, // which came from offset i of the symbol table. -func (f *File) gnuVersion(i int) (versionIndex int16, version string, library string, versionFlags SymbolVersionScope) { +func (f *File) gnuVersion(i int) (hasVersion bool, versionIndex VersionIndex, version string, library string) { // Each entry is two bytes; skip undef entry at beginning. i = (i + 1) * 2 if i >= len(f.gnuVersym) { - return -1, "", "", VersionScopeNone + return false, 0, "", "" } s := f.gnuVersym[i:] if len(s) < 2 { - return -1, "", "", VersionScopeNone - } - j := int32(f.ByteOrder.Uint16(s)) - ndx := int16(j & 0x7fff) - - if j == 0 { - return ndx, "", "", VersionScopeLocal - } else if j == 1 { - return ndx, "", "", VersionScopeGlobal + return false, 0, "", "" } + vi := VersionIndex(f.ByteOrder.Uint16(s)) + ndx := vi.Index() - scope := VersionScopeSpecific - if j&0x8000 != 0 { - scope = VersionScopeHidden + if ndx == 0 || ndx == 1 { + return true, vi, "", "" } for _, v := range f.dynVerNeeds { for _, n := range v.Needs { - if uint16(ndx) == n.Index { - return ndx, n.Dep, v.Name, scope + if ndx == n.Index { + return true, vi, n.Dep, v.Name } } } for _, v := range f.dynVers { - if uint16(ndx) == v.Index { - return ndx, v.Name, "", scope + if ndx == v.Index { + return true, vi, v.Name, "" } } - return -1, "", "", VersionScopeNone + return false, 0, "", "" } // ImportedLibraries returns the names of all libraries diff --git a/src/debug/elf/file_test.go b/src/debug/elf/file_test.go index 72e45588682b55..1fdbbad04df44f 100644 --- a/src/debug/elf/file_test.go +++ b/src/debug/elf/file_test.go @@ -78,80 +78,80 @@ var fileTests = []fileTest{ }, []string{"libc.so.6"}, []Symbol{ - {"", 3, 0, VersionScopeNone, -1, 1, 134512852, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 2, 134512876, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 3, 134513020, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 4, 134513292, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 5, 134513480, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 6, 134513512, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 7, 134513532, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 8, 134513612, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 9, 134513996, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 10, 134514008, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 11, 134518268, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 13, 134518284, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 14, 134518436, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 15, 134518444, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 17, 134518456, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 18, 134518484, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 19, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 20, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 21, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 22, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 23, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 24, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 25, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 26, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 27, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 28, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 29, 0, 0, "", ""}, - {"crt1.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"__CTOR_LIST__", 1, 0, VersionScopeNone, -1, 14, 134518436, 0, "", ""}, - {"__DTOR_LIST__", 1, 0, VersionScopeNone, -1, 15, 134518444, 0, "", ""}, - {"__EH_FRAME_BEGIN__", 1, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, - {"__JCR_LIST__", 1, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, - {"p.0", 1, 0, VersionScopeNone, -1, 11, 134518276, 0, "", ""}, - {"completed.1", 1, 0, VersionScopeNone, -1, 18, 134518484, 1, "", ""}, - {"__do_global_dtors_aux", 2, 0, VersionScopeNone, -1, 8, 134513760, 0, "", ""}, - {"object.2", 1, 0, VersionScopeNone, -1, 18, 134518488, 24, "", ""}, - {"frame_dummy", 2, 0, VersionScopeNone, -1, 8, 134513836, 0, "", ""}, - {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"__CTOR_END__", 1, 0, VersionScopeNone, -1, 14, 134518440, 0, "", ""}, - {"__DTOR_END__", 1, 0, VersionScopeNone, -1, 15, 134518448, 0, "", ""}, - {"__FRAME_END__", 1, 0, VersionScopeNone, -1, 12, 134518280, 0, "", ""}, - {"__JCR_END__", 1, 0, VersionScopeNone, -1, 16, 134518452, 0, "", ""}, - {"__do_global_ctors_aux", 2, 0, VersionScopeNone, -1, 8, 134513960, 0, "", ""}, - {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {" ", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"printf", 18, 0, VersionScopeNone, -1, 0, 0, 44, "", ""}, - {"_DYNAMIC", 17, 0, VersionScopeNone, -1, 65521, 134518284, 0, "", ""}, - {"__dso_handle", 17, 2, VersionScopeNone, -1, 11, 134518272, 0, "", ""}, - {"_init", 18, 0, VersionScopeNone, -1, 6, 134513512, 0, "", ""}, - {"environ", 17, 0, VersionScopeNone, -1, 18, 134518512, 4, "", ""}, - {"__deregister_frame_info", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, - {"__progname", 17, 0, VersionScopeNone, -1, 11, 134518268, 4, "", ""}, - {"_start", 18, 0, VersionScopeNone, -1, 8, 134513612, 145, "", ""}, - {"__bss_start", 16, 0, VersionScopeNone, -1, 65521, 134518484, 0, "", ""}, - {"main", 18, 0, VersionScopeNone, -1, 8, 134513912, 46, "", ""}, - {"_init_tls", 18, 0, VersionScopeNone, -1, 0, 0, 5, "", ""}, - {"_fini", 18, 0, VersionScopeNone, -1, 9, 134513996, 0, "", ""}, - {"atexit", 18, 0, VersionScopeNone, -1, 0, 0, 43, "", ""}, - {"_edata", 16, 0, VersionScopeNone, -1, 65521, 134518484, 0, "", ""}, - {"_GLOBAL_OFFSET_TABLE_", 17, 0, VersionScopeNone, -1, 65521, 134518456, 0, "", ""}, - {"_end", 16, 0, VersionScopeNone, -1, 65521, 134518516, 0, "", ""}, - {"exit", 18, 0, VersionScopeNone, -1, 0, 0, 68, "", ""}, - {"_Jv_RegisterClasses", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, - {"__register_frame_info", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, + {"", 3, 0, false, 0, 1, 134512852, 0, "", ""}, + {"", 3, 0, false, 0, 2, 134512876, 0, "", ""}, + {"", 3, 0, false, 0, 3, 134513020, 0, "", ""}, + {"", 3, 0, false, 0, 4, 134513292, 0, "", ""}, + {"", 3, 0, false, 0, 5, 134513480, 0, "", ""}, + {"", 3, 0, false, 0, 6, 134513512, 0, "", ""}, + {"", 3, 0, false, 0, 7, 134513532, 0, "", ""}, + {"", 3, 0, false, 0, 8, 134513612, 0, "", ""}, + {"", 3, 0, false, 0, 9, 134513996, 0, "", ""}, + {"", 3, 0, false, 0, 10, 134514008, 0, "", ""}, + {"", 3, 0, false, 0, 11, 134518268, 0, "", ""}, + {"", 3, 0, false, 0, 12, 134518280, 0, "", ""}, + {"", 3, 0, false, 0, 13, 134518284, 0, "", ""}, + {"", 3, 0, false, 0, 14, 134518436, 0, "", ""}, + {"", 3, 0, false, 0, 15, 134518444, 0, "", ""}, + {"", 3, 0, false, 0, 16, 134518452, 0, "", ""}, + {"", 3, 0, false, 0, 17, 134518456, 0, "", ""}, + {"", 3, 0, false, 0, 18, 134518484, 0, "", ""}, + {"", 3, 0, false, 0, 19, 0, 0, "", ""}, + {"", 3, 0, false, 0, 20, 0, 0, "", ""}, + {"", 3, 0, false, 0, 21, 0, 0, "", ""}, + {"", 3, 0, false, 0, 22, 0, 0, "", ""}, + {"", 3, 0, false, 0, 23, 0, 0, "", ""}, + {"", 3, 0, false, 0, 24, 0, 0, "", ""}, + {"", 3, 0, false, 0, 25, 0, 0, "", ""}, + {"", 3, 0, false, 0, 26, 0, 0, "", ""}, + {"", 3, 0, false, 0, 27, 0, 0, "", ""}, + {"", 3, 0, false, 0, 28, 0, 0, "", ""}, + {"", 3, 0, false, 0, 29, 0, 0, "", ""}, + {"crt1.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"/usr/src/lib/csu/i386-elf/crti.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"__CTOR_LIST__", 1, 0, false, 0, 14, 134518436, 0, "", ""}, + {"__DTOR_LIST__", 1, 0, false, 0, 15, 134518444, 0, "", ""}, + {"__EH_FRAME_BEGIN__", 1, 0, false, 0, 12, 134518280, 0, "", ""}, + {"__JCR_LIST__", 1, 0, false, 0, 16, 134518452, 0, "", ""}, + {"p.0", 1, 0, false, 0, 11, 134518276, 0, "", ""}, + {"completed.1", 1, 0, false, 0, 18, 134518484, 1, "", ""}, + {"__do_global_dtors_aux", 2, 0, false, 0, 8, 134513760, 0, "", ""}, + {"object.2", 1, 0, false, 0, 18, 134518488, 24, "", ""}, + {"frame_dummy", 2, 0, false, 0, 8, 134513836, 0, "", ""}, + {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"__CTOR_END__", 1, 0, false, 0, 14, 134518440, 0, "", ""}, + {"__DTOR_END__", 1, 0, false, 0, 15, 134518448, 0, "", ""}, + {"__FRAME_END__", 1, 0, false, 0, 12, 134518280, 0, "", ""}, + {"__JCR_END__", 1, 0, false, 0, 16, 134518452, 0, "", ""}, + {"__do_global_ctors_aux", 2, 0, false, 0, 8, 134513960, 0, "", ""}, + {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {" ", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"/usr/src/lib/csu/i386-elf/crtn.S", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"printf", 18, 0, false, 0, 0, 0, 44, "", ""}, + {"_DYNAMIC", 17, 0, false, 0, 65521, 134518284, 0, "", ""}, + {"__dso_handle", 17, 2, false, 0, 11, 134518272, 0, "", ""}, + {"_init", 18, 0, false, 0, 6, 134513512, 0, "", ""}, + {"environ", 17, 0, false, 0, 18, 134518512, 4, "", ""}, + {"__deregister_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""}, + {"__progname", 17, 0, false, 0, 11, 134518268, 4, "", ""}, + {"_start", 18, 0, false, 0, 8, 134513612, 145, "", ""}, + {"__bss_start", 16, 0, false, 0, 65521, 134518484, 0, "", ""}, + {"main", 18, 0, false, 0, 8, 134513912, 46, "", ""}, + {"_init_tls", 18, 0, false, 0, 0, 0, 5, "", ""}, + {"_fini", 18, 0, false, 0, 9, 134513996, 0, "", ""}, + {"atexit", 18, 0, false, 0, 0, 0, 43, "", ""}, + {"_edata", 16, 0, false, 0, 65521, 134518484, 0, "", ""}, + {"_GLOBAL_OFFSET_TABLE_", 17, 0, false, 0, 65521, 134518456, 0, "", ""}, + {"_end", 16, 0, false, 0, 65521, 134518516, 0, "", ""}, + {"exit", 18, 0, false, 0, 0, 0, 68, "", ""}, + {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""}, + {"__register_frame_info", 32, 0, false, 0, 0, 0, 0, "", ""}, }, }, { @@ -208,79 +208,79 @@ var fileTests = []fileTest{ }, []string{"libc.so.6"}, []Symbol{ - {"", 3, 0, VersionScopeNone, -1, 1, 4194816, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 2, 4194844, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 3, 4194880, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 4, 4194920, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 5, 4194952, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 6, 4195048, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 7, 4195110, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 8, 4195120, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 9, 4195152, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 10, 4195176, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 11, 4195224, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 12, 4195248, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 13, 4195296, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 14, 4195732, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 15, 4195748, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 16, 4195768, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 17, 4195808, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 18, 6293128, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 19, 6293144, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 21, 6293168, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 22, 6293584, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 23, 6293592, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 25, 6293656, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 26, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 27, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 28, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 29, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 30, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 31, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 32, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 33, 0, 0, "", ""}, - {"init.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"initfini.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"call_gmon_start", 2, 0, VersionScopeNone, -1, 13, 4195340, 0, "", ""}, - {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"__CTOR_LIST__", 1, 0, VersionScopeNone, -1, 18, 6293128, 0, "", ""}, - {"__DTOR_LIST__", 1, 0, VersionScopeNone, -1, 19, 6293144, 0, "", ""}, - {"__JCR_LIST__", 1, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, - {"__do_global_dtors_aux", 2, 0, VersionScopeNone, -1, 13, 4195376, 0, "", ""}, - {"completed.6183", 1, 0, VersionScopeNone, -1, 25, 6293656, 1, "", ""}, - {"p.6181", 1, 0, VersionScopeNone, -1, 24, 6293648, 0, "", ""}, - {"frame_dummy", 2, 0, VersionScopeNone, -1, 13, 4195440, 0, "", ""}, - {"crtstuff.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"__CTOR_END__", 1, 0, VersionScopeNone, -1, 18, 6293136, 0, "", ""}, - {"__DTOR_END__", 1, 0, VersionScopeNone, -1, 19, 6293152, 0, "", ""}, - {"__FRAME_END__", 1, 0, VersionScopeNone, -1, 17, 4195968, 0, "", ""}, - {"__JCR_END__", 1, 0, VersionScopeNone, -1, 20, 6293160, 0, "", ""}, - {"__do_global_ctors_aux", 2, 0, VersionScopeNone, -1, 13, 4195680, 0, "", ""}, - {"initfini.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"_GLOBAL_OFFSET_TABLE_", 1, 2, VersionScopeNone, -1, 23, 6293592, 0, "", ""}, - {"__init_array_end", 0, 2, VersionScopeNone, -1, 18, 6293124, 0, "", ""}, - {"__init_array_start", 0, 2, VersionScopeNone, -1, 18, 6293124, 0, "", ""}, - {"_DYNAMIC", 1, 2, VersionScopeNone, -1, 21, 6293168, 0, "", ""}, - {"data_start", 32, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, - {"__libc_csu_fini", 18, 0, VersionScopeNone, -1, 13, 4195520, 2, "", ""}, - {"_start", 18, 0, VersionScopeNone, -1, 13, 4195296, 0, "", ""}, - {"__gmon_start__", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, - {"_Jv_RegisterClasses", 32, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, - {"puts@@GLIBC_2.2.5", 18, 0, VersionScopeNone, -1, 0, 0, 396, "", ""}, - {"_fini", 18, 0, VersionScopeNone, -1, 14, 4195732, 0, "", ""}, - {"__libc_start_main@@GLIBC_2.2.5", 18, 0, VersionScopeNone, -1, 0, 0, 450, "", ""}, - {"_IO_stdin_used", 17, 0, VersionScopeNone, -1, 15, 4195748, 4, "", ""}, - {"__data_start", 16, 0, VersionScopeNone, -1, 24, 6293632, 0, "", ""}, - {"__dso_handle", 17, 2, VersionScopeNone, -1, 24, 6293640, 0, "", ""}, - {"__libc_csu_init", 18, 0, VersionScopeNone, -1, 13, 4195536, 137, "", ""}, - {"__bss_start", 16, 0, VersionScopeNone, -1, 65521, 6293656, 0, "", ""}, - {"_end", 16, 0, VersionScopeNone, -1, 65521, 6293664, 0, "", ""}, - {"_edata", 16, 0, VersionScopeNone, -1, 65521, 6293656, 0, "", ""}, - {"main", 18, 0, VersionScopeNone, -1, 13, 4195480, 27, "", ""}, - {"_init", 18, 0, VersionScopeNone, -1, 11, 4195224, 0, "", ""}, + {"", 3, 0, false, 0, 1, 4194816, 0, "", ""}, + {"", 3, 0, false, 0, 2, 4194844, 0, "", ""}, + {"", 3, 0, false, 0, 3, 4194880, 0, "", ""}, + {"", 3, 0, false, 0, 4, 4194920, 0, "", ""}, + {"", 3, 0, false, 0, 5, 4194952, 0, "", ""}, + {"", 3, 0, false, 0, 6, 4195048, 0, "", ""}, + {"", 3, 0, false, 0, 7, 4195110, 0, "", ""}, + {"", 3, 0, false, 0, 8, 4195120, 0, "", ""}, + {"", 3, 0, false, 0, 9, 4195152, 0, "", ""}, + {"", 3, 0, false, 0, 10, 4195176, 0, "", ""}, + {"", 3, 0, false, 0, 11, 4195224, 0, "", ""}, + {"", 3, 0, false, 0, 12, 4195248, 0, "", ""}, + {"", 3, 0, false, 0, 13, 4195296, 0, "", ""}, + {"", 3, 0, false, 0, 14, 4195732, 0, "", ""}, + {"", 3, 0, false, 0, 15, 4195748, 0, "", ""}, + {"", 3, 0, false, 0, 16, 4195768, 0, "", ""}, + {"", 3, 0, false, 0, 17, 4195808, 0, "", ""}, + {"", 3, 0, false, 0, 18, 6293128, 0, "", ""}, + {"", 3, 0, false, 0, 19, 6293144, 0, "", ""}, + {"", 3, 0, false, 0, 20, 6293160, 0, "", ""}, + {"", 3, 0, false, 0, 21, 6293168, 0, "", ""}, + {"", 3, 0, false, 0, 22, 6293584, 0, "", ""}, + {"", 3, 0, false, 0, 23, 6293592, 0, "", ""}, + {"", 3, 0, false, 0, 24, 6293632, 0, "", ""}, + {"", 3, 0, false, 0, 25, 6293656, 0, "", ""}, + {"", 3, 0, false, 0, 26, 0, 0, "", ""}, + {"", 3, 0, false, 0, 27, 0, 0, "", ""}, + {"", 3, 0, false, 0, 28, 0, 0, "", ""}, + {"", 3, 0, false, 0, 29, 0, 0, "", ""}, + {"", 3, 0, false, 0, 30, 0, 0, "", ""}, + {"", 3, 0, false, 0, 31, 0, 0, "", ""}, + {"", 3, 0, false, 0, 32, 0, 0, "", ""}, + {"", 3, 0, false, 0, 33, 0, 0, "", ""}, + {"init.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"call_gmon_start", 2, 0, false, 0, 13, 4195340, 0, "", ""}, + {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"__CTOR_LIST__", 1, 0, false, 0, 18, 6293128, 0, "", ""}, + {"__DTOR_LIST__", 1, 0, false, 0, 19, 6293144, 0, "", ""}, + {"__JCR_LIST__", 1, 0, false, 0, 20, 6293160, 0, "", ""}, + {"__do_global_dtors_aux", 2, 0, false, 0, 13, 4195376, 0, "", ""}, + {"completed.6183", 1, 0, false, 0, 25, 6293656, 1, "", ""}, + {"p.6181", 1, 0, false, 0, 24, 6293648, 0, "", ""}, + {"frame_dummy", 2, 0, false, 0, 13, 4195440, 0, "", ""}, + {"crtstuff.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"__CTOR_END__", 1, 0, false, 0, 18, 6293136, 0, "", ""}, + {"__DTOR_END__", 1, 0, false, 0, 19, 6293152, 0, "", ""}, + {"__FRAME_END__", 1, 0, false, 0, 17, 4195968, 0, "", ""}, + {"__JCR_END__", 1, 0, false, 0, 20, 6293160, 0, "", ""}, + {"__do_global_ctors_aux", 2, 0, false, 0, 13, 4195680, 0, "", ""}, + {"initfini.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"_GLOBAL_OFFSET_TABLE_", 1, 2, false, 0, 23, 6293592, 0, "", ""}, + {"__init_array_end", 0, 2, false, 0, 18, 6293124, 0, "", ""}, + {"__init_array_start", 0, 2, false, 0, 18, 6293124, 0, "", ""}, + {"_DYNAMIC", 1, 2, false, 0, 21, 6293168, 0, "", ""}, + {"data_start", 32, 0, false, 0, 24, 6293632, 0, "", ""}, + {"__libc_csu_fini", 18, 0, false, 0, 13, 4195520, 2, "", ""}, + {"_start", 18, 0, false, 0, 13, 4195296, 0, "", ""}, + {"__gmon_start__", 32, 0, false, 0, 0, 0, 0, "", ""}, + {"_Jv_RegisterClasses", 32, 0, false, 0, 0, 0, 0, "", ""}, + {"puts@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 396, "", ""}, + {"_fini", 18, 0, false, 0, 14, 4195732, 0, "", ""}, + {"__libc_start_main@@GLIBC_2.2.5", 18, 0, false, 0, 0, 0, 450, "", ""}, + {"_IO_stdin_used", 17, 0, false, 0, 15, 4195748, 4, "", ""}, + {"__data_start", 16, 0, false, 0, 24, 6293632, 0, "", ""}, + {"__dso_handle", 17, 2, false, 0, 24, 6293640, 0, "", ""}, + {"__libc_csu_init", 18, 0, false, 0, 13, 4195536, 137, "", ""}, + {"__bss_start", 16, 0, false, 0, 65521, 6293656, 0, "", ""}, + {"_end", 16, 0, false, 0, 65521, 6293664, 0, "", ""}, + {"_edata", 16, 0, false, 0, 65521, 6293656, 0, "", ""}, + {"main", 18, 0, false, 0, 13, 4195480, 27, "", ""}, + {"_init", 18, 0, false, 0, 11, 4195224, 0, "", ""}, }, }, { @@ -338,21 +338,21 @@ var fileTests = []fileTest{ []ProgHeader{}, nil, []Symbol{ - {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, - {"main", 18, 0, VersionScopeNone, -1, 1, 0, 23, "", ""}, - {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, + {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"", 3, 0, false, 0, 1, 0, 0, "", ""}, + {"", 3, 0, false, 0, 3, 0, 0, "", ""}, + {"", 3, 0, false, 0, 4, 0, 0, "", ""}, + {"", 3, 0, false, 0, 5, 0, 0, "", ""}, + {"", 3, 0, false, 0, 6, 0, 0, "", ""}, + {"", 3, 0, false, 0, 8, 0, 0, "", ""}, + {"", 3, 0, false, 0, 9, 0, 0, "", ""}, + {"", 3, 0, false, 0, 11, 0, 0, "", ""}, + {"", 3, 0, false, 0, 13, 0, 0, "", ""}, + {"", 3, 0, false, 0, 15, 0, 0, "", ""}, + {"", 3, 0, false, 0, 16, 0, 0, "", ""}, + {"", 3, 0, false, 0, 14, 0, 0, "", ""}, + {"main", 18, 0, false, 0, 1, 0, 23, "", ""}, + {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, }, }, { @@ -384,21 +384,21 @@ var fileTests = []fileTest{ []ProgHeader{}, nil, []Symbol{ - {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, - {"main", 18, 0, VersionScopeNone, -1, 1, 0, 27, "", ""}, - {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, + {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"", 3, 0, false, 0, 1, 0, 0, "", ""}, + {"", 3, 0, false, 0, 3, 0, 0, "", ""}, + {"", 3, 0, false, 0, 4, 0, 0, "", ""}, + {"", 3, 0, false, 0, 5, 0, 0, "", ""}, + {"", 3, 0, false, 0, 6, 0, 0, "", ""}, + {"", 3, 0, false, 0, 8, 0, 0, "", ""}, + {"", 3, 0, false, 0, 9, 0, 0, "", ""}, + {"", 3, 0, false, 0, 11, 0, 0, "", ""}, + {"", 3, 0, false, 0, 13, 0, 0, "", ""}, + {"", 3, 0, false, 0, 15, 0, 0, "", ""}, + {"", 3, 0, false, 0, 16, 0, 0, "", ""}, + {"", 3, 0, false, 0, 14, 0, 0, "", ""}, + {"main", 18, 0, false, 0, 1, 0, 27, "", ""}, + {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, }, }, { @@ -430,21 +430,21 @@ var fileTests = []fileTest{ []ProgHeader{}, nil, []Symbol{ - {"hello.c", 4, 0, VersionScopeNone, -1, 65521, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 1, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 3, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 4, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 5, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 6, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 8, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 9, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 11, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 13, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 15, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 16, 0, 0, "", ""}, - {"", 3, 0, VersionScopeNone, -1, 14, 0, 0, "", ""}, - {"main", 18, 0, VersionScopeNone, -1, 1, 0, 44, "", ""}, - {"puts", 16, 0, VersionScopeNone, -1, 0, 0, 0, "", ""}, + {"hello.c", 4, 0, false, 0, 65521, 0, 0, "", ""}, + {"", 3, 0, false, 0, 1, 0, 0, "", ""}, + {"", 3, 0, false, 0, 3, 0, 0, "", ""}, + {"", 3, 0, false, 0, 4, 0, 0, "", ""}, + {"", 3, 0, false, 0, 5, 0, 0, "", ""}, + {"", 3, 0, false, 0, 6, 0, 0, "", ""}, + {"", 3, 0, false, 0, 8, 0, 0, "", ""}, + {"", 3, 0, false, 0, 9, 0, 0, "", ""}, + {"", 3, 0, false, 0, 11, 0, 0, "", ""}, + {"", 3, 0, false, 0, 13, 0, 0, "", ""}, + {"", 3, 0, false, 0, 15, 0, 0, "", ""}, + {"", 3, 0, false, 0, 16, 0, 0, "", ""}, + {"", 3, 0, false, 0, 14, 0, 0, "", ""}, + {"main", 18, 0, false, 0, 1, 0, 44, "", ""}, + {"puts", 16, 0, false, 0, 0, 0, 0, "", ""}, }, }, } diff --git a/src/debug/elf/symbols_test.go b/src/debug/elf/symbols_test.go index 8b6dac019b63a1..6053d99acc1a0b 100644 --- a/src/debug/elf/symbols_test.go +++ b/src/debug/elf/symbols_test.go @@ -39,6 +39,19 @@ func TestSymbols(t *testing.T) { if !reflect.DeepEqual(ts, fs) { t.Errorf("%s: Symbols = %v, want %v", file, fs, ts) } + + for i, s := range fs { + if s.HasVersion { + // No hidden versions here. + if s.VersionIndex.IsHidden() { + t.Errorf("%s: symbol %d: unexpected hidden version", file, i) + } + if got, want := s.VersionIndex.Index(), uint16(s.VersionIndex); got != want { + t.Errorf("%s: symbol %d: VersionIndex.Index() == %d, want %d", file, i, got, want) + } + } + } + } for file, ts := range symbolsGolden { do(file, ts, (*File).Symbols) @@ -56,8 +69,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1, Value: 0x400200, Size: 0x0, @@ -66,8 +79,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x2, Value: 0x40021C, Size: 0x0, @@ -76,8 +89,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x3, Value: 0x400240, Size: 0x0, @@ -86,8 +99,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x4, Value: 0x400268, Size: 0x0, @@ -96,8 +109,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x5, Value: 0x400288, Size: 0x0, @@ -106,8 +119,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x6, Value: 0x4002E8, Size: 0x0, @@ -116,8 +129,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x7, Value: 0x400326, Size: 0x0, @@ -126,8 +139,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x8, Value: 0x400330, Size: 0x0, @@ -136,8 +149,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x9, Value: 0x400350, Size: 0x0, @@ -146,8 +159,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xA, Value: 0x400368, Size: 0x0, @@ -156,8 +169,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xB, Value: 0x400398, Size: 0x0, @@ -166,8 +179,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xC, Value: 0x4003B0, Size: 0x0, @@ -176,8 +189,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x4003E0, Size: 0x0, @@ -186,8 +199,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xE, Value: 0x400594, Size: 0x0, @@ -196,8 +209,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xF, Value: 0x4005A4, Size: 0x0, @@ -206,8 +219,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x10, Value: 0x4005B8, Size: 0x0, @@ -216,8 +229,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x11, Value: 0x4005E0, Size: 0x0, @@ -226,8 +239,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x12, Value: 0x600688, Size: 0x0, @@ -236,8 +249,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x13, Value: 0x600698, Size: 0x0, @@ -246,8 +259,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x14, Value: 0x6006A8, Size: 0x0, @@ -256,8 +269,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x15, Value: 0x6006B0, Size: 0x0, @@ -266,8 +279,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x16, Value: 0x600850, Size: 0x0, @@ -276,8 +289,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x17, Value: 0x600858, Size: 0x0, @@ -286,8 +299,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x18, Value: 0x600880, Size: 0x0, @@ -296,8 +309,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x19, Value: 0x600898, Size: 0x0, @@ -306,8 +319,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1A, Value: 0x0, Size: 0x0, @@ -316,8 +329,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1B, Value: 0x0, Size: 0x0, @@ -326,8 +339,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1C, Value: 0x0, Size: 0x0, @@ -336,8 +349,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1D, Value: 0x0, Size: 0x0, @@ -346,8 +359,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1E, Value: 0x0, Size: 0x0, @@ -356,8 +369,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1F, Value: 0x0, Size: 0x0, @@ -366,8 +379,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x20, Value: 0x0, Size: 0x0, @@ -376,8 +389,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x21, Value: 0x0, Size: 0x0, @@ -386,8 +399,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "init.c", Info: 0x4, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x0, Size: 0x0, @@ -396,8 +409,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "initfini.c", Info: 0x4, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x0, Size: 0x0, @@ -406,8 +419,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "call_gmon_start", Info: 0x2, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x40040C, Size: 0x0, @@ -416,8 +429,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "crtstuff.c", Info: 0x4, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x0, Size: 0x0, @@ -426,8 +439,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__CTOR_LIST__", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x12, Value: 0x600688, Size: 0x0, @@ -436,8 +449,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__DTOR_LIST__", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x13, Value: 0x600698, Size: 0x0, @@ -446,8 +459,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__JCR_LIST__", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x14, Value: 0x6006A8, Size: 0x0, @@ -456,8 +469,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__do_global_dtors_aux", Info: 0x2, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x400430, Size: 0x0, @@ -466,8 +479,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "completed.6183", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x19, Value: 0x600898, Size: 0x1, @@ -476,8 +489,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "p.6181", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x18, Value: 0x600890, Size: 0x0, @@ -486,8 +499,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "frame_dummy", Info: 0x2, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x400470, Size: 0x0, @@ -496,8 +509,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "crtstuff.c", Info: 0x4, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x0, Size: 0x0, @@ -506,8 +519,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__CTOR_END__", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x12, Value: 0x600690, Size: 0x0, @@ -516,8 +529,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__DTOR_END__", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x13, Value: 0x6006A0, Size: 0x0, @@ -526,8 +539,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__FRAME_END__", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x11, Value: 0x400680, Size: 0x0, @@ -536,8 +549,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__JCR_END__", Info: 0x1, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x14, Value: 0x6006A8, Size: 0x0, @@ -546,8 +559,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__do_global_ctors_aux", Info: 0x2, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x400560, Size: 0x0, @@ -556,8 +569,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "initfini.c", Info: 0x4, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x0, Size: 0x0, @@ -566,8 +579,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "hello.c", Info: 0x4, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x0, Size: 0x0, @@ -576,8 +589,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_GLOBAL_OFFSET_TABLE_", Info: 0x1, Other: 0x2, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x17, Value: 0x600858, Size: 0x0, @@ -586,8 +599,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__init_array_end", Info: 0x0, Other: 0x2, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x12, Value: 0x600684, Size: 0x0, @@ -596,8 +609,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__init_array_start", Info: 0x0, Other: 0x2, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x12, Value: 0x600684, Size: 0x0, @@ -606,8 +619,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_DYNAMIC", Info: 0x1, Other: 0x2, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x15, Value: 0x6006B0, Size: 0x0, @@ -616,8 +629,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "data_start", Info: 0x20, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x18, Value: 0x600880, Size: 0x0, @@ -626,8 +639,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__libc_csu_fini", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x4004C0, Size: 0x2, @@ -636,8 +649,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_start", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x4003E0, Size: 0x0, @@ -646,8 +659,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__gmon_start__", Info: 0x20, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x0, Value: 0x0, Size: 0x0, @@ -656,8 +669,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_Jv_RegisterClasses", Info: 0x20, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x0, Value: 0x0, Size: 0x0, @@ -666,8 +679,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "puts@@GLIBC_2.2.5", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x0, Value: 0x0, Size: 0x18C, @@ -676,8 +689,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_fini", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xE, Value: 0x400594, Size: 0x0, @@ -686,8 +699,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__libc_start_main@@GLIBC_2.2.5", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x0, Value: 0x0, Size: 0x1C2, @@ -696,8 +709,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_IO_stdin_used", Info: 0x11, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xF, Value: 0x4005A4, Size: 0x4, @@ -706,8 +719,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__data_start", Info: 0x10, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x18, Value: 0x600880, Size: 0x0, @@ -716,8 +729,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__dso_handle", Info: 0x11, Other: 0x2, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x18, Value: 0x600888, Size: 0x0, @@ -726,8 +739,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__libc_csu_init", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x4004D0, Size: 0x89, @@ -736,8 +749,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "__bss_start", Info: 0x10, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x600898, Size: 0x0, @@ -746,8 +759,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_end", Info: 0x10, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x6008A0, Size: 0x0, @@ -756,8 +769,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_edata", Info: 0x10, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x600898, Size: 0x0, @@ -766,8 +779,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "main", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x400498, Size: 0x1B, @@ -776,8 +789,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "_init", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xB, Value: 0x400398, Size: 0x0, @@ -788,8 +801,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "go-relocation-test-clang.c", Info: 0x4, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF1, Value: 0x0, Size: 0x0, @@ -798,8 +811,8 @@ var symbolsGolden = map[string][]Symbol{ Name: ".Linfo_string0", Info: 0x0, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xC, Value: 0x0, Size: 0x0, @@ -808,8 +821,8 @@ var symbolsGolden = map[string][]Symbol{ Name: ".Linfo_string1", Info: 0x0, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xC, Value: 0x2C, Size: 0x0, @@ -818,8 +831,8 @@ var symbolsGolden = map[string][]Symbol{ Name: ".Linfo_string2", Info: 0x0, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xC, Value: 0x47, Size: 0x0, @@ -828,8 +841,8 @@ var symbolsGolden = map[string][]Symbol{ Name: ".Linfo_string3", Info: 0x0, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xC, Value: 0x4C, Size: 0x0, @@ -838,8 +851,8 @@ var symbolsGolden = map[string][]Symbol{ Name: ".Linfo_string4", Info: 0x0, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xC, Value: 0x4E, Size: 0x0, @@ -848,8 +861,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x1, Value: 0x0, Size: 0x0, @@ -858,8 +871,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x2, Value: 0x0, Size: 0x0, @@ -868,8 +881,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x3, Value: 0x0, Size: 0x0, @@ -878,8 +891,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x4, Value: 0x0, Size: 0x0, @@ -888,8 +901,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x6, Value: 0x0, Size: 0x0, @@ -898,8 +911,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x7, Value: 0x0, Size: 0x0, @@ -908,8 +921,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x8, Value: 0x0, Size: 0x0, @@ -918,8 +931,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xA, Value: 0x0, Size: 0x0, @@ -928,8 +941,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xC, Value: 0x0, Size: 0x0, @@ -938,8 +951,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xD, Value: 0x0, Size: 0x0, @@ -948,8 +961,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xE, Value: 0x0, Size: 0x0, @@ -958,8 +971,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xF, Value: 0x0, Size: 0x0, @@ -968,8 +981,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "", Info: 0x3, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0x10, Value: 0x0, Size: 0x0, @@ -978,8 +991,8 @@ var symbolsGolden = map[string][]Symbol{ Name: "v", Info: 0x11, Other: 0x0, - VersionScope: VersionScopeNone, - VersionIndex: -1, + HasVersion: false, + VersionIndex: 0, Section: 0xFFF2, Value: 0x4, Size: 0x4, @@ -994,7 +1007,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "__gmon_start__", Info: 0x20, Other: 0x0, - VersionScope: VersionScopeLocal, + HasVersion: true, VersionIndex: 0x0, Section: 0x0, Value: 0x0, @@ -1004,7 +1017,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "puts", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x2, Section: 0x0, Value: 0x0, @@ -1016,7 +1029,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "__libc_start_main", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x2, Section: 0x0, Value: 0x0, @@ -1032,7 +1045,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSo3putEc", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1044,7 +1057,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "strchr", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x4, Section: 0x0, Value: 0x0, @@ -1056,7 +1069,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "__cxa_finalize", Info: 0x22, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x4, Section: 0x0, Value: 0x0, @@ -1068,7 +1081,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSo5tellpEv", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1080,7 +1093,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSo5seekpElSt12_Ios_Seekdir", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1092,7 +1105,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_Znwm", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1104,7 +1117,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZdlPvm", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x5, Section: 0x0, Value: 0x0, @@ -1116,7 +1129,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "__stack_chk_fail", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x6, Section: 0x0, Value: 0x0, @@ -1128,7 +1141,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZSt16__ostream_insertIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_PKS3_l", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x7, Section: 0x0, Value: 0x0, @@ -1140,7 +1153,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSo5seekpESt4fposI11__mbstate_tE", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1152,7 +1165,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSi4readEPcl", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1164,7 +1177,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSi5seekgESt4fposI11__mbstate_tE", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1176,7 +1189,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSo5writeEPKcl", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1188,7 +1201,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSi5seekgElSt12_Ios_Seekdir", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1200,7 +1213,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZSt21ios_base_library_initv", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x8, Section: 0x0, Value: 0x0, @@ -1212,7 +1225,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "TIFFClientOpen", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x9, Section: 0x0, Value: 0x0, @@ -1224,7 +1237,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSt9basic_iosIcSt11char_traitsIcEE5clearESt12_Ios_Iostate", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1236,7 +1249,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ZNSi5tellgEv", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x3, Section: 0x0, Value: 0x0, @@ -1248,7 +1261,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ITM_deregisterTMCloneTable", Info: 0x20, Other: 0x0, - VersionScope: VersionScopeGlobal, + HasVersion: true, VersionIndex: 0x1, Section: 0x0, Value: 0x0, @@ -1258,7 +1271,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "__gmon_start__", Info: 0x20, Other: 0x0, - VersionScope: VersionScopeGlobal, + HasVersion: true, VersionIndex: 0x1, Section: 0x0, Value: 0x0, @@ -1268,7 +1281,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_ITM_registerTMCloneTable", Info: 0x20, Other: 0x0, - VersionScope: VersionScopeGlobal, + HasVersion: true, VersionIndex: 0x1, Section: 0x0, Value: 0x0, @@ -1278,7 +1291,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "LIBTIFFXX_4.0", Info: 0x11, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x2, Section: 0xFFF1, Value: 0x0, @@ -1290,7 +1303,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_Z14TIFFStreamOpenPKcPSo", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x2, Section: 0xF, Value: 0x1860, @@ -1302,7 +1315,7 @@ var dynamicSymbolsGolden = map[string][]Symbol{ Name: "_Z14TIFFStreamOpenPKcPSi", Info: 0x12, Other: 0x0, - VersionScope: VersionScopeSpecific, + HasVersion: true, VersionIndex: 0x2, Section: 0xF, Value: 0x1920, From 971448ddf8c55a5f4a829735a5a96cacf982f230 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 17 Dec 2024 15:31:10 -0800 Subject: [PATCH 047/397] testing: support B.Context and F.Context CL 603959 added T.Context for #36532. The discussion on the proposal only mentions t.Context. However, the implementation of CL 603959 also added B.Context and F.Context. They were added to the API listing, and B.Context was mentioned in the release notes. Unfortunately, the new B.Context and F.Context methods always returned nil, rather than a context.Context value. This change adds a working implementation of B.Context and F.Context. For #36532 Fixes #70866 Change-Id: I8a44e6649fb658e4f641ffb7efd08b4374f578ef Reviewed-on: https://go-review.googlesource.com/c/go/+/637236 LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Damien Neil --- .../go/testdata/script/test_fuzz_context.txt | 47 ++++++++++++++++++ src/testing/benchmark.go | 4 ++ src/testing/benchmark_test.go | 30 ++++++++++++ src/testing/fuzz.go | 49 ++++++++++++------- src/testing/testing.go | 4 +- 5 files changed, 113 insertions(+), 21 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_fuzz_context.txt diff --git a/src/cmd/go/testdata/script/test_fuzz_context.txt b/src/cmd/go/testdata/script/test_fuzz_context.txt new file mode 100644 index 00000000000000..a830684708e65b --- /dev/null +++ b/src/cmd/go/testdata/script/test_fuzz_context.txt @@ -0,0 +1,47 @@ +[!fuzz] skip +[short] skip +env GOCACHE=$WORK/cache + +# Test fuzz.Context. +go test -vet=off context_fuzz_test.go +stdout ^ok +! stdout FAIL + +go test -vet=off -fuzz=Fuzz -fuzztime=1x context_fuzz_test.go +stdout ok +! stdout FAIL + +-- context_fuzz_test.go -- +package context_fuzz + +import ( + "context" + "errors" + "testing" +) + +func Fuzz(f *testing.F) { + ctx := f.Context() + if err := ctx.Err(); err != nil { + f.Fatalf("expected non-canceled context, got %v", err) + } + + f.Fuzz(func(t *testing.T, data []byte) { + innerCtx := t.Context() + if err := innerCtx.Err(); err != nil { + t.Fatalf("expected inner test to not inherit canceled context, got %v", err) + } + + t.Cleanup(func() { + if !errors.Is(innerCtx.Err(), context.Canceled) { + t.Fatal("expected context of inner test to be canceled after its fuzz function finished") + } + }) + }) + + f.Cleanup(func() { + if !errors.Is(ctx.Err(), context.Canceled) { + f.Fatal("expected context canceled before cleanup") + } + }) +} diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index 2660c9bba06f3d..3a7da9e54012b7 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -5,6 +5,7 @@ package testing import ( + "context" "flag" "fmt" "internal/sysinfo" @@ -181,6 +182,7 @@ func (b *B) ReportAllocs() { func (b *B) runN(n int) { benchmarkLock.Lock() defer benchmarkLock.Unlock() + ctx, cancelCtx := context.WithCancel(context.Background()) defer func() { b.runCleanup(normalPanic) b.checkRaces() @@ -191,6 +193,8 @@ func (b *B) runN(n int) { b.resetRaces() b.N = n b.loopN = 0 + b.ctx = ctx + b.cancelCtx = cancelCtx b.parallelism = 1 b.ResetTimer() diff --git a/src/testing/benchmark_test.go b/src/testing/benchmark_test.go index a195e4c5766813..e2dd24c839d694 100644 --- a/src/testing/benchmark_test.go +++ b/src/testing/benchmark_test.go @@ -7,6 +7,8 @@ package testing_test import ( "bytes" "cmp" + "context" + "errors" "runtime" "slices" "strings" @@ -127,6 +129,34 @@ func TestRunParallelSkipNow(t *testing.T) { }) } +func TestBenchmarkContext(t *testing.T) { + testing.Benchmark(func(b *testing.B) { + ctx := b.Context() + if err := ctx.Err(); err != nil { + b.Fatalf("expected non-canceled context, got %v", err) + } + + var innerCtx context.Context + b.Run("inner", func(b *testing.B) { + innerCtx = b.Context() + if err := innerCtx.Err(); err != nil { + b.Fatalf("expected inner benchmark to not inherit canceled context, got %v", err) + } + }) + b.Run("inner2", func(b *testing.B) { + if !errors.Is(innerCtx.Err(), context.Canceled) { + t.Fatal("expected context of sibling benchmark to be canceled after its test function finished") + } + }) + + t.Cleanup(func() { + if !errors.Is(ctx.Err(), context.Canceled) { + t.Fatal("expected context canceled before cleanup") + } + }) + }) +} + func ExampleB_RunParallel() { // Parallel benchmark for text/template.Template.Execute on a single object. testing.Benchmark(func(b *testing.B) { diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go index b41a07f88e0863..dceb786ae2829e 100644 --- a/src/testing/fuzz.go +++ b/src/testing/fuzz.go @@ -5,6 +5,7 @@ package testing import ( + "context" "errors" "flag" "fmt" @@ -293,6 +294,8 @@ func (f *F) Fuzz(ff any) { f.tstate.match.clearSubNames() } + ctx, cancelCtx := context.WithCancel(f.ctx) + // Record the stack trace at the point of this call so that if the subtest // function - which runs in a separate stack - is marked as a helper, we can // continue walking the stack into the parent test. @@ -300,13 +303,15 @@ func (f *F) Fuzz(ff any) { n := runtime.Callers(2, pc[:]) t := &T{ common: common{ - barrier: make(chan bool), - signal: make(chan bool), - name: testName, - parent: &f.common, - level: f.level + 1, - creator: pc[:n], - chatty: f.chatty, + barrier: make(chan bool), + signal: make(chan bool), + name: testName, + parent: &f.common, + level: f.level + 1, + creator: pc[:n], + chatty: f.chatty, + ctx: ctx, + cancelCtx: cancelCtx, }, tstate: f.tstate, } @@ -508,14 +513,17 @@ func runFuzzTests(deps testDeps, fuzzTests []InternalFuzzTarget, deadline time.T continue } } + ctx, cancelCtx := context.WithCancel(context.Background()) f := &F{ common: common{ - signal: make(chan bool), - barrier: make(chan bool), - name: testName, - parent: &root, - level: root.level + 1, - chatty: root.chatty, + signal: make(chan bool), + barrier: make(chan bool), + name: testName, + parent: &root, + level: root.level + 1, + chatty: root.chatty, + ctx: ctx, + cancelCtx: cancelCtx, }, tstate: tstate, fstate: fstate, @@ -590,14 +598,17 @@ func runFuzzing(deps testDeps, fuzzTests []InternalFuzzTarget) (ok bool) { return false } + ctx, cancelCtx := context.WithCancel(context.Background()) f := &F{ common: common{ - signal: make(chan bool), - barrier: nil, // T.Parallel has no effect when fuzzing. - name: testName, - parent: &root, - level: root.level + 1, - chatty: root.chatty, + signal: make(chan bool), + barrier: nil, // T.Parallel has no effect when fuzzing. + name: testName, + parent: &root, + level: root.level + 1, + chatty: root.chatty, + ctx: ctx, + cancelCtx: cancelCtx, }, fstate: fstate, tstate: tstate, diff --git a/src/testing/testing.go b/src/testing/testing.go index 8b4bdfbc39828e..be6391b0ab15ce 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -1385,10 +1385,10 @@ func (c *common) Chdir(dir string) { } // Context returns a context that is canceled just before -// [T.Cleanup]-registered functions are called. +// Cleanup-registered functions are called. // // Cleanup functions can wait for any resources -// that shut down on Context.Done before the test completes. +// that shut down on Context.Done before the test or benchmark completes. func (c *common) Context() context.Context { c.checkFuzzFn("Context") return c.ctx From 8ff4cee56491eeb3ce146974109cb4893ef5cbd6 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 17 Dec 2024 19:57:54 +0100 Subject: [PATCH 048/397] cmd/go,crypto: reject using Go+BoringCrypto and fips140 together The combination is untested and nonsensical. Both are solutions to the same problem. For #69536 Change-Id: I95cc3baaf03b64ce08096e304e311a29e9577385 Reviewed-on: https://go-review.googlesource.com/c/go/+/637177 LUCI-TryBot-Result: Go LUCI Reviewed-by: Russ Cox Auto-Submit: Filippo Valsorda Reviewed-by: David Chase --- src/cmd/go/internal/fips140/fips140.go | 4 ++++ src/cmd/go/testdata/script/env_changed.txt | 3 +++ src/cmd/go/testdata/script/fips.txt | 3 +++ src/cmd/go/testdata/script/fipssnap.txt | 3 +++ src/crypto/internal/boring/boring.go | 7 +++++++ src/crypto/internal/fips140test/check_test.go | 5 +++++ 6 files changed, 25 insertions(+) diff --git a/src/cmd/go/internal/fips140/fips140.go b/src/cmd/go/internal/fips140/fips140.go index 7c04a94dd1fea3..1dad8e0bbf96e8 100644 --- a/src/cmd/go/internal/fips140/fips140.go +++ b/src/cmd/go/internal/fips140/fips140.go @@ -119,6 +119,10 @@ func Init() { if Snapshot() { fsys.Bind(Dir(), filepath.Join(cfg.GOROOT, "src/crypto/internal/fips140")) } + + if cfg.Experiment.BoringCrypto && Enabled() { + base.Fatalf("go: cannot use GOFIPS140 with GOEXPERIMENT=boringcrypto") + } } var initDone bool diff --git a/src/cmd/go/testdata/script/env_changed.txt b/src/cmd/go/testdata/script/env_changed.txt index f57f69bfd78ca0..10db7654070615 100644 --- a/src/cmd/go/testdata/script/env_changed.txt +++ b/src/cmd/go/testdata/script/env_changed.txt @@ -1,5 +1,8 @@ # Test query for non-defaults in the env +# Go+BoringCrypto conflicts with GOFIPS140. +[GOEXPERIMENT:boringcrypto] skip + env GOROOT=./a env GOTOOLCHAIN=local env GOSUMDB=nodefault diff --git a/src/cmd/go/testdata/script/fips.txt b/src/cmd/go/testdata/script/fips.txt index fd791d39903e88..fe096ea0c3a2f0 100644 --- a/src/cmd/go/testdata/script/fips.txt +++ b/src/cmd/go/testdata/script/fips.txt @@ -1,3 +1,6 @@ +# Go+BoringCrypto conflicts with GOFIPS140. +[GOEXPERIMENT:boringcrypto] skip + # list with GOFIPS140=off env GOFIPS140=off go list -f '{{.DefaultGODEBUG}}' diff --git a/src/cmd/go/testdata/script/fipssnap.txt b/src/cmd/go/testdata/script/fipssnap.txt index 17a9d647a1845b..0bf46c56e292a4 100644 --- a/src/cmd/go/testdata/script/fipssnap.txt +++ b/src/cmd/go/testdata/script/fipssnap.txt @@ -7,6 +7,9 @@ env alias=inprocess skip 'no snapshots yet' env GOFIPS140=$snap +# Go+BoringCrypto conflicts with GOFIPS140. +[GOEXPERIMENT:boringcrypto] skip + # default GODEBUG includes fips140=on go list -f '{{.DefaultGODEBUG}}' stdout fips140=on diff --git a/src/crypto/internal/boring/boring.go b/src/crypto/internal/boring/boring.go index 90cf1edb75bbad..6dfc6ed5f50207 100644 --- a/src/crypto/internal/boring/boring.go +++ b/src/crypto/internal/boring/boring.go @@ -16,6 +16,7 @@ import "C" import ( "crypto/internal/boring/sig" _ "crypto/internal/boring/syso" + "crypto/internal/fips140" "internal/stringslite" "math/bits" "unsafe" @@ -31,6 +32,12 @@ func init() { sig.BoringCrypto() } +func init() { + if fips140.Enabled { + panic("boringcrypto: cannot use GODEBUG=fips140 with GOEXPERIMENT=boringcrypto") + } +} + // Unreachable marks code that should be unreachable // when BoringCrypto is in use. It panics. func Unreachable() { diff --git a/src/crypto/internal/fips140test/check_test.go b/src/crypto/internal/fips140test/check_test.go index b156de2cbbab6c..cf42dbfa7823f9 100644 --- a/src/crypto/internal/fips140test/check_test.go +++ b/src/crypto/internal/fips140test/check_test.go @@ -5,6 +5,7 @@ package fipstest import ( + "crypto/internal/boring" . "crypto/internal/fips140/check" "crypto/internal/fips140/check/checktest" "fmt" @@ -22,6 +23,10 @@ import ( const enableFIPSTest = true func TestFIPSCheckVerify(t *testing.T) { + if boring.Enabled { + t.Skip("not testing fips140 with boringcrypto enabled") + } + if Verified { t.Logf("verified") return From 10ca5ba4ffecb58028e301904f943a66110966ba Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 17 Dec 2024 20:39:24 +0100 Subject: [PATCH 049/397] crypto/pbkdf2: update RFC reference in package doc Now that it's published, we don't need to explain how we diverge from the old one. Change-Id: If2c22e89dd1b9fc531a363b5fb7b1eb5720eb84e Reviewed-on: https://go-review.googlesource.com/c/go/+/637215 Auto-Submit: Filippo Valsorda Reviewed-by: Daniel McCarney Reviewed-by: David Chase Reviewed-by: Roland Shoemaker LUCI-TryBot-Result: Go LUCI --- src/crypto/pbkdf2/pbkdf2.go | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/crypto/pbkdf2/pbkdf2.go b/src/crypto/pbkdf2/pbkdf2.go index 0fdd9e822d40a5..d40daab5e5b879 100644 --- a/src/crypto/pbkdf2/pbkdf2.go +++ b/src/crypto/pbkdf2/pbkdf2.go @@ -2,20 +2,12 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -/* -Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC -2898 / PKCS #5 v2.0. - -A key derivation function is useful when encrypting data based on a password -or any other not-fully-random data. It uses a pseudorandom function to derive -a secure encryption key based on the password. - -While v2.0 of the standard defines only one pseudorandom function to use, -HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved -Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To -choose, you can pass the `New` functions from the different SHA packages to -pbkdf2.Key. -*/ +// Package pbkdf2 implements the key derivation function PBKDF2 as defined in +// RFC 8018 (PKCS #5 v2.1). +// +// A key derivation function is useful when encrypting data based on a password +// or any other not-fully-random data. It uses a pseudorandom function to derive +// a secure encryption key based on the password. package pbkdf2 import ( From 6aa46eb75005c87ab4d44d989e1688362991c731 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 17 Dec 2024 20:47:17 +0100 Subject: [PATCH 050/397] crypto/tls: normalize spelling of "ClientHello" in comments Change-Id: I2b62fb37ae390c42682354eaa2a9d03159563b6d Reviewed-on: https://go-review.googlesource.com/c/go/+/637179 Reviewed-by: Daniel McCarney Reviewed-by: Roland Shoemaker LUCI-TryBot-Result: Go LUCI Auto-Submit: Filippo Valsorda Reviewed-by: David Chase --- src/crypto/tls/common.go | 4 ++-- src/crypto/tls/handshake_client.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index f98d24b879b889..d6942d2ef14a27 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -456,7 +456,7 @@ type ClientHelloInfo struct { SupportedVersions []uint16 // Extensions lists the IDs of the extensions presented by the client - // in the client hello. + // in the ClientHello. Extensions []uint16 // Conn is the underlying net.Conn for the connection. Do not read @@ -821,7 +821,7 @@ type Config struct { // EncryptedClientHelloRejectionVerify, if not nil, is called when ECH is // rejected by the remote server, in order to verify the ECH provider - // certificate in the outer Client Hello. If it returns a non-nil error, the + // certificate in the outer ClientHello. If it returns a non-nil error, the // handshake is aborted and that error results. // // On the server side this field is not used. diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index ecc62ff2edefc0..3bf703e4b93b22 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -944,7 +944,7 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) { } // checkALPN ensure that the server's choice of ALPN protocol is compatible with -// the protocols that we advertised in the Client Hello. +// the protocols that we advertised in the ClientHello. func checkALPN(clientProtos []string, serverProto string, quic bool) error { if serverProto == "" { if quic && len(clientProtos) > 0 { From f4e3ec3dbe3b8e04a058d266adf8e048bab563f2 Mon Sep 17 00:00:00 2001 From: Mauri de Souza Meneguzzo Date: Wed, 18 Dec 2024 16:19:24 +0000 Subject: [PATCH 051/397] crypto/ecdsa: fix condition for fips140=only check Fixes #70894 Change-Id: I78c9f2e46006ffc5f1d2886218f8aaaf3f1b59eb GitHub-Last-Rev: 11f0b452f57aacc40139eab557a8bed1386ad07b GitHub-Pull-Request: golang/go#70904 Reviewed-on: https://go-review.googlesource.com/c/go/+/637455 Reviewed-by: Filippo Valsorda LUCI-TryBot-Result: Go LUCI Reviewed-by: Carlos Amedee Reviewed-by: David Chase --- src/crypto/ecdsa/ecdsa.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go index 77727aaf96befb..0f9749975ffba9 100644 --- a/src/crypto/ecdsa/ecdsa.go +++ b/src/crypto/ecdsa/ecdsa.go @@ -183,7 +183,7 @@ func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { } func generateFIPS[P ecdsa.Point[P]](curve elliptic.Curve, c *ecdsa.Curve[P], rand io.Reader) (*PrivateKey, error) { - if fips140only.Enabled && fips140only.ApprovedRandomReader(rand) { + if fips140only.Enabled && !fips140only.ApprovedRandomReader(rand) { return nil, errors.New("crypto/ecdsa: only crypto/rand.Reader is allowed in FIPS 140-only mode") } privateKey, err := ecdsa.GenerateKey(c, rand) From 87dbfb9fa73c335fd0014445bd34135365c21b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Bohusl=C3=A1vek?= Date: Wed, 18 Dec 2024 13:32:37 +0100 Subject: [PATCH 052/397] weak: improve grammar in doc comments Change-Id: I577b8a6bf2b7d899cc7ff7211c73549c90db9d94 Reviewed-on: https://go-review.googlesource.com/c/go/+/637355 Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor Reviewed-by: Michael Knyszek --- src/weak/pointer.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/weak/pointer.go b/src/weak/pointer.go index fb10bc2d699ab3..d8be4093492149 100644 --- a/src/weak/pointer.go +++ b/src/weak/pointer.go @@ -13,9 +13,9 @@ import ( // Pointer is a weak pointer to a value of type T. // // Just like regular pointers, Pointer may reference any part of an -// object, such as the field of a struct or an element of an array. +// object, such as a field of a struct or an element of an array. // Objects that are only pointed to by weak pointers are not considered -// reachable and once the object becomes unreachable [Pointer.Value] +// reachable, and once the object becomes unreachable, [Pointer.Value] // may return nil. // // The primary use-cases for weak pointers are for implementing caches, @@ -23,19 +23,19 @@ import ( // the lifetimes of separate values (for example, through a map with weak // keys). // -// Two Pointer values always compare equal if the pointers that they were -// created from compare equal. This property is retained even after the +// Two Pointer values always compare equal if the pointers from which they were +// created compare equal. This property is retained even after the // object referenced by the pointer used to create a weak reference is // reclaimed. -// If multiple weak pointers are made to different offsets within same object +// If multiple weak pointers are made to different offsets within the same object // (for example, pointers to different fields of the same struct), those pointers // will not compare equal. // If a weak pointer is created from an object that becomes unreachable, but is // then resurrected due to a finalizer, that weak pointer will not compare equal -// with weak pointers created after resurrection. +// with weak pointers created after the resurrection. // // Calling [Make] with a nil pointer returns a weak pointer whose [Pointer.Value] -// always returns nil. The zero value of a Pointer behaves as if it was created +// always returns nil. The zero value of a Pointer behaves as if it were created // by passing nil to [Make] and compares equal with such pointers. // // [Pointer.Value] is not guaranteed to eventually return nil. From 4f0561f9d354233787de7aa9eff8119a2d4cd5c6 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 18 Dec 2024 11:28:18 -0500 Subject: [PATCH 053/397] cmd/dist: skip fips140test in exe mode on Android Android does not support non-PIE linking. Skip the test. Change-Id: I53071538c82f1e1f96eed1a2619f92eacd18d263 Reviewed-on: https://go-review.googlesource.com/c/go/+/637495 Run-TryBot: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov TryBot-Result: Gopher Robot --- src/cmd/dist/test.go | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 5a981f8bc147de..06bd01bc5bb995 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -876,16 +876,18 @@ func (t *tester) registerTests() { } if t.extLink() && !t.compileOnly { - t.registerTest("external linking, -buildmode=exe", - &goTest{ - variant: "exe_external", - timeout: 60 * time.Second, - buildmode: "exe", - ldflags: "-linkmode=external", - env: []string{"CGO_ENABLED=1"}, - pkg: "crypto/internal/fips140test", - runTests: "TestFIPSCheck", - }) + if goos != "android" { // Android does not support non-PIE linking + t.registerTest("external linking, -buildmode=exe", + &goTest{ + variant: "exe_external", + timeout: 60 * time.Second, + buildmode: "exe", + ldflags: "-linkmode=external", + env: []string{"CGO_ENABLED=1"}, + pkg: "crypto/internal/fips140test", + runTests: "TestFIPSCheck", + }) + } if t.externalLinkPIE() && !disablePIE { t.registerTest("external linking, -buildmode=pie", &goTest{ From cb72406c36e5c39c049fd150d65be67372ba60e2 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 18 Dec 2024 15:42:48 -0500 Subject: [PATCH 054/397] cmd/go: fix two-step toolchain upgrade through go install, GOTOOLCHAIN If we do one upgrade because of a go install target's go.mod file, we still might need a second upgrade to implement the GOTOOLCHAIN minimum. Instead of allowing a two-step switch (which we were cutting off anyway), skip the first step and go straight to the GOTOOLCHAIN min upgrade. Fixes #69051. Change-Id: I16f060f473574d8b8f84c55fae2fd0cdabc8aa19 Reviewed-on: https://go-review.googlesource.com/c/go/+/637496 Reviewed-by: Michael Matloob LUCI-TryBot-Result: Go LUCI --- src/cmd/go/internal/toolchain/select.go | 10 +++++++--- src/cmd/go/testdata/script/gotoolchain_local.txt | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go index cbdd7a2418e1f0..aeab59519c7e6d 100644 --- a/src/cmd/go/internal/toolchain/select.go +++ b/src/cmd/go/internal/toolchain/select.go @@ -169,7 +169,7 @@ func Select() { } gotoolchain = minToolchain - if (mode == "auto" || mode == "path") && !goInstallVersion() { + if (mode == "auto" || mode == "path") && !goInstallVersion(minVers) { // Read go.mod to find new minimum and suggested toolchain. file, goVers, toolchain := modGoToolchain() gover.Startup.AutoFile = file @@ -549,7 +549,7 @@ func modGoToolchain() (file, goVers, toolchain string) { // goInstallVersion reports whether the command line is go install m@v or go run m@v. // If so, Select must not read the go.mod or go.work file in "auto" or "path" mode. -func goInstallVersion() bool { +func goInstallVersion(minVers string) bool { // Note: We assume there are no flags between 'go' and 'install' or 'run'. // During testing there are some debugging flags that are accepted // in that position, but in production go binaries there are not. @@ -708,7 +708,11 @@ func goInstallVersion() bool { if errors.Is(err, gover.ErrTooNew) { // Run early switch, same one go install or go run would eventually do, // if it understood all the command-line flags. - SwitchOrFatal(ctx, err) + var s Switcher + s.Error(err) + if s.TooNew != nil && gover.Compare(s.TooNew.GoVersion, minVers) > 0 { + SwitchOrFatal(ctx, err) + } } return true // pkg@version found diff --git a/src/cmd/go/testdata/script/gotoolchain_local.txt b/src/cmd/go/testdata/script/gotoolchain_local.txt index db7e082db96749..8bece6ebd8439b 100644 --- a/src/cmd/go/testdata/script/gotoolchain_local.txt +++ b/src/cmd/go/testdata/script/gotoolchain_local.txt @@ -197,6 +197,17 @@ go mod edit -go=1.501 -toolchain=none go version stdout go1.501 +# avoid two-step switch, first from install target requirement, then from GOTOOLCHAIN min +# instead, just jump directly to GOTOOLCHAIN min +env TESTGO_VERSION=go1.2.3 +env GODEBUG=toolchaintrace=1 +env GOTOOLCHAIN=go1.23.0+auto +! go install rsc.io/fortune/nonexist@v0.0.1 +! stderr 'switching to go1.22.9' +stderr 'using go1.23.0' +env GODEBUG= +env GOTOOLCHAIN=auto + # go install m@v and go run m@v should ignore go.mod and use m@v env TESTGO_VERSION=go1.2.3 go mod edit -go=1.999 -toolchain=go1.998 From 7b6c94dd037b5d78afca70975109294d7439517c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 17 Dec 2024 10:40:41 -0500 Subject: [PATCH 055/397] cmd/go: drop fips140 build ID hacks We were trying to keep all binaries stale in fips140 mode so that every build would write and leave behind a fips.o in the work directory for use by validating labs. That breaks various staleness checks, including the one in cmd/dist during GOFIPS140=latest ./make.bash. Revert the fips140 hack. Validating labs will still be able to find the fips.o when building against a clean cache. Add the default godebug to the link hash though, so that it is clear that GOFIPS140=latest and GOFIPS140=off binaries have different hashes. (The only effect is the default GODEBUG setting.) They already had different hashes, because the default GODEBUG ends up in p.Internal.BuildInfo, and that gets hashed in a "modinfo" line, but better to be explicit. Fixes #70873. Change-Id: I49a38c180208098c2b6720facef48f4e96d44c54 Reviewed-on: https://go-review.googlesource.com/c/go/+/637116 Reviewed-by: Michael Matloob Reviewed-by: Filippo Valsorda Reviewed-by: Sam Thanawalla LUCI-TryBot-Result: Go LUCI --- src/cmd/go/internal/fips140/fips140.go | 10 ++-------- src/cmd/go/internal/work/buildid.go | 16 +--------------- src/cmd/go/internal/work/exec.go | 1 + src/cmd/go/testdata/script/fips.txt | 6 ++---- src/cmd/go/testdata/script/fipssnap.txt | 4 ++-- 5 files changed, 8 insertions(+), 29 deletions(-) diff --git a/src/cmd/go/internal/fips140/fips140.go b/src/cmd/go/internal/fips140/fips140.go index 1dad8e0bbf96e8..328e06088e3d47 100644 --- a/src/cmd/go/internal/fips140/fips140.go +++ b/src/cmd/go/internal/fips140/fips140.go @@ -40,14 +40,8 @@ // // GOFIPS140=latest go build -work my/binary // -// will leave fips.o behind in $WORK/b001. Auditors like to be able to -// see that file. Accordingly, when [Enabled] returns true, -// [cmd/go/internal/work.Builder.useCache] arranges never to cache linker -// output, so that the link step always runs, and fips.o is always left -// behind in the link step. If this proves too slow, we could always -// cache fips.o as an extra link output and then restore it when -work is -// set, but we went a very long time never caching link steps at all, so -// not caching them in FIPS mode seems perfectly fine. +// will leave fips.o behind in $WORK/b001 +// (unless the build result is cached, of course). // // When GOFIPS140 is set to something besides off and latest, [Snapshot] // returns true, indicating that the build should replace the latest copy diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 55b3190300ff60..cab722c28a8396 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -15,7 +15,6 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cache" "cmd/go/internal/cfg" - "cmd/go/internal/fips140" "cmd/go/internal/fsys" "cmd/go/internal/str" "cmd/internal/buildid" @@ -447,19 +446,6 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string, a.buildID = actionID + buildIDSeparator + mainpkg.buildID + buildIDSeparator + contentID } - // In FIPS mode, we disable any link caching, - // so that we always leave fips.o in $WORK/b001. - // This makes sure that labs validating the FIPS - // implementation can always run 'go build -work' - // and then find fips.o in $WORK/b001/fips.o. - // We could instead also save the fips.o and restore it - // to $WORK/b001 from the cache, - // but we went years without caching binaries anyway, - // so not caching them for FIPS will be fine, at least to start. - if a.Mode == "link" && fips140.Enabled() && a.Package != nil && !strings.HasSuffix(a.Package.ImportPath, ".test") { - return false - } - // If user requested -a, we force a rebuild, so don't use the cache. if cfg.BuildA { if p := a.Package; p != nil && !p.Stale { @@ -519,7 +505,7 @@ func (b *Builder) useCache(a *Action, actionHash cache.ActionID, target string, oldBuildID := a.buildID a.buildID = id[1] + buildIDSeparator + id[2] linkID := buildid.HashToString(b.linkActionID(a.triggers[0])) - if id[0] == linkID && !fips140.Enabled() { + if id[0] == linkID { // Best effort attempt to display output from the compile and link steps. // If it doesn't work, it doesn't work: reusing the cached binary is more // important than reprinting diagnostic information. diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 2538fae52f2d8e..7b073165d5fe25 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -1374,6 +1374,7 @@ func (b *Builder) linkActionID(a *Action) cache.ActionID { fmt.Fprintf(h, "buildmode %s goos %s goarch %s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch) fmt.Fprintf(h, "import %q\n", p.ImportPath) fmt.Fprintf(h, "omitdebug %v standard %v local %v prefix %q\n", p.Internal.OmitDebug, p.Standard, p.Internal.Local, p.Internal.LocalPrefix) + fmt.Fprintf(h, "defaultgodebug %q\n", p.DefaultGODEBUG) if cfg.BuildTrimpath { fmt.Fprintln(h, "trimpath") } diff --git a/src/cmd/go/testdata/script/fips.txt b/src/cmd/go/testdata/script/fips.txt index fe096ea0c3a2f0..374902eb702a2e 100644 --- a/src/cmd/go/testdata/script/fips.txt +++ b/src/cmd/go/testdata/script/fips.txt @@ -20,12 +20,12 @@ go build -x -o x.exe go build -x -o x.exe ! stderr link -# build with GOFIPS140=latest is NOT cached (need fipso) +# build with GOFIPS140=latest is cached too env GOFIPS140=latest go build -x -o x.exe stderr link.*-fipso go build -x -o x.exe -stderr link.*-fipso +! stderr link.*-fipso # build test with GOFIPS140=off is cached env GOFIPS140=off @@ -41,8 +41,6 @@ stderr link.*-fipso go test -x -c ! stderr link - - -- go.mod -- module m -- x.go -- diff --git a/src/cmd/go/testdata/script/fipssnap.txt b/src/cmd/go/testdata/script/fipssnap.txt index 0bf46c56e292a4..465f304c46c126 100644 --- a/src/cmd/go/testdata/script/fipssnap.txt +++ b/src/cmd/go/testdata/script/fipssnap.txt @@ -47,11 +47,11 @@ stdout crypto/internal/fips140/$snap/sha256 [short] skip -# build with GOFIPS140=snap is NOT cached (need fipso) +# build with GOFIPS140=snap is cached go build -x -o x.exe stderr link.*-fipso go build -x -o x.exe -stderr link.*-fipso +! stderr link.*-fipso # build test with GOFIPS140=snap is cached go test -x -c From e63eb98e98709a68bf7781a34a3297b72521826e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 19 Dec 2024 13:35:34 -0500 Subject: [PATCH 056/397] net/http: fix nil panic in test Observed on a builder in an unrelated CL. https://logs.chromium.org/logs/golang/buildbucket/cr-buildbucket/8728107031663629713/+/u/step/11/log/2 goroutine 27937 gp=0xc00000f6c0 m=20 mp=0xc000085008 [running]: panic({0x560ac0?, 0xa1f400?}) C:/b/s/w/ir/x/w/goroot/src/runtime/panic.go:806 +0x168 fp=0xc00043fac8 sp=0xc00043fa18 pc=0xa5f88 testing.tRunner.func1.2({0x560ac0, 0xa1f400}) C:/b/s/w/ir/x/w/goroot/src/testing/testing.go:1734 +0x219 fp=0xc00043fb78 sp=0xc00043fac8 pc=0x1537f9 testing.tRunner.func1() C:/b/s/w/ir/x/w/goroot/src/testing/testing.go:1737 +0x359 fp=0xc00043fce0 sp=0xc00043fb78 pc=0x153259 panic({0x560ac0?, 0xa1f400?}) C:/b/s/w/ir/x/w/goroot/src/runtime/panic.go:787 +0x132 fp=0xc00043fd90 sp=0xc00043fce0 pc=0xa5f52 runtime.panicmem(...) C:/b/s/w/ir/x/w/goroot/src/runtime/panic.go:262 runtime.sigpanic() C:/b/s/w/ir/x/w/goroot/src/runtime/signal_windows.go:401 +0x198 fp=0xc00043fdd8 sp=0xc00043fd90 pc=0x87938 net/http_test.testTransportIdleConnTimeout.func3(...) C:/b/s/w/ir/x/w/goroot/src/net/http/transport_test.go:5503 net/http_test.testTransportIdleConnTimeout(0xc000e83340, {0x5ec863, 0x2}) C:/b/s/w/ir/x/w/goroot/src/net/http/transport_test.go:5522 +0x4c1 fp=0xc00043ff20 sp=0xc00043fdd8 pc=0x47a841 net/http_test.run[...].func1() C:/b/s/w/ir/x/w/goroot/src/net/http/clientserver_test.go:93 +0xfe fp=0xc00043ff70 sp=0xc00043ff20 pc=0x49a21e testing.tRunner(0xc000e83340, 0xc0004687b0) C:/b/s/w/ir/x/w/goroot/src/testing/testing.go:1792 +0xcb fp=0xc00043ffc0 sp=0xc00043ff70 pc=0x152e4b testing.(*T).Run.gowrap1() C:/b/s/w/ir/x/w/goroot/src/testing/testing.go:1851 +0x25 fp=0xc00043ffe0 sp=0xc00043ffc0 pc=0x153e65 runtime.goexit({}) C:/b/s/w/ir/x/w/goroot/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc00043ffe8 sp=0xc00043ffe0 pc=0xadfe1 created by testing.(*T).Run in goroutine 27899 C:/b/s/w/ir/x/w/goroot/src/testing/testing.go:1851 +0x3f6 Change-Id: I3f8bd7c7863b5031ff43d4837dfe11d26ac75652 Reviewed-on: https://go-review.googlesource.com/c/go/+/637897 Reviewed-by: Damien Neil Auto-Submit: Russ Cox LUCI-TryBot-Result: Go LUCI --- src/net/http/transport_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 2963255b874378..a454db5e034ff0 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -5500,7 +5500,9 @@ timeoutLoop: return false } } - res.Body.Close() + if err == nil { + res.Body.Close() + } conns := idleConns() if len(conns) != 1 { if len(conns) == 0 { From 45f49139f5c0c4921239b7f0865c4041e663b1d0 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 19 Dec 2024 20:58:19 -0500 Subject: [PATCH 057/397] runtime: test trap panic parsing in TestTracebackSystem This mirrors https://go.dev/cl/637755, as x/telemetry is now aware of sigpanic preceding trap frames. For #70637. Change-Id: I13a775f25e89047702d4f2d463ce3210bcf192d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/638015 Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/runtime/crash_test.go | 7 +- src/runtime/traceback_system_test.go | 249 +++++++++++++++++++++------ 2 files changed, 202 insertions(+), 54 deletions(-) diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 268ddb59c9e4c1..236c32ea34f7de 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -32,8 +32,11 @@ const entrypointVar = "RUNTIME_TEST_ENTRYPOINT" func TestMain(m *testing.M) { switch entrypoint := os.Getenv(entrypointVar); entrypoint { - case "crash": - crash() + case "panic": + crashViaPanic() + panic("unreachable") + case "trap": + crashViaTrap() panic("unreachable") default: log.Fatalf("invalid %s: %q", entrypointVar, entrypoint) diff --git a/src/runtime/traceback_system_test.go b/src/runtime/traceback_system_test.go index ece58e806d51c1..af20f54a0946fc 100644 --- a/src/runtime/traceback_system_test.go +++ b/src/runtime/traceback_system_test.go @@ -23,8 +23,8 @@ import ( ) // This is the entrypoint of the child process used by -// TestTracebackSystem. It prints a crash report to stdout. -func crash() { +// TestTracebackSystem/panic. It prints a crash report to stdout. +func crashViaPanic() { // Ensure that we get pc=0x%x values in the traceback. debug.SetTraceback("system") writeSentinel(os.Stdout) @@ -37,6 +37,21 @@ func crash() { select {} } +// This is the entrypoint of the child process used by +// TestTracebackSystem/trap. It prints a crash report to stdout. +func crashViaTrap() { + // Ensure that we get pc=0x%x values in the traceback. + debug.SetTraceback("system") + writeSentinel(os.Stdout) + debug.SetCrashOutput(os.Stdout, debug.CrashOptions{}) + + go func() { + // This call is typically inlined. + trap1() + }() + select {} +} + func child1() { child2() } @@ -85,6 +100,20 @@ func child7() { panic("oops") } +func trap1() { + trap2() +} + +var sinkPtr *int + +func trap2() { + trap3(sinkPtr) +} + +func trap3(i *int) { + *i = 42 +} + // TestTracebackSystem tests that the syntax of crash reports produced // by GOTRACEBACK=system (see traceback2) contains a complete, // parseable list of program counters for the running goroutine that @@ -100,46 +129,75 @@ func TestTracebackSystem(t *testing.T) { t.Skip("Can't read source code for this file on Android") } - // Fork+exec the crashing process. - exe, err := os.Executable() - if err != nil { - t.Fatal(err) - } - cmd := testenv.Command(t, exe) - cmd.Env = append(cmd.Environ(), entrypointVar+"=crash") - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - cmd.Run() // expected to crash - t.Logf("stderr:\n%s\nstdout: %s\n", stderr.Bytes(), stdout.Bytes()) - crash := stdout.String() - - // If the only line is the sentinel, it wasn't a crash. - if strings.Count(crash, "\n") < 2 { - t.Fatalf("child process did not produce a crash report") + tests := []struct{ + name string + want string + }{ + { + name: "panic", + want: `redacted.go:0: runtime.gopanic +traceback_system_test.go:100: runtime_test.child7: panic("oops") +traceback_system_test.go:83: runtime_test.child6: child7() // appears in stack trace +traceback_system_test.go:74: runtime_test.child5: child6() // appears in stack trace +traceback_system_test.go:68: runtime_test.child4: child5() +traceback_system_test.go:64: runtime_test.child3: child4() +traceback_system_test.go:60: runtime_test.child2: child3() +traceback_system_test.go:56: runtime_test.child1: child2() +traceback_system_test.go:35: runtime_test.crashViaPanic.func1: child1() +redacted.go:0: runtime.goexit +`, + }, + { + // Test panic via trap. x/telemetry is aware that trap + // PCs follow runtime.sigpanic and need to be + // incremented to offset the decrement done by + // CallersFrames. + name: "trap", + want: `redacted.go:0: runtime.gopanic +redacted.go:0: runtime.panicmem +redacted.go:0: runtime.sigpanic +traceback_system_test.go:114: runtime_test.trap3: *i = 42 +traceback_system_test.go:110: runtime_test.trap2: trap3(sinkPtr) +traceback_system_test.go:104: runtime_test.trap1: trap2() +traceback_system_test.go:50: runtime_test.crashViaTrap.func1: trap1() +redacted.go:0: runtime.goexit +`, + }, } - // Parse the PCs out of the child's crash report. - pcs, err := parseStackPCs(crash) - if err != nil { - t.Fatal(err) - } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + // Fork+exec the crashing process. + exe, err := os.Executable() + if err != nil { + t.Fatal(err) + } + cmd := testenv.Command(t, exe) + cmd.Env = append(cmd.Environ(), entrypointVar+"="+tc.name) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + cmd.Run() // expected to crash + t.Logf("stderr:\n%s\nstdout: %s\n", stderr.Bytes(), stdout.Bytes()) + crash := stdout.String() + + // If the only line is the sentinel, it wasn't a crash. + if strings.Count(crash, "\n") < 2 { + t.Fatalf("child process did not produce a crash report") + } - // Unwind the stack using this executable's symbol table. - got := formatStack(pcs) - want := `redacted.go:0: runtime.gopanic -traceback_system_test.go:85: runtime_test.child7: panic("oops") -traceback_system_test.go:68: runtime_test.child6: child7() // appears in stack trace -traceback_system_test.go:59: runtime_test.child5: child6() // appears in stack trace -traceback_system_test.go:53: runtime_test.child4: child5() -traceback_system_test.go:49: runtime_test.child3: child4() -traceback_system_test.go:45: runtime_test.child2: child3() -traceback_system_test.go:41: runtime_test.child1: child2() -traceback_system_test.go:35: runtime_test.crash.func1: child1() -redacted.go:0: runtime.goexit -` - if strings.TrimSpace(got) != strings.TrimSpace(want) { - t.Errorf("got:\n%swant:\n%s", got, want) + // Parse the PCs out of the child's crash report. + pcs, err := parseStackPCs(crash) + if err != nil { + t.Fatal(err) + } + + // Unwind the stack using this executable's symbol table. + got := formatStack(pcs) + if strings.TrimSpace(got) != strings.TrimSpace(tc.want) { + t.Errorf("got:\n%swant:\n%s", got, tc.want) + } + }) } } @@ -154,6 +212,35 @@ redacted.go:0: runtime.goexit // // (Copied from golang.org/x/telemetry/crashmonitor.parseStackPCs.) func parseStackPCs(crash string) ([]uintptr, error) { + // getSymbol parses the symbol name out of a line of the form: + // SYMBOL(ARGS) + // + // Note: SYMBOL may contain parens "pkg.(*T).method". However, type + // parameters are always replaced with ..., so they cannot introduce + // more parens. e.g., "pkg.(*T[...]).method". + // + // ARGS can contain parens. We want the first paren that is not + // immediately preceded by a ".". + // + // TODO(prattmic): This is mildly complicated and is only used to find + // runtime.sigpanic, so perhaps simplify this by checking explicitly + // for sigpanic. + getSymbol := func(line string) (string, error) { + var prev rune + for i, c := range line { + if line[i] != '(' { + prev = c + continue + } + if prev == '.' { + prev = c + continue + } + return line[:i], nil + } + return "", fmt.Errorf("no symbol for stack frame: %s", line) + } + // getPC parses the PC out of a line of the form: // \tFILE:LINE +0xRELPC sp=... fp=... pc=... getPC := func(line string) (uint64, error) { @@ -170,6 +257,9 @@ func parseStackPCs(crash string) ([]uintptr, error) { childSentinel = sentinel() on = false // are we in the first running goroutine? lines = strings.Split(crash, "\n") + symLine = true // within a goroutine, every other line is a symbol or file/line/pc location, starting with symbol. + currSymbol string + prevSymbol string // symbol of the most recent previous frame with a PC. ) for i := 0; i < len(lines); i++ { line := lines[i] @@ -212,21 +302,76 @@ func parseStackPCs(crash string) ([]uintptr, error) { // Note: SYMBOL may contain parens "pkg.(*T).method" // The RELPC is sometimes missing. - // Skip the symbol(args) line. - i++ - if i == len(lines) { - break - } - line = lines[i] + if symLine { + var err error + currSymbol, err = getSymbol(line) + if err != nil { + return nil, fmt.Errorf("error extracting symbol: %v", err) + } - // Parse the PC, and correct for the parent and child's - // different mappings of the text section. - pc, err := getPC(line) - if err != nil { - // Inlined frame, perhaps; skip it. - continue + symLine = false // Next line is FILE:LINE. + } else { + // Parse the PC, and correct for the parent and child's + // different mappings of the text section. + pc, err := getPC(line) + if err != nil { + // Inlined frame, perhaps; skip it. + + // Done with this frame. Next line is a new frame. + // + // Don't update prevSymbol; we only want to + // track frames with a PC. + currSymbol = "" + symLine = true + continue + } + + pc = pc-parentSentinel+childSentinel + + // If the previous frame was sigpanic, then this frame + // was a trap (e.g., SIGSEGV). + // + // Typically all middle frames are calls, and report + // the "return PC". That is, the instruction following + // the CALL where the callee will eventually return to. + // + // runtime.CallersFrames is aware of this property and + // will decrement each PC by 1 to "back up" to the + // location of the CALL, which is the actual line + // number the user expects. + // + // This does not work for traps, as a trap is not a + // call, so the reported PC is not the return PC, but + // the actual PC of the trap. + // + // runtime.Callers is aware of this and will + // intentionally increment trap PCs in order to correct + // for the decrement performed by + // runtime.CallersFrames. See runtime.tracebackPCs and + // runtume.(*unwinder).symPC. + // + // We must emulate the same behavior, otherwise we will + // report the location of the instruction immediately + // prior to the trap, which may be on a different line, + // or even a different inlined functions. + // + // TODO(prattmic): The runtime applies the same trap + // behavior for other "injected calls", see injectCall + // in runtime.(*unwinder).next. Do we want to handle + // those as well? I don't believe we'd ever see + // runtime.asyncPreempt or runtime.debugCallV2 in a + // typical crash. + if prevSymbol == "runtime.sigpanic" { + pc++ + } + + pcs = append(pcs, uintptr(pc)) + + // Done with this frame. Next line is a new frame. + prevSymbol = currSymbol + currSymbol = "" + symLine = true } - pcs = append(pcs, uintptr(pc-parentSentinel+childSentinel)) } return pcs, nil } From 669d87a935536eb14cb2db311a83345359189924 Mon Sep 17 00:00:00 2001 From: Cosmos Nicolaou Date: Thu, 19 Dec 2024 15:55:05 -0800 Subject: [PATCH 058/397] runtime/pprof: continued attempt to deflake the VMInfo test. This change catches an additional error message to trigger skipping the test when the underlying system is failing. Fixes #62352 Change-Id: I5c12b20f3e9023597ff89fc905c0646a80ec4811 Reviewed-on: https://go-review.googlesource.com/c/go/+/637995 Reviewed-by: Cherry Mui Auto-Submit: Michael Pratt Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI --- src/runtime/pprof/vminfo_darwin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/pprof/vminfo_darwin_test.go b/src/runtime/pprof/vminfo_darwin_test.go index 4c0a0fefd87600..6d375c5d53368a 100644 --- a/src/runtime/pprof/vminfo_darwin_test.go +++ b/src/runtime/pprof/vminfo_darwin_test.go @@ -97,7 +97,7 @@ func useVMMap(t *testing.T) (hi, lo uint64, retryable bool, err error) { t.Logf("vmmap output: %s", out) if ee, ok := cmdErr.(*exec.ExitError); ok && len(ee.Stderr) > 0 { t.Logf("%v: %v\n%s", cmd, cmdErr, ee.Stderr) - if testing.Short() && strings.Contains(string(ee.Stderr), "No process corpse slots currently available, waiting to get one") { + if testing.Short() && (strings.Contains(string(ee.Stderr), "No process corpse slots currently available, waiting to get one") || strings.Contains(string(ee.Stderr), "Failed to generate corpse from the process")) { t.Skipf("Skipping knwn flake in short test mode") } retryable = bytes.Contains(ee.Stderr, []byte("resource shortage")) From 110ab1aaf4b0055027b86ff564b66a47e0f37b58 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Fri, 20 Dec 2024 09:28:55 -0500 Subject: [PATCH 059/397] slices: document two oddities Fixes #70935 Change-Id: Idf4a38a05ba595d616b6469a14419ff873bbd354 Reviewed-on: https://go-review.googlesource.com/c/go/+/638095 Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor --- src/slices/slices.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slices/slices.go b/src/slices/slices.go index 40b4d088b06e39..32029cd8ed297c 100644 --- a/src/slices/slices.go +++ b/src/slices/slices.go @@ -414,6 +414,7 @@ func Grow[S ~[]E, E any](s S, n int) S { panic("cannot be negative") } if n -= cap(s) - len(s); n > 0 { + // This expression allocates only once (see test). s = append(s[:cap(s)], make([]E, n)...)[:len(s)] } return s @@ -483,6 +484,9 @@ func Concat[S ~[]E, E any](slices ...S) S { panic("len out of range") } } + // Use Grow, not make, to round up to the size class: + // the extra space is otherwise unused and helps + // callers that append a few elements to the result. newslice := Grow[S](nil, size) for _, s := range slices { newslice = append(newslice, s...) From 06b191e11f6f78b19e5c5a43b3d0c461226c7084 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Sat, 21 Dec 2024 00:07:34 -0500 Subject: [PATCH 060/397] internal/syscall/unix: apply fstatat fix to linux/mips64le Apply CL 633280 to linux/mips64le, as it has the same struct as mips64. Updates #70659. Change-Id: Ibab635e69e44682eb214bf6a00f4cd75816b2d34 Reviewed-on: https://go-review.googlesource.com/c/go/+/637739 TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Run-TryBot: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/internal/syscall/unix/at_fstatat.go | 2 +- src/internal/syscall/unix/at_fstatat2.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/internal/syscall/unix/at_fstatat.go b/src/internal/syscall/unix/at_fstatat.go index 217e19a776d2b2..18cd62be203556 100644 --- a/src/internal/syscall/unix/at_fstatat.go +++ b/src/internal/syscall/unix/at_fstatat.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build dragonfly || (linux && !(loong64 || mips64)) || netbsd || (openbsd && mips64) +//go:build dragonfly || (linux && !(loong64 || mips64 || mips64le)) || netbsd || (openbsd && mips64) package unix diff --git a/src/internal/syscall/unix/at_fstatat2.go b/src/internal/syscall/unix/at_fstatat2.go index b18098b7d36eb0..b09aecbcdda4dd 100644 --- a/src/internal/syscall/unix/at_fstatat2.go +++ b/src/internal/syscall/unix/at_fstatat2.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build freebsd || (linux && (loong64 || mips64)) +//go:build freebsd || (linux && (loong64 || mips64 || mips64le)) package unix From 500675a7c8c72bd6b1054a7eb4daaf61970f5ad7 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Sat, 21 Dec 2024 15:54:34 -0500 Subject: [PATCH 061/397] cmd/compile: load map length with the right type len(map) is lowered to loading the first field of the map structure, which is the length. Currently it is a load of an int. With the old map, the first field is indeed an int. With Swiss map, however, it is a uint64. On big-endian 32-bit machine, loading an (32-bit) int from a uint64 would load just the high bits, which are (probably) all 0. Change to a load with the proper type. Fixes #70248. Change-Id: I39cf2d1e6658dac5a8de25c858e1580e2a14b894 Reviewed-on: https://go-review.googlesource.com/c/go/+/638375 Run-TryBot: Cherry Mui LUCI-TryBot-Result: Go LUCI TryBot-Result: Gopher Robot Reviewed-by: Keith Randall Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssagen/ssa.go | 13 +++++++++---- src/internal/runtime/maps/map.go | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index dc9b508c01ed12..edd1ffb0c915e8 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -5452,12 +5452,15 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value { if n.X.Type().IsChan() && n.Op() == ir.OCAP { s.Fatalf("cannot inline cap(chan)") // must use runtime.chancap now } + if n.X.Type().IsMap() && n.Op() == ir.OCAP { + s.Fatalf("cannot inline cap(map)") // cap(map) does not exist + } // if n == nil { // return 0 // } else { - // // len - // return *((*int)n) - // // cap + // // len, the actual loadType depends + // return int(*((*loadType)n)) + // // cap (chan only, not used for now) // return *(((*int)n)+1) // } lenType := n.Type() @@ -5485,7 +5488,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value { case ir.OLEN: if buildcfg.Experiment.SwissMap && n.X.Type().IsMap() { // length is stored in the first word. - s.vars[n] = s.load(lenType, x) + loadType := reflectdata.SwissMapType().Field(0).Type // uint64 + load := s.load(loadType, x) + s.vars[n] = s.conv(nil, load, loadType, lenType) // integer conversion doesn't need Node } else { // length is stored in the first word for map/chan s.vars[n] = s.load(lenType, x) diff --git a/src/internal/runtime/maps/map.go b/src/internal/runtime/maps/map.go index ffafcacdea1bc7..62463351c7d2de 100644 --- a/src/internal/runtime/maps/map.go +++ b/src/internal/runtime/maps/map.go @@ -194,6 +194,7 @@ func h2(h uintptr) uintptr { type Map struct { // The number of filled slots (i.e. the number of elements in all // tables). Excludes deleted slots. + // Must be first (known by the compiler, for len() builtin). used uint64 // seed is the hash seed, computed as a unique random number per map. From 05d8984781f7cf2f0f39b53699a558b6a1965c6c Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 22 Dec 2024 23:51:26 +0000 Subject: [PATCH 062/397] net: document LookupTXT behavior with multiple strings per record CL 8966 ("net: allow a dns TXT record to contain more than one ") concatenates strings in a TXT record. Document that behavior, since it's not obvious whether the strings will be concatenated or accumulated in the returned slice. Change-Id: I6acb27b296290361a95a6058a056f8e7c2df9a2b GitHub-Last-Rev: ec0726c7b83a56773d0ac4a86cbfc89c6f4884c9 GitHub-Pull-Request: golang/go#65233 Reviewed-on: https://go-review.googlesource.com/c/go/+/557695 Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Damien Neil Reviewed-by: Ian Lance Taylor --- src/net/lookup.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/net/lookup.go b/src/net/lookup.go index b04dfa23b9877b..f94fd8cefaab18 100644 --- a/src/net/lookup.go +++ b/src/net/lookup.go @@ -614,6 +614,9 @@ func (r *Resolver) LookupNS(ctx context.Context, name string) ([]*NS, error) { // LookupTXT returns the DNS TXT records for the given domain name. // +// If a DNS TXT record holds multiple strings, they are concatenated as a +// single string. +// // LookupTXT uses [context.Background] internally; to specify the context, use // [Resolver.LookupTXT]. func LookupTXT(name string) ([]string, error) { @@ -621,6 +624,9 @@ func LookupTXT(name string) ([]string, error) { } // LookupTXT returns the DNS TXT records for the given domain name. +// +// If a DNS TXT record holds multiple strings, they are concatenated as a +// single string. func (r *Resolver) LookupTXT(ctx context.Context, name string) ([]string, error) { return r.lookupTXT(ctx, name) } From 9f6c80a76ad56f653b743fe2df3f2296210c90d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20T=C3=B4rres?= Date: Fri, 20 Dec 2024 06:45:52 +0000 Subject: [PATCH 063/397] cmd/go/internal/work: allow single character values in -Wl, linker flags Allow single character values in -Wl, linker flags by modifying the regular expressions to use the star operator instead of the plus operator. Fixes #70924 Change-Id: Ie7940197cc8503440a87c6b29409a13377a20534 GitHub-Last-Rev: 42e8ac87d600239ceff434eb202e2747f2cceb3c GitHub-Pull-Request: golang/go#70937 Reviewed-on: https://go-review.googlesource.com/c/go/+/638035 Auto-Submit: Ian Lance Taylor Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/work/security.go | 12 ++++++------ src/cmd/go/internal/work/security_test.go | 7 +++++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go index 1e2f81b2d4d23e..50bfd0ab705383 100644 --- a/src/cmd/go/internal/work/security.go +++ b/src/cmd/go/internal/work/security.go @@ -201,23 +201,23 @@ var validLinkerFlags = []*lazyregexp.Regexp{ re(`-Wl,--end-group`), re(`-Wl,--(no-)?export-dynamic`), re(`-Wl,-E`), - re(`-Wl,-framework,[^,@\-][^,]+`), + re(`-Wl,-framework,[^,@\-][^,]*`), re(`-Wl,--hash-style=(sysv|gnu|both)`), re(`-Wl,-headerpad_max_install_names`), re(`-Wl,--no-undefined`), re(`-Wl,--pop-state`), re(`-Wl,--push-state`), re(`-Wl,-R,?([^@\-,][^,@]*$)`), - re(`-Wl,--just-symbols[=,]([^,@\-][^,@]+)`), - re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]+)`), + re(`-Wl,--just-symbols[=,]([^,@\-][^,@]*)`), + re(`-Wl,-rpath(-link)?[=,]([^,@\-][^,]*)`), re(`-Wl,-s`), re(`-Wl,-search_paths_first`), - re(`-Wl,-sectcreate,([^,@\-][^,]+),([^,@\-][^,]+),([^,@\-][^,]+)`), + re(`-Wl,-sectcreate,([^,@\-][^,]*),([^,@\-][^,]*),([^,@\-][^,]*)`), re(`-Wl,--start-group`), re(`-Wl,-?-static`), re(`-Wl,-?-subsystem,(native|windows|console|posix|xbox)`), - re(`-Wl,-syslibroot[=,]([^,@\-][^,]+)`), - re(`-Wl,-undefined[=,]([^,@\-][^,]+)`), + re(`-Wl,-syslibroot[=,]([^,@\-][^,]*)`), + re(`-Wl,-undefined[=,]([^,@\-][^,]*)`), re(`-Wl,-?-unresolved-symbols=[^,]+`), re(`-Wl,--(no-)?warn-([^,]+)`), re(`-Wl,-?-wrap[=,][^,@\-][^,]*`), diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go index 63dd569f7d3964..35af62176472b4 100644 --- a/src/cmd/go/internal/work/security_test.go +++ b/src/cmd/go/internal/work/security_test.go @@ -182,6 +182,13 @@ var goodLinkerFlags = [][]string{ {"-Wl,--pop-state"}, {"-Wl,--push-state,--as-needed"}, {"-Wl,--push-state,--no-as-needed,-Bstatic"}, + {"-Wl,--just-symbols,."}, + {"-Wl,-framework,."}, + {"-Wl,-rpath,."}, + {"-Wl,-rpath-link,."}, + {"-Wl,-sectcreate,.,.,."}, + {"-Wl,-syslibroot,."}, + {"-Wl,-undefined,."}, } var badLinkerFlags = [][]string{ From eef35e3bd989afcbf4141a570d933ff05b866504 Mon Sep 17 00:00:00 2001 From: Jorropo Date: Sat, 21 Dec 2024 20:32:42 +0100 Subject: [PATCH 064/397] internal/goexperiment: run go generate for synctest Updates #70954 Change-Id: If5f9c8b8b820b1cc4e41e76b50038c6155b575a8 Reviewed-on: https://go-review.googlesource.com/c/go/+/638355 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Reviewed-by: Michael Pratt --- src/internal/goexperiment/exp_synctest_off.go | 8 ++++++++ src/internal/goexperiment/exp_synctest_on.go | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/internal/goexperiment/exp_synctest_off.go create mode 100644 src/internal/goexperiment/exp_synctest_on.go diff --git a/src/internal/goexperiment/exp_synctest_off.go b/src/internal/goexperiment/exp_synctest_off.go new file mode 100644 index 00000000000000..fade13f89ca79c --- /dev/null +++ b/src/internal/goexperiment/exp_synctest_off.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.synctest + +package goexperiment + +const Synctest = false +const SynctestInt = 0 diff --git a/src/internal/goexperiment/exp_synctest_on.go b/src/internal/goexperiment/exp_synctest_on.go new file mode 100644 index 00000000000000..9c44be7276138b --- /dev/null +++ b/src/internal/goexperiment/exp_synctest_on.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.synctest + +package goexperiment + +const Synctest = true +const SynctestInt = 1 From b9955f0ad952a22388eead15e3d15610a29e03a0 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 20 Dec 2024 22:33:15 -0500 Subject: [PATCH 065/397] cmd/link, runtime: apply a delta to RODATA->DATA relocations On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol does not work, as the dynamic loader can change the address of the data section, and it is not possible to apply a dynamic relocation to RODATA. In order to get the correct address, we apply the delta between unrelocated and relocated data section addresses at run time. The linker saves both the unrelocated and the relocated addresses, so we can compute the delta. This is possible because RODATA symbols are generated by the compiler and so we have full control of. On AIX, the only case is the on-demand GC pointer masks from the type descriptors, for very large types. Perhaps there is a better way. Fixes #70483. Change-Id: I2664c0a813b38f7b146794cb1e73ccf5e238ca65 Reviewed-on: https://go-review.googlesource.com/c/go/+/638016 Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI --- src/cmd/link/internal/ld/data.go | 3 +++ src/cmd/link/internal/ld/symtab.go | 11 +++++++++++ src/runtime/symtab.go | 12 ++++++++++++ src/runtime/type.go | 4 ++++ 4 files changed, 30 insertions(+) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 5c4497cdd75b0f..a6b94a829f1442 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -424,6 +424,9 @@ func (st *relocSymState) relocsym(s loader.Sym, P []byte) { // FIXME: It should be forbidden to have R_ADDR from a // symbol which isn't in .data. However, as .text has the // same address once loaded, this is possible. + // TODO: .text (including rodata) to .data relocation + // doesn't work correctly, so we should really disallow it. + // See also aixStaticDataBase in symtab.go and in runtime. if ldr.SymSect(s).Seg == &Segdata { Xcoffadddynrel(target, ldr, syms, s, r, ri) } diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 8156f83a7a3267..b89a7802a2c62a 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -707,6 +707,17 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { // except go:buildid which is generated late and not used by the program. addRef("go:buildid") } + if ctxt.IsAIX() { + // On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol + // does not work. See data.go:relocsym, case R_ADDR. + // Here we record the unrelocated address in aixStaticDataBase (it is + // unrelocated as it is in RODATA) so we can compute the delta at + // run time. + sb := ldr.CreateSymForUpdate("runtime.aixStaticDataBase", 0) + sb.SetSize(0) + sb.AddAddr(ctxt.Arch, ldr.Lookup("runtime.data", 0)) + sb.SetType(sym.SRODATA) + } // text section information slice(textsectionmapSym, uint64(nsections)) diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index c78b044264742d..c3bd5103205cf6 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -468,6 +468,18 @@ type modulehash struct { // To make sure the map isn't collected, we keep a second reference here. var pinnedTypemaps []map[typeOff]*_type +// aixStaticDataBase (used only on AIX) holds the unrelocated address +// of the data section, set by the linker. +// +// On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol +// does not work, as the dynamic loader can change the address of the +// data section, and it is not possible to apply a dynamic relocation +// to RODATA. In order to get the correct address, we need to apply +// the delta between unrelocated and relocated data section addresses. +// aixStaticDataBase is the unrelocated address, and moduledata.data is +// the relocated one. +var aixStaticDataBase uintptr // linker symbol + var firstmoduledata moduledata // linker symbol var lastmoduledatap *moduledata // linker symbol diff --git a/src/runtime/type.go b/src/runtime/type.go index 9702164b1a261a..1edf9c9dd6d85c 100644 --- a/src/runtime/type.go +++ b/src/runtime/type.go @@ -104,6 +104,10 @@ func getGCMaskOnDemand(t *_type) *byte { // in read-only memory currently. addr := unsafe.Pointer(t.GCData) + if GOOS == "aix" { + addr = add(addr, firstmoduledata.data-aixStaticDataBase) + } + for { p := (*byte)(atomic.Loadp(addr)) switch p { From 772f024c615ec13c6cd28bf024e9d6be852201b6 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 23 Dec 2024 20:42:42 +0000 Subject: [PATCH 066/397] weak: fix typo in warning about tiny allocator optimization Fixes #70972. Change-Id: Ib04c2a3129a1da651a0b4674b372aec73966115a Reviewed-on: https://go-review.googlesource.com/c/go/+/638377 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- src/weak/pointer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weak/pointer.go b/src/weak/pointer.go index d8be4093492149..50af0c2fdc0a16 100644 --- a/src/weak/pointer.go +++ b/src/weak/pointer.go @@ -52,7 +52,7 @@ import ( // nil, even after an object is no longer referenced, the runtime is allowed to // perform a space-saving optimization that batches objects together in a single // allocation slot. The weak pointer for an unreferenced object in such an -// allocation may never be called if it always exists in the same batch as a +// allocation may never become nil if it always exists in the same batch as a // referenced object. Typically, this batching only happens for tiny // (on the order of 16 bytes or less) and pointer-free objects. type Pointer[T any] struct { From cce75da30b6a1a58f7265401279cab707d403dcf Mon Sep 17 00:00:00 2001 From: Alec Bakholdin Date: Sun, 22 Dec 2024 20:36:59 -0500 Subject: [PATCH 067/397] crypto/mlkem: swap order of return values of Encapsulate Per FIPS 203 (https://csrc.nist.gov/pubs/fips/203/final), the order of return values should be sharedKey, ciphertext. This commit simply swaps those return values and updates any consumers of the Encapsulate() method to respect the new order. Fixes #70950 Change-Id: I2a0d605e3baf7fe69510d60d3d35bbac18f883c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/638376 LUCI-TryBot-Result: Go LUCI Reviewed-by: Austin Clements Auto-Submit: Ian Lance Taylor