From 9c017ff30dd21bbdcdb11f39458d3944db530d7e Mon Sep 17 00:00:00 2001 From: Aofei Sheng Date: Sat, 26 Sep 2020 13:21:41 +0800 Subject: [PATCH 001/403] net/http/httputil: copy response header back to http.ResponseWriter in ReverseProxy.handleUpgradeResponse Fixes: #41634 Change-Id: Ib78cc37a4d2ca0753d567eafb616238e4103484e Reviewed-on: https://go-review.googlesource.com/c/go/+/257777 Reviewed-by: Damien Neil Trust: Damien Neil Trust: Brad Fitzpatrick Run-TryBot: Damien Neil TryBot-Result: Go Bot --- src/net/http/httputil/reverseproxy.go | 6 ++++-- src/net/http/httputil/reverseproxy_test.go | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/net/http/httputil/reverseproxy.go b/src/net/http/httputil/reverseproxy.go index 46e5f68a843..4e369580ea8 100644 --- a/src/net/http/httputil/reverseproxy.go +++ b/src/net/http/httputil/reverseproxy.go @@ -549,8 +549,6 @@ func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.R return } - copyHeader(res.Header, rw.Header()) - hj, ok := rw.(http.Hijacker) if !ok { p.getErrorHandler()(rw, req, fmt.Errorf("can't switch protocols using non-Hijacker ResponseWriter type %T", rw)) @@ -581,6 +579,10 @@ func (p *ReverseProxy) handleUpgradeResponse(rw http.ResponseWriter, req *http.R return } defer conn.Close() + + copyHeader(rw.Header(), res.Header) + + res.Header = rw.Header() res.Body = nil // so res.Write only writes the headers; we have res.Body in backConn above if err := res.Write(brw); err != nil { p.getErrorHandler()(rw, req, fmt.Errorf("response write: %v", err)) diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go index ea786864d8b..cc05d55d879 100644 --- a/src/net/http/httputil/reverseproxy_test.go +++ b/src/net/http/httputil/reverseproxy_test.go @@ -1157,6 +1157,9 @@ func TestReverseProxyWebSocket(t *testing.T) { handler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { rw.Header().Set("X-Header", "X-Value") rproxy.ServeHTTP(rw, req) + if got, want := rw.Header().Get("X-Modified"), "true"; got != want { + t.Errorf("response writer X-Modified header = %q; want %q", got, want) + } }) frontendProxy := httptest.NewServer(handler) From 58eadc232e4fd2633761ffdeeaa922216beee74e Mon Sep 17 00:00:00 2001 From: avivklas Date: Tue, 15 Sep 2020 08:48:44 +0300 Subject: [PATCH 002/403] net/http: test that ParseMultipartForm returns an error for int overflow ParseMultipartForm has been changed to return an error if maxMemory parameter + 10MB causes int overflows. This adds a test for the new behaviour. For #40430 Change-Id: I4f66ce8a9382940182011d22a84ee52b1d1364cf Reviewed-on: https://go-review.googlesource.com/c/go/+/254977 Reviewed-by: Damien Neil Trust: Damien Neil Trust: Brad Fitzpatrick --- src/net/http/request_test.go | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go index 461d66e05d7..4f4f435814c 100644 --- a/src/net/http/request_test.go +++ b/src/net/http/request_test.go @@ -13,6 +13,7 @@ import ( "fmt" "io" "io/ioutil" + "math" "mime/multipart" . "net/http" "net/http/httptest" @@ -245,6 +246,41 @@ func TestParseMultipartForm(t *testing.T) { } } +// Issue #40430: ParseMultipartForm should return error for int overflow +func TestMaxInt64ForMultipartFormMaxMemory(t *testing.T) { + cst := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { + if err := req.ParseMultipartForm(math.MaxInt64); err != nil { + Error(rw, err.Error(), StatusBadRequest) + return + } + })) + defer cst.Close() + fBuf := new(bytes.Buffer) + mw := multipart.NewWriter(fBuf) + mf, err := mw.CreateFormFile("file", "myfile.txt") + if err != nil { + t.Fatal(err) + } + if _, err := mf.Write(bytes.Repeat([]byte("abc"), 1<<10)); err != nil { + t.Fatal(err) + } + if err := mw.Close(); err != nil { + t.Fatal(err) + } + req, err := NewRequest("POST", cst.URL, fBuf) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Content-Type", mw.FormDataContentType()) + res, err := cst.Client().Do(req) + if err != nil { + t.Fatal(err) + } + if g, w := res.StatusCode, StatusBadRequest; g != w { + t.Fatalf("Status code mismatch: got %d, want %d", g, w) + } +} + func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) } func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) } func testRedirect(t *testing.T, h2 bool) { From 178b0f59ff0d8be6d41d0f4099d16bfd3bc21ea7 Mon Sep 17 00:00:00 2001 From: hk Date: Mon, 19 Oct 2020 12:13:25 +0000 Subject: [PATCH 003/403] cmd/compile/internal/gc: remove an unused method Change-Id: Ib496d1e9a47d2cf69509ffd0009038b7d34a0149 GitHub-Last-Rev: 5b5589dd03e1d781e4cedc643d5e8a7f8bda2139 GitHub-Pull-Request: golang/go#42060 Reviewed-on: https://go-review.googlesource.com/c/go/+/263618 Run-TryBot: Robert Griesemer Reviewed-by: Matthew Dempsky Trust: Matthew Dempsky Trust: Robert Griesemer TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/noder.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 68d0327cdb4..85e710086a9 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -1438,11 +1438,6 @@ func (p *noder) mkname(name *syntax.Name) *Node { return mkname(p.name(name)) } -func (p *noder) newname(name *syntax.Name) *Node { - // TODO(mdempsky): Set line number? - return newname(p.name(name)) -} - func (p *noder) wrapname(n syntax.Node, x *Node) *Node { // These nodes do not carry line numbers. // Introduce a wrapper node to give them the correct line. From bb44c90a94fefcdf51caf1be05b9af6876cac2f4 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Mon, 19 Oct 2020 18:16:31 +0000 Subject: [PATCH 004/403] Revert "cmd/link: put C static symbols in the symbol table" This reverts CL 263259. Reason for revert: break AIX builder. Change-Id: I3abb0b1f509961a06f1567d8c87679b0ca5782d7 Reviewed-on: https://go-review.googlesource.com/c/go/+/263660 Trust: Cherry Zhang Run-TryBot: Cherry Zhang Reviewed-by: Bryan C. Mills --- src/cmd/link/internal/ld/symtab.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index 245a320493f..dd82963a416 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -518,7 +518,7 @@ func (ctxt *Link) symtab(pcln *pclntab) []sym.SymKind { nsym := loader.Sym(ldr.NSym()) symGroupType := make([]sym.SymKind, nsym) for s := loader.Sym(1); s < nsym; s++ { - if !ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) && !ldr.IsExternal(s) { + if !ctxt.IsExternal() && ldr.IsFileLocal(s) && !ldr.IsFromAssembly(s) { ldr.SetAttrNotInSymbolTable(s, true) } if !ldr.AttrReachable(s) || ldr.AttrSpecial(s) || (ldr.SymType(s) != sym.SRODATA && ldr.SymType(s) != sym.SGOFUNC) { From 0040adfd0f98e1012837b0317fabf69cf1f8855b Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 16 Oct 2020 21:39:36 -0400 Subject: [PATCH 005/403] runtime: define ios/arm64 entry points Updates #38485. Change-Id: I030346c7f0c3ce89209588525b210284fdea4efd Reviewed-on: https://go-review.googlesource.com/c/go/+/263638 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- src/runtime/rt0_ios_arm64.s | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/runtime/rt0_ios_arm64.s diff --git a/src/runtime/rt0_ios_arm64.s b/src/runtime/rt0_ios_arm64.s new file mode 100644 index 00000000000..dcc83656e2c --- /dev/null +++ b/src/runtime/rt0_ios_arm64.s @@ -0,0 +1,14 @@ +// Copyright 2020 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. + +#include "textflag.h" + +// internal linking executable entry point. +// ios/arm64 only supports external linking. +TEXT _rt0_arm64_ios(SB),NOSPLIT|NOFRAME,$0 + UNDEF + +// library entry point. +TEXT _rt0_arm64_ios_lib(SB),NOSPLIT|NOFRAME,$0 + JMP _rt0_arm64_darwin_lib(SB) From 2ff9e01d72f718ef61c635a25db6d2084aef95eb Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 16 Oct 2020 21:42:01 -0400 Subject: [PATCH 006/403] cmd/link: fix TestDWARFiOS Use GOOS=ios. Run "xcodebuild -showsdks" correctly. Wrap testDWARF in subtests, as it calls t.Parallel, otherwise the two calls of testDWARF will cause t.Parallel being called twice, which panics. Updates #38485. Change-Id: I614c8daa99c83cbfd05a4cfa041968d49279f16a Reviewed-on: https://go-review.googlesource.com/c/go/+/263639 Trust: Cherry Zhang Run-TryBot: Cherry Zhang Reviewed-by: Jeremy Faller Reviewed-by: Than McIntosh --- src/cmd/link/dwarf_test.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index 88480064dd1..db710bed6ab 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -195,14 +195,18 @@ func TestDWARFiOS(t *testing.T) { } // Check to see if the ios tools are installed. It's possible to have the command line tools // installed without the iOS sdk. - if output, err := exec.Command("xcodebuild -showsdks").CombinedOutput(); err != nil { + if output, err := exec.Command("xcodebuild", "-showsdks").CombinedOutput(); err != nil { t.Skipf("error running xcodebuild, required for iOS cross build: %v", err) } else if !strings.Contains(string(output), "iOS SDK") { t.Skipf("iOS SDK not detected.") } cc := "CC=" + runtime.GOROOT() + "/misc/ios/clangwrap.sh" // iOS doesn't allow unmapped segments, so iOS executables don't have DWARF. - testDWARF(t, "", false, cc, "CGO_ENABLED=1", "GOOS=darwin", "GOARCH=arm64") + t.Run("exe", func(t *testing.T) { + testDWARF(t, "", false, cc, "CGO_ENABLED=1", "GOOS=ios", "GOARCH=arm64") + }) // However, c-archive iOS objects have embedded DWARF. - testDWARF(t, "c-archive", true, cc, "CGO_ENABLED=1", "GOOS=darwin", "GOARCH=arm64") + t.Run("c-archive", func(t *testing.T) { + testDWARF(t, "c-archive", true, cc, "CGO_ENABLED=1", "GOOS=ios", "GOARCH=arm64") + }) } From 06839e3c9a014da580c2cdcd11263e2b08991b74 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sat, 17 Oct 2020 14:00:35 -0400 Subject: [PATCH 007/403] cmd/link: run generator functions along with symbol writing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like we do for applying relocations, for generator symbols, run the generator function along with symbol writing. This will probably have better locality and parallelism. Linking cmd/compile, Asmb 29.9ms ± 5% 19.1ms ±12% -36.18% (p=0.000 n=10+9) TotalTime 351ms ± 3% 339ms ± 2% -3.51% (p=0.000 n=11+10) Change-Id: I9cda6718bf70b3bcf1b7a501a845d6136234d2ee Reviewed-on: https://go-review.googlesource.com/c/go/+/263640 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Jeremy Faller Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/data.go | 3 +++ src/cmd/link/internal/ld/main.go | 12 ------------ 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/cmd/link/internal/ld/data.go b/src/cmd/link/internal/ld/data.go index 84e03a40113..00130044abb 100644 --- a/src/cmd/link/internal/ld/data.go +++ b/src/cmd/link/internal/ld/data.go @@ -951,6 +951,9 @@ func writeBlock(ctxt *Link, out *OutBuf, ldr *loader.Loader, syms []loader.Sym, } P := out.WriteSym(ldr, s) st.relocsym(s, P) + if f, ok := ctxt.generatorSyms[s]; ok { + f(ctxt, s) + } addr += int64(len(P)) siz := ldr.SymSize(s) if addr < val+siz { diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 5ae57d19922..5c8293810f9 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -36,14 +36,12 @@ import ( "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/benchmark" - "cmd/link/internal/loader" "flag" "log" "os" "runtime" "runtime/pprof" "strings" - "sync" ) var ( @@ -331,16 +329,6 @@ func Main(arch *sys.Arch, theArch Arch) { // will be applied directly there. bench.Start("Asmb") asmb(ctxt) - // Generate large symbols. - var wg sync.WaitGroup - for s, f := range ctxt.generatorSyms { - wg.Add(1) - go func(f generatorFunc, s loader.Sym) { - defer wg.Done() - f(ctxt, s) - }(f, s) - } - wg.Wait() // Generate additional symbols for the native symbol table just prior // to code generation. From ab541a0560408999ac65d12bec2a3057994eda38 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Sat, 17 Oct 2020 15:19:53 +0000 Subject: [PATCH 008/403] compress/flate: fix corrupted output The fastest compression mode can pick up a false match for every 2GB of input data resulting in incorrectly decompressed data. Since matches are allowed to be up to and including at maxMatchOffset we must offset the buffer by an additional element to prevent the first 4 bytes to match after an out-of-reach value after shiftOffsets has been called. We offset by `maxMatchOffset + 1` so offset 0 in the table will now fail the `if offset > maxMatchOffset` in all cases. Fixes #41420 Change-Id: If1fbe01728e132b8a207e3f3f439edd832dcc710 GitHub-Last-Rev: 50fabab0da874c37543b139459a810e12e83cee2 GitHub-Pull-Request: golang/go#41477 Reviewed-on: https://go-review.googlesource.com/c/go/+/255879 Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Trust: Joe Tsai Trust: Matthew Dempsky --- src/compress/flate/deflate_test.go | 57 ++++++++++++++++++++++++++++++ src/compress/flate/deflatefast.go | 11 ++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go index 49a0345fd1d..b19cbec5a9a 100644 --- a/src/compress/flate/deflate_test.go +++ b/src/compress/flate/deflate_test.go @@ -11,6 +11,7 @@ import ( "internal/testenv" "io" "io/ioutil" + "math/rand" "reflect" "runtime/debug" "sync" @@ -896,6 +897,62 @@ func TestBestSpeedMaxMatchOffset(t *testing.T) { } } +func TestBestSpeedShiftOffsets(t *testing.T) { + // Test if shiftoffsets properly preserves matches and resets out-of-range matches + // seen in https://github.com/golang/go/issues/4142 + enc := newDeflateFast() + + // testData may not generate internal matches. + testData := make([]byte, 32) + rng := rand.New(rand.NewSource(0)) + for i := range testData { + testData[i] = byte(rng.Uint32()) + } + + // Encode the testdata with clean state. + // Second part should pick up matches from the first block. + wantFirstTokens := len(enc.encode(nil, testData)) + wantSecondTokens := len(enc.encode(nil, testData)) + + if wantFirstTokens <= wantSecondTokens { + t.Fatalf("test needs matches between inputs to be generated") + } + // Forward the current indicator to before wraparound. + enc.cur = bufferReset - int32(len(testData)) + + // Part 1 before wrap, should match clean state. + got := len(enc.encode(nil, testData)) + if wantFirstTokens != got { + t.Errorf("got %d, want %d tokens", got, wantFirstTokens) + } + + // Verify we are about to wrap. + if enc.cur != bufferReset { + t.Errorf("got %d, want e.cur to be at bufferReset (%d)", enc.cur, bufferReset) + } + + // Part 2 should match clean state as well even if wrapped. + got = len(enc.encode(nil, testData)) + if wantSecondTokens != got { + t.Errorf("got %d, want %d token", got, wantSecondTokens) + } + + // Verify that we wrapped. + if enc.cur >= bufferReset { + t.Errorf("want e.cur to be < bufferReset (%d), got %d", bufferReset, enc.cur) + } + + // Forward the current buffer, leaving the matches at the bottom. + enc.cur = bufferReset + enc.shiftOffsets() + + // Ensure that no matches were picked up. + got = len(enc.encode(nil, testData)) + if wantFirstTokens != got { + t.Errorf("got %d, want %d tokens", got, wantFirstTokens) + } +} + func TestMaxStackSize(t *testing.T) { // This test must not run in parallel with other tests as debug.SetMaxStack // affects all goroutines. diff --git a/src/compress/flate/deflatefast.go b/src/compress/flate/deflatefast.go index 24f8be9d5db..6aa439f13d9 100644 --- a/src/compress/flate/deflatefast.go +++ b/src/compress/flate/deflatefast.go @@ -270,6 +270,7 @@ func (e *deflateFast) matchLen(s, t int32, src []byte) int32 { func (e *deflateFast) reset() { e.prev = e.prev[:0] // Bump the offset, so all matches will fail distance check. + // Nothing should be >= e.cur in the table. e.cur += maxMatchOffset // Protect against e.cur wraparound. @@ -288,17 +289,21 @@ func (e *deflateFast) shiftOffsets() { for i := range e.table[:] { e.table[i] = tableEntry{} } - e.cur = maxMatchOffset + e.cur = maxMatchOffset + 1 return } // Shift down everything in the table that isn't already too far away. for i := range e.table[:] { - v := e.table[i].offset - e.cur + maxMatchOffset + v := e.table[i].offset - e.cur + maxMatchOffset + 1 if v < 0 { + // We want to reset e.cur to maxMatchOffset + 1, so we need to shift + // all table entries down by (e.cur - (maxMatchOffset + 1)). + // Because we ignore matches > maxMatchOffset, we can cap + // any negative offsets at 0. v = 0 } e.table[i].offset = v } - e.cur = maxMatchOffset + e.cur = maxMatchOffset + 1 } From 4d1cecdee8360ef12a817c124d7a04c9d29741c3 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 14 Oct 2020 08:06:54 -0400 Subject: [PATCH 009/403] cmd/dist,cmd/go: broaden use of asm macro GOEXPERIMENT_REGABI This extends a change made in https://golang.org/cl/252258 to the go command (to define an asm macro when GOEXPERIMENT=regabi is in effect); we need this same macro during the bootstrap build in order to build the runtime correctly. In addition, expand the set of packages where the macro is applied to {runtime, reflect, syscall, runtime/internal/*}, and move the logic for deciding when something is a "runtime package" out of the assembler and into cmd/{go,dist}, introducing a new assembler command line flag instead. Updates #27539, #40724. Change-Id: Ifcc7f029f56873584de1e543c55b0d3e54ad6c49 Reviewed-on: https://go-review.googlesource.com/c/go/+/262317 Trust: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Austin Clements Reviewed-by: Cherry Zhang --- src/cmd/asm/internal/flags/flags.go | 19 ++++++++-------- src/cmd/asm/main.go | 4 ++-- src/cmd/dist/build.go | 35 +++++++++++++++++++++++++++++ src/cmd/go/internal/work/gc.go | 22 +++++++++++------- 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go index 64024cc97db..07654399591 100644 --- a/src/cmd/asm/internal/flags/flags.go +++ b/src/cmd/asm/internal/flags/flags.go @@ -15,15 +15,16 @@ import ( ) var ( - Debug = flag.Bool("debug", false, "dump instructions as they are parsed") - OutputFile = flag.String("o", "", "output file; default foo.o for /a/b/c/foo.s as first argument") - TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths") - Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library") - Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries") - AllErrors = flag.Bool("e", false, "no limit on number of errors reported") - SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble") - Importpath = flag.String("p", "", "set expected package import to path") - Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)") + Debug = flag.Bool("debug", false, "dump instructions as they are parsed") + OutputFile = flag.String("o", "", "output file; default foo.o for /a/b/c/foo.s as first argument") + TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths") + Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library") + Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries") + AllErrors = flag.Bool("e", false, "no limit on number of errors reported") + SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble") + Importpath = flag.String("p", "", "set expected package import to path") + Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)") + CompilingRuntime = flag.Bool("compilingRuntime", false, "source to be compiled is part of the Go runtime") ) var ( diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index 01c963ac729..149925d23f1 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -52,7 +52,6 @@ func main() { case "all", "ret": ctxt.Retpoline = true } - compilingRuntime := objabi.IsRuntimePackagePath(*flags.Importpath) ctxt.Bso = bufio.NewWriter(os.Stdout) defer ctxt.Bso.Flush() @@ -75,7 +74,8 @@ func main() { var failedFile string for _, f := range flag.Args() { lexer := lex.NewLexer(f) - parser := asm.NewParser(ctxt, architecture, lexer, compilingRuntime) + parser := asm.NewParser(ctxt, architecture, lexer, + *flags.CompilingRuntime) ctxt.DiagFunc = func(format string, args ...interface{}) { diag = true log.Printf(format, args...) diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index 398ed6bce11..11da38ebdf8 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -832,6 +832,21 @@ func runInstall(pkg string, ch chan struct{}) { asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64) } goasmh := pathf("%s/go_asm.h", workdir) + if IsRuntimePackagePath(pkg) { + asmArgs = append(asmArgs, "-compilingRuntime") + if os.Getenv("GOEXPERIMENT") == "regabi" { + // In order to make it easier to port runtime assembly + // to the register ABI, we introduce a macro + // indicating the experiment is enabled. + // + // Note: a similar change also appears in + // cmd/go/internal/work/gc.go. + // + // TODO(austin): Remove this once we commit to the + // register ABI (#40724). + asmArgs = append(asmArgs, "-D=GOEXPERIMENT_REGABI=1") + } + } // Collect symabis from assembly code. var symabis string @@ -1733,3 +1748,23 @@ func cmdlist() { fatalf("write failed: %v", err) } } + +// IsRuntimePackagePath examines 'pkgpath' and returns TRUE if it +// belongs to the collection of "runtime-related" packages, including +// "runtime" itself, "reflect", "syscall", and the +// "runtime/internal/*" packages. See also the function of the same +// name in cmd/internal/objabi/path.go. +func IsRuntimePackagePath(pkgpath string) bool { + rval := false + switch pkgpath { + case "runtime": + rval = true + case "reflect": + rval = true + case "syscall": + rval = true + default: + rval = strings.HasPrefix(pkgpath, "runtime/internal") + } + return rval +} diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 56ad1872be4..2df4a52ba59 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -292,14 +292,20 @@ func asmArgs(a *Action, p *load.Package) []interface{} { } } } - if p.ImportPath == "runtime" && objabi.Regabi_enabled != 0 { - // In order to make it easier to port runtime assembly - // to the register ABI, we introduce a macro - // indicating the experiment is enabled. - // - // TODO(austin): Remove this once we commit to the - // register ABI (#40724). - args = append(args, "-D=GOEXPERIMENT_REGABI=1") + if objabi.IsRuntimePackagePath(pkgpath) { + args = append(args, "-compilingRuntime") + if objabi.Regabi_enabled != 0 { + // In order to make it easier to port runtime assembly + // to the register ABI, we introduce a macro + // indicating the experiment is enabled. + // + // Note: a similar change also appears in + // cmd/dist/build.go. + // + // TODO(austin): Remove this once we commit to the + // register ABI (#40724). + args = append(args, "-D=GOEXPERIMENT_REGABI=1") + } } if cfg.Goarch == "mips" || cfg.Goarch == "mipsle" { From 5647d01ab724a19793ac7002776b0dec03fa35f5 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 19 Oct 2020 18:03:51 +0000 Subject: [PATCH 010/403] Revert "net/http: test that ParseMultipartForm returns an error for int overflow" This reverts CL 254977. Reason for revert: introduced test failures on longtest builders. Change-Id: I75e868245f980189ad85dd4103d9178989e06ecf Reviewed-on: https://go-review.googlesource.com/c/go/+/263658 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Carlos Amedee Reviewed-by: Dmitri Shuralyov --- src/net/http/request_test.go | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go index 4f4f435814c..461d66e05d7 100644 --- a/src/net/http/request_test.go +++ b/src/net/http/request_test.go @@ -13,7 +13,6 @@ import ( "fmt" "io" "io/ioutil" - "math" "mime/multipart" . "net/http" "net/http/httptest" @@ -246,41 +245,6 @@ func TestParseMultipartForm(t *testing.T) { } } -// Issue #40430: ParseMultipartForm should return error for int overflow -func TestMaxInt64ForMultipartFormMaxMemory(t *testing.T) { - cst := httptest.NewServer(HandlerFunc(func(rw ResponseWriter, req *Request) { - if err := req.ParseMultipartForm(math.MaxInt64); err != nil { - Error(rw, err.Error(), StatusBadRequest) - return - } - })) - defer cst.Close() - fBuf := new(bytes.Buffer) - mw := multipart.NewWriter(fBuf) - mf, err := mw.CreateFormFile("file", "myfile.txt") - if err != nil { - t.Fatal(err) - } - if _, err := mf.Write(bytes.Repeat([]byte("abc"), 1<<10)); err != nil { - t.Fatal(err) - } - if err := mw.Close(); err != nil { - t.Fatal(err) - } - req, err := NewRequest("POST", cst.URL, fBuf) - if err != nil { - t.Fatal(err) - } - req.Header.Set("Content-Type", mw.FormDataContentType()) - res, err := cst.Client().Do(req) - if err != nil { - t.Fatal(err) - } - if g, w := res.StatusCode, StatusBadRequest; g != w { - t.Fatalf("Status code mismatch: got %d, want %d", g, w) - } -} - func TestRedirect_h1(t *testing.T) { testRedirect(t, h1Mode) } func TestRedirect_h2(t *testing.T) { testRedirect(t, h2Mode) } func testRedirect(t *testing.T, h2 bool) { From c216ae80c965acb9641d94d5f58c206bd0cf7d66 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Mon, 19 Oct 2020 14:14:40 -0700 Subject: [PATCH 011/403] cmd/compile: fix ICE in reporting of invalid recursive types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit asNode(t.Nod).Name.Param will be nil for builtin types (i.e., the universal predeclared types and unsafe.Pointer). These types can't be part of a cycle anyway, so we can just skip them. Fixes #42075. Change-Id: Ic7a44de65c6bfd16936545dee25e36de8850acf3 Reviewed-on: https://go-review.googlesource.com/c/go/+/263717 Trust: Matthew Dempsky Trust: Daniel Martí Reviewed-by: Daniel Martí --- src/cmd/compile/internal/gc/align.go | 2 +- test/fixedbugs/issue42075.go | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue42075.go diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index 5af403afa36..4bc454df224 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -199,7 +199,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool { } *path = append(*path, t) - if findTypeLoop(asNode(t.Nod).Name.Param.Ntype.Type, path) { + if p := asNode(t.Nod).Name.Param; p != nil && findTypeLoop(p.Ntype.Type, path) { return true } *path = (*path)[:len(*path)-1] diff --git a/test/fixedbugs/issue42075.go b/test/fixedbugs/issue42075.go new file mode 100644 index 00000000000..af85fb281d8 --- /dev/null +++ b/test/fixedbugs/issue42075.go @@ -0,0 +1,16 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type T struct { // ERROR "recursive type" + x int + p unsafe.Pointer + + f T +} From 70cad2744b57691962645681722ce756e81791c1 Mon Sep 17 00:00:00 2001 From: hk Date: Mon, 19 Oct 2020 12:11:13 +0000 Subject: [PATCH 012/403] cmd/compile/internal/gc: use plural nouns in comments Change-Id: I99a5b5b88495cfaef16d41ee4b962c5d0b3488aa GitHub-Last-Rev: fa0d895b3a87e45f499f02651a5f0e4946124765 GitHub-Pull-Request: golang/go#42059 Reviewed-on: https://go-review.googlesource.com/c/go/+/263617 Reviewed-by: Keith Randall Trust: Keith Randall Trust: Robert Griesemer --- src/cmd/compile/internal/gc/go.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go index 2fbdf710553..ee2add3733b 100644 --- a/src/cmd/compile/internal/gc/go.go +++ b/src/cmd/compile/internal/gc/go.go @@ -61,12 +61,12 @@ type Class uint8 //go:generate stringer -type=Class const ( Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables - PEXTERN // global variable + PEXTERN // global variables PAUTO // local variables - PAUTOHEAP // local variable or parameter moved to heap + PAUTOHEAP // local variables or parameters moved to heap PPARAM // input arguments PPARAMOUT // output results - PFUNC // global function + PFUNC // global functions // Careful: Class is stored in three bits in Node.flags. _ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3) From 2754d911641c3a4569f48d61c541fc2ac395d23b Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 19 Oct 2020 17:55:55 +0000 Subject: [PATCH 013/403] runtime: add lock rank partial-order edge between fin and mheap finlock may be held across a write barrier, which could then acquire the mheap lock. Notably, this occurs in the mp.unlockf write in gopark where finlock is held by the finalizer goroutines and is going to sleep. Fixes #42062. Change-Id: Icf76637ae6fc12795436272633dca3d473780875 Reviewed-on: https://go-review.googlesource.com/c/go/+/263678 Trust: Michael Knyszek Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/runtime/lockrank.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/lockrank.go b/src/runtime/lockrank.go index 042f10b1d32..0cbbfc4f45d 100644 --- a/src/runtime/lockrank.go +++ b/src/runtime/lockrank.go @@ -231,7 +231,7 @@ var lockPartialOrder [][]lockRank = [][]lockRank{ lockRankDefer: {}, lockRankSudog: {lockRankNotifyList, lockRankHchan}, lockRankWbufSpans: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankSweep, lockRankSched, lockRankAllg, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankHchan, lockRankFin, lockRankNotifyList, lockRankTraceStrings, lockRankMspanSpecial, lockRankProf, lockRankRoot, lockRankGscan, lockRankDefer, lockRankSudog}, - lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans, lockRankSpanSetSpine}, + lockRankMheap: {lockRankSysmon, lockRankScavenge, lockRankSweepWaiters, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankFin, lockRankPollDesc, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan, lockRankMspanSpecial, lockRankProf, lockRankGcBitsArenas, lockRankRoot, lockRankGscan, lockRankStackpool, lockRankStackLarge, lockRankDefer, lockRankSudog, lockRankWbufSpans, lockRankSpanSetSpine}, lockRankMheapSpecial: {lockRankSysmon, lockRankScavenge, lockRankAssistQueue, lockRankCpuprof, lockRankSweep, lockRankSched, lockRankAllg, lockRankAllp, lockRankTimers, lockRankItab, lockRankReflectOffs, lockRankNotifyList, lockRankTraceBuf, lockRankTraceStrings, lockRankHchan}, lockRankGlobalAlloc: {lockRankProf, lockRankSpanSetSpine, lockRankMheap, lockRankMheapSpecial}, From 8fe372c7b36b4d078c871a26e10b427c41275ecd Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Mon, 19 Oct 2020 13:09:55 -0700 Subject: [PATCH 014/403] cmd/compile: allowing inlining of functions with OCALLPART OCALLPART is exported in its original form, which is as an OXDOT. The body of the method value wrapper created in makepartialcall() was not being typechecked, and that was causing a problem during escape analysis, so I added code to typecheck the body. The go executable got slightly bigger with this change (13598111 -> 13598905), because of extra exported methods with OCALLPART (I believe), while the text size got slightly smaller (9686964 -> 9686643). This is mainly part of the work to make sure all function bodies can be exported (for purposes of generics), but might as well fix the OCALLPART inlining bug as well. Fixes #18493 Change-Id: If7aa055ff78ed7a6330c6a1e22f836ec567d04fd Reviewed-on: https://go-review.googlesource.com/c/go/+/263620 Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/closure.go | 6 ++++++ src/cmd/compile/internal/gc/iexport.go | 9 +++++++-- src/cmd/compile/internal/gc/iimport.go | 2 +- src/cmd/compile/internal/gc/inl.go | 6 ++++-- test/inline.go | 17 +++++++++++++++++ 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/gc/closure.go b/src/cmd/compile/internal/gc/closure.go index 250be38e5bf..5d1012111fc 100644 --- a/src/cmd/compile/internal/gc/closure.go +++ b/src/cmd/compile/internal/gc/closure.go @@ -434,6 +434,8 @@ func typecheckpartialcall(fn *Node, sym *types.Sym) { fn.Type = xfunc.Type } +// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed +// for partial calls. func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node { rcvrtype := fn.Left.Type sym := methodSymSuffix(rcvrtype, meth, "-fm") @@ -500,6 +502,10 @@ func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node { funcbody() xfunc = typecheck(xfunc, ctxStmt) + // Need to typecheck the body of the just-generated wrapper. + // typecheckslice() requires that Curfn is set when processing an ORETURN. + Curfn = xfunc + typecheckslice(xfunc.Nbody.Slice(), ctxStmt) sym.Def = asTypesNode(xfunc) xtop = append(xtop, xfunc) Curfn = savecurfn diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index df08a4a6c20..9bc1f64600d 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1266,8 +1266,13 @@ func (w *exportWriter) expr(n *Node) { // case OSTRUCTKEY: // unreachable - handled in case OSTRUCTLIT by elemList - // case OCALLPART: - // unimplemented - handled by default case + case OCALLPART: + // An OCALLPART is an OXDOT before type checking. + w.op(OXDOT) + w.pos(n.Pos) + w.expr(n.Left) + // Right node should be ONAME + w.selector(n.Right.Sym) case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: w.op(OXDOT) diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 5f107eeec7e..107e96cc6ad 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -866,7 +866,7 @@ func (r *importReader) node() *Node { // unreachable - handled in case OSTRUCTLIT by elemList // case OCALLPART: - // unimplemented + // unreachable - mapped to case OXDOT below by exporter // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: // unreachable - mapped to case OXDOT below by exporter diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index ba12cf40b51..55a14d378e0 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -374,8 +374,10 @@ func (v *hairyVisitor) visit(n *Node) bool { v.reason = "call to recover" return true + case OCALLPART: + // OCALLPART is inlineable, but no extra cost to the budget + case OCLOSURE, - OCALLPART, ORANGE, OSELECT, OTYPESW, @@ -454,7 +456,7 @@ func inlcopy(n *Node) *Node { } m := n.copy() - if m.Func != nil { + if n.Op != OCALLPART && m.Func != nil { Fatalf("unexpected Func: %v", m) } m.Left = inlcopy(n.Left) diff --git a/test/inline.go b/test/inline.go index 0e41873de4b..9b75bc50658 100644 --- a/test/inline.go +++ b/test/inline.go @@ -229,3 +229,20 @@ Loop: } } } + +// Issue #18493 - make sure we can do inlining of functions with a method value +type T1 struct{} + +func (a T1) meth(val int) int { // ERROR "can inline T1.meth" "inlining call to T1.meth" + return val + 5 +} + +func getMeth(t1 T1) func(int) int { // ERROR "can inline getMeth" + return t1.meth // ERROR "t1.meth escapes to heap" +} + +func ii() { // ERROR "can inline ii" + var t1 T1 + f := getMeth(t1) // ERROR "inlining call to getMeth" "t1.meth does not escape" + _ = f(3) +} From a4ede9f9a6254360d39d0f45aec133c355ac6b2a Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 9 Oct 2020 11:49:59 -0400 Subject: [PATCH 015/403] os: add File.ReadDir method and DirEntry type ReadDir provides a portable, efficient way to read a directory and discover the type of directory entries. This enables a more efficient file system walk, yet to be added. See #41467 for the proposal review for the API. Fixes #41467. Change-Id: I461a526793ae46df48821aa448b04f1705546739 Reviewed-on: https://go-review.googlesource.com/c/go/+/261540 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Rob Pike --- src/os/dir.go | 62 ++++++++++++++++++- src/os/dir_darwin.go | 62 ++++++++++++++++--- src/os/dir_plan9.go | 42 ++++++++----- src/os/dir_unix.go | 122 +++++++++++++++++++++++++++++++++--- src/os/dir_windows.go | 51 ++++++++------- src/os/dirent_aix.go | 30 +++++++++ src/os/dirent_dragonfly.go | 55 ++++++++++++++++ src/os/dirent_freebsd.go | 47 ++++++++++++++ src/os/dirent_js.go | 30 +++++++++ src/os/dirent_linux.go | 51 +++++++++++++++ src/os/dirent_netbsd.go | 47 ++++++++++++++ src/os/dirent_openbsd.go | 47 ++++++++++++++ src/os/dirent_solaris.go | 30 +++++++++ src/os/endian_big.go | 9 +++ src/os/endian_little.go | 9 +++ src/os/export_test.go | 1 + src/os/file_unix.go | 66 +++++++++++--------- src/os/os_test.go | 124 ++++++++++++++++++++++++++++++++----- src/os/stat_plan9.go | 2 +- src/os/types.go | 7 ++- 20 files changed, 784 insertions(+), 110 deletions(-) create mode 100644 src/os/dirent_aix.go create mode 100644 src/os/dirent_dragonfly.go create mode 100644 src/os/dirent_freebsd.go create mode 100644 src/os/dirent_js.go create mode 100644 src/os/dirent_linux.go create mode 100644 src/os/dirent_netbsd.go create mode 100644 src/os/dirent_openbsd.go create mode 100644 src/os/dirent_solaris.go create mode 100644 src/os/endian_big.go create mode 100644 src/os/endian_little.go diff --git a/src/os/dir.go b/src/os/dir.go index 1d7ced8061c..a3120017043 100644 --- a/src/os/dir.go +++ b/src/os/dir.go @@ -4,6 +4,14 @@ package os +type readdirMode int + +const ( + readdirName readdirMode = iota + readdirDirEntry + readdirFileInfo +) + // Readdir reads the contents of the directory associated with file and // returns a slice of up to n FileInfo values, as would be returned // by Lstat, in directory order. Subsequent calls on the same file will yield @@ -19,11 +27,14 @@ package os // nil error. If it encounters an error before the end of the // directory, Readdir returns the FileInfo read until that point // and a non-nil error. +// +// Most clients are better served by the more efficient ReadDir method. func (f *File) Readdir(n int) ([]FileInfo, error) { if f == nil { return nil, ErrInvalid } - return f.readdir(n) + _, _, infos, err := f.readdir(n, readdirFileInfo) + return infos, err } // Readdirnames reads the contents of the directory associated with file @@ -45,5 +56,52 @@ func (f *File) Readdirnames(n int) (names []string, err error) { if f == nil { return nil, ErrInvalid } - return f.readdirnames(n) + names, _, _, err = f.readdir(n, readdirName) + return names, err } + +// A DirEntry is an entry read from a directory +// (using the ReadDir function or a File's ReadDir method). +type DirEntry interface { + // Name returns the name of the file (or subdirectory) described by the entry. + // This name is only the final element of the path, not the entire path. + // For example, Name would return "hello.go" not "/home/gopher/hello.go". + Name() string + + // IsDir reports whether the entry describes a subdirectory. + IsDir() bool + + // Type returns the type bits for the entry. + // The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method. + Type() FileMode + + // Info returns the FileInfo for the file or subdirectory described by the entry. + // The returned FileInfo may be from the time of the original directory read + // or from the time of the call to Info. If the file has been removed or renamed + // since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist). + // If the entry denotes a symbolic link, Info reports the information about the link itself, + // not the link's target. + Info() (FileInfo, error) +} + +// ReadDir reads the contents of the directory associated with the file f +// and returns a slice of DirEntry values in directory order. +// Subsequent calls on the same file will yield later DirEntry records in the directory. +// +// If n > 0, ReadDir returns at most n DirEntry records. +// In this case, if ReadDir returns an empty slice, it will return an error explaining why. +// At the end of a directory, the error is io.EOF. +// +// If n <= 0, ReadDir returns all the DirEntry records remaining in the directory. +// When it succeeds, it returns a nil error (not io.EOF). +func (f *File) ReadDir(n int) ([]DirEntry, error) { + if f == nil { + return nil, ErrInvalid + } + _, dirents, _, err := f.readdir(n, readdirDirEntry) + return dirents, err +} + +// testingForceReadDirLstat forces ReadDir to call Lstat, for testing that code path. +// This can be difficult to provoke on some Unix systems otherwise. +var testingForceReadDirLstat bool diff --git a/src/os/dir_darwin.go b/src/os/dir_darwin.go index 476af6862e6..deba3eb37f1 100644 --- a/src/os/dir_darwin.go +++ b/src/os/dir_darwin.go @@ -24,11 +24,11 @@ func (d *dirInfo) close() { d.dir = 0 } -func (f *File) readdirnames(n int) (names []string, err error) { +func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) { if f.dirinfo == nil { dir, call, errno := f.pfd.OpenDir() if errno != nil { - return nil, &PathError{call, f.name, errno} + return nil, nil, nil, &PathError{Op: call, Path: f.name, Err: errno} } f.dirinfo = &dirInfo{ dir: dir, @@ -42,15 +42,14 @@ func (f *File) readdirnames(n int) (names []string, err error) { n = -1 } - names = make([]string, 0, size) var dirent syscall.Dirent var entptr *syscall.Dirent - for len(names) < size || n == -1 { + for len(names)+len(dirents)+len(infos) < size || n == -1 { if errno := readdir_r(d.dir, &dirent, &entptr); errno != 0 { if errno == syscall.EINTR { continue } - return names, &PathError{"readdir", f.name, errno} + return names, dirents, infos, &PathError{Op: "readdir", Path: f.name, Err: errno} } if entptr == nil { // EOF break @@ -69,13 +68,58 @@ func (f *File) readdirnames(n int) (names []string, err error) { if string(name) == "." || string(name) == ".." { continue } - names = append(names, string(name)) + if mode == readdirName { + names = append(names, string(name)) + } else if mode == readdirDirEntry { + de, err := newUnixDirent(f.name, string(name), dtToType(dirent.Type)) + if IsNotExist(err) { + // File disappeared between readdir and stat. + // Treat as if it didn't exist. + continue + } + if err != nil { + return nil, dirents, nil, err + } + dirents = append(dirents, de) + } else { + info, err := lstat(f.name + "/" + string(name)) + if IsNotExist(err) { + // File disappeared between readdir + stat. + // Treat as if it didn't exist. + continue + } + if err != nil { + return nil, nil, infos, err + } + infos = append(infos, info) + } runtime.KeepAlive(f) } - if n >= 0 && len(names) == 0 { - return names, io.EOF + + if n > 0 && len(names)+len(dirents)+len(infos) == 0 { + return nil, nil, nil, io.EOF } - return names, nil + return names, dirents, infos, nil +} + +func dtToType(typ uint8) FileMode { + switch typ { + case syscall.DT_BLK: + return ModeDevice + case syscall.DT_CHR: + return ModeDevice | ModeCharDevice + case syscall.DT_DIR: + return ModeDir + case syscall.DT_FIFO: + return ModeNamedPipe + case syscall.DT_LNK: + return ModeSymlink + case syscall.DT_REG: + return 0 + case syscall.DT_SOCK: + return ModeSocket + } + return ^FileMode(0) } // Implemented in syscall/syscall_darwin.go. diff --git a/src/os/dir_plan9.go b/src/os/dir_plan9.go index 8195c02a465..5e6376282ca 100644 --- a/src/os/dir_plan9.go +++ b/src/os/dir_plan9.go @@ -9,7 +9,7 @@ import ( "syscall" ) -func (file *File) readdir(n int) ([]FileInfo, error) { +func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) { // If this file has no dirinfo, create one. if file.dirinfo == nil { file.dirinfo = new(dirInfo) @@ -20,7 +20,6 @@ func (file *File) readdir(n int) ([]FileInfo, error) { size = 100 n = -1 } - fi := make([]FileInfo, 0, size) // Empty with room to grow. for n != 0 { // Refill the buffer if necessary. if d.bufp >= d.nbuf { @@ -33,10 +32,10 @@ func (file *File) readdir(n int) ([]FileInfo, error) { if err == io.EOF { break } - return fi, &PathError{"readdir", file.name, err} + return names, dirents, infos, &PathError{"readdir", file.name, err} } if nb < syscall.STATFIXLEN { - return fi, &PathError{"readdir", file.name, syscall.ErrShortStat} + return names, dirents, infos, &PathError{"readdir", file.name, syscall.ErrShortStat} } } @@ -44,30 +43,39 @@ func (file *File) readdir(n int) ([]FileInfo, error) { b := d.buf[d.bufp:] m := int(uint16(b[0])|uint16(b[1])<<8) + 2 if m < syscall.STATFIXLEN { - return fi, &PathError{"readdir", file.name, syscall.ErrShortStat} + return names, dirents, infos, &PathError{"readdir", file.name, syscall.ErrShortStat} } dir, err := syscall.UnmarshalDir(b[:m]) if err != nil { - return fi, &PathError{"readdir", file.name, err} + return names, dirents, infos, &PathError{"readdir", file.name, err} } - fi = append(fi, fileInfoFromStat(dir)) + if mode == readdirName { + names = append(names, dir.Name) + } else { + f := fileInfoFromStat(dir) + if mode == readdirDirEntry { + dirents = append(dirents, dirEntry{f}) + } else { + infos = append(infos, f) + } + } d.bufp += m n-- } - if n >= 0 && len(fi) == 0 { - return fi, io.EOF + if n > 0 && len(names)+len(dirents)+len(infos) == 0 { + return nil, nil, nil, io.EOF } - return fi, nil + return names, dirents, infos, nil } -func (file *File) readdirnames(n int) (names []string, err error) { - fi, err := file.Readdir(n) - names = make([]string, len(fi)) - for i := range fi { - names[i] = fi[i].Name() - } - return +type dirEntry struct { + fs *fileStat } + +func (de dirEntry) Name() string { return de.fs.Name() } +func (de dirEntry) IsDir() bool { return de.fs.IsDir() } +func (de dirEntry) Type() FileMode { return de.fs.Mode().Type() } +func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil } diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go index 58ec406ab87..22a4e715fe6 100644 --- a/src/os/dir_unix.go +++ b/src/os/dir_unix.go @@ -10,6 +10,7 @@ import ( "io" "runtime" "syscall" + "unsafe" ) // Auxiliary information if the File describes a directory @@ -26,7 +27,7 @@ const ( func (d *dirInfo) close() {} -func (f *File) readdirnames(n int) (names []string, err error) { +func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) { // If this file has no dirinfo, create one. if f.dirinfo == nil { f.dirinfo = new(dirInfo) @@ -41,7 +42,6 @@ func (f *File) readdirnames(n int) (names []string, err error) { n = -1 } - names = make([]string, 0, size) // Empty with room to grow. for n != 0 { // Refill the buffer if necessary if d.bufp >= d.nbuf { @@ -50,7 +50,7 @@ func (f *File) readdirnames(n int) (names []string, err error) { d.nbuf, errno = f.pfd.ReadDirent(d.buf) runtime.KeepAlive(f) if errno != nil { - return names, &PathError{"readdirent", f.name, errno} + return names, dirents, infos, &PathError{"readdirent", f.name, errno} } if d.nbuf <= 0 { break // EOF @@ -58,13 +58,115 @@ func (f *File) readdirnames(n int) (names []string, err error) { } // Drain the buffer - var nb, nc int - nb, nc, names = syscall.ParseDirent(d.buf[d.bufp:d.nbuf], n, names) - d.bufp += nb - n -= nc + buf := d.buf[d.bufp:d.nbuf] + reclen, ok := direntReclen(buf) + if !ok || reclen > uint64(len(buf)) { + break + } + rec := buf[:reclen] + d.bufp += int(reclen) + ino, ok := direntIno(rec) + if !ok { + break + } + if ino == 0 { + continue + } + const namoff = uint64(unsafe.Offsetof(syscall.Dirent{}.Name)) + namlen, ok := direntNamlen(rec) + if !ok || namoff+namlen > uint64(len(rec)) { + break + } + name := rec[namoff : namoff+namlen] + for i, c := range name { + if c == 0 { + name = name[:i] + break + } + } + // Check for useless names before allocating a string. + if string(name) == "." || string(name) == ".." { + continue + } + n-- + if mode == readdirName { + names = append(names, string(name)) + } else if mode == readdirDirEntry { + de, err := newUnixDirent(f.name, string(name), direntType(rec)) + if IsNotExist(err) { + // File disappeared between readdir and stat. + // Treat as if it didn't exist. + continue + } + if err != nil { + return nil, dirents, nil, err + } + dirents = append(dirents, de) + } else { + info, err := lstat(f.name + "/" + string(name)) + if IsNotExist(err) { + // File disappeared between readdir + stat. + // Treat as if it didn't exist. + continue + } + if err != nil { + return nil, nil, infos, err + } + infos = append(infos, info) + } } - if n >= 0 && len(names) == 0 { - return names, io.EOF + + if n > 0 && len(names)+len(dirents)+len(infos) == 0 { + return nil, nil, nil, io.EOF + } + return names, dirents, infos, nil +} + +// readInt returns the size-bytes unsigned integer in native byte order at offset off. +func readInt(b []byte, off, size uintptr) (u uint64, ok bool) { + if len(b) < int(off+size) { + return 0, false + } + if isBigEndian { + return readIntBE(b[off:], size), true + } + return readIntLE(b[off:], size), true +} + +func readIntBE(b []byte, size uintptr) uint64 { + switch size { + case 1: + return uint64(b[0]) + case 2: + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[1]) | uint64(b[0])<<8 + case 4: + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[3]) | uint64(b[2])<<8 | uint64(b[1])<<16 | uint64(b[0])<<24 + case 8: + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 | + uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56 + default: + panic("syscall: readInt with unsupported size") + } +} + +func readIntLE(b []byte, size uintptr) uint64 { + switch size { + case 1: + return uint64(b[0]) + case 2: + _ = b[1] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 + case 4: + _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 + case 8: + _ = b[7] // bounds check hint to compiler; see golang.org/issue/14808 + return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | + uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 + default: + panic("syscall: readInt with unsupported size") } - return names, nil } diff --git a/src/os/dir_windows.go b/src/os/dir_windows.go index 9e5d6bd5052..1c3f2f0d574 100644 --- a/src/os/dir_windows.go +++ b/src/os/dir_windows.go @@ -10,20 +10,14 @@ import ( "syscall" ) -func (file *File) readdir(n int) (fi []FileInfo, err error) { - if file == nil { - return nil, syscall.EINVAL - } +func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) { if !file.isdir() { - return nil, &PathError{"Readdir", file.name, syscall.ENOTDIR} + return nil, nil, nil, &PathError{"readdir", file.name, syscall.ENOTDIR} } wantAll := n <= 0 - size := n if wantAll { n = -1 - size = 100 } - fi = make([]FileInfo, 0, size) // Empty with room to grow. d := &file.dirinfo.data for n != 0 && !file.dirinfo.isempty { if file.dirinfo.needdata { @@ -34,9 +28,6 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) { break } else { err = &PathError{"FindNextFile", file.name, e} - if !wantAll { - fi = nil - } return } } @@ -46,24 +37,32 @@ func (file *File) readdir(n int) (fi []FileInfo, err error) { if name == "." || name == ".." { // Useless names continue } - f := newFileStatFromWin32finddata(d) - f.name = name - f.path = file.dirinfo.path - f.appendNameToPath = true + if mode == readdirName { + names = append(names, name) + } else { + f := newFileStatFromWin32finddata(d) + f.name = name + f.path = file.dirinfo.path + f.appendNameToPath = true + if mode == readdirDirEntry { + dirents = append(dirents, dirEntry{f}) + } else { + infos = append(infos, f) + } + } n-- - fi = append(fi, f) } - if !wantAll && len(fi) == 0 { - return fi, io.EOF + if !wantAll && len(names)+len(dirents)+len(infos) == 0 { + return nil, nil, nil, io.EOF } - return fi, nil + return names, dirents, infos, nil } -func (file *File) readdirnames(n int) (names []string, err error) { - fis, err := file.Readdir(n) - names = make([]string, len(fis)) - for i, fi := range fis { - names[i] = fi.Name() - } - return names, err +type dirEntry struct { + fs *fileStat } + +func (de dirEntry) Name() string { return de.fs.Name() } +func (de dirEntry) IsDir() bool { return de.fs.IsDir() } +func (de dirEntry) Type() FileMode { return de.fs.Mode().Type() } +func (de dirEntry) Info() (FileInfo, error) { return de.fs, nil } diff --git a/src/os/dirent_aix.go b/src/os/dirent_aix.go new file mode 100644 index 00000000000..5597b8af20e --- /dev/null +++ b/src/os/dirent_aix.go @@ -0,0 +1,30 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Ino), unsafe.Sizeof(syscall.Dirent{}.Ino)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + reclen, ok := direntReclen(buf) + if !ok { + return 0, false + } + return reclen - uint64(unsafe.Offsetof(syscall.Dirent{}.Name)), true +} + +func direntType(buf []byte) FileMode { + return ^FileMode(0) // unknown +} diff --git a/src/os/dirent_dragonfly.go b/src/os/dirent_dragonfly.go new file mode 100644 index 00000000000..38cbd61ed33 --- /dev/null +++ b/src/os/dirent_dragonfly.go @@ -0,0 +1,55 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Fileno), unsafe.Sizeof(syscall.Dirent{}.Fileno)) +} + +func direntReclen(buf []byte) (uint64, bool) { + namlen, ok := direntNamlen(buf) + if !ok { + return 0, false + } + return (16 + namlen + 1 + 7) &^ 7, true +} + +func direntNamlen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Namlen), unsafe.Sizeof(syscall.Dirent{}.Namlen)) +} + +func direntType(buf []byte) FileMode { + off := unsafe.Offsetof(syscall.Dirent{}.Type) + if off >= uintptr(len(buf)) { + return ^FileMode(0) // unknown + } + typ := buf[off] + switch typ { + case syscall.DT_BLK: + return ModeDevice + case syscall.DT_CHR: + return ModeDevice | ModeCharDevice + case syscall.DT_DBF: + // DT_DBF is "database record file". + // fillFileStatFromSys treats as regular file. + return 0 + case syscall.DT_DIR: + return ModeDir + case syscall.DT_FIFO: + return ModeNamedPipe + case syscall.DT_LNK: + return ModeSymlink + case syscall.DT_REG: + return 0 + case syscall.DT_SOCK: + return ModeSocket + } + return ^FileMode(0) // unknown +} diff --git a/src/os/dirent_freebsd.go b/src/os/dirent_freebsd.go new file mode 100644 index 00000000000..d600837ebb1 --- /dev/null +++ b/src/os/dirent_freebsd.go @@ -0,0 +1,47 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Fileno), unsafe.Sizeof(syscall.Dirent{}.Fileno)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Namlen), unsafe.Sizeof(syscall.Dirent{}.Namlen)) +} + +func direntType(buf []byte) FileMode { + off := unsafe.Offsetof(syscall.Dirent{}.Type) + if off >= uintptr(len(buf)) { + return ^FileMode(0) // unknown + } + typ := buf[off] + switch typ { + case syscall.DT_BLK: + return ModeDevice + case syscall.DT_CHR: + return ModeDevice | ModeCharDevice + case syscall.DT_DIR: + return ModeDir + case syscall.DT_FIFO: + return ModeNamedPipe + case syscall.DT_LNK: + return ModeSymlink + case syscall.DT_REG: + return 0 + case syscall.DT_SOCK: + return ModeSocket + } + return ^FileMode(0) // unknown +} diff --git a/src/os/dirent_js.go b/src/os/dirent_js.go new file mode 100644 index 00000000000..31778c2ad85 --- /dev/null +++ b/src/os/dirent_js.go @@ -0,0 +1,30 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return 1, true +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + reclen, ok := direntReclen(buf) + if !ok { + return 0, false + } + return reclen - uint64(unsafe.Offsetof(syscall.Dirent{}.Name)), true +} + +func direntType(buf []byte) FileMode { + return ^FileMode(0) // unknown +} diff --git a/src/os/dirent_linux.go b/src/os/dirent_linux.go new file mode 100644 index 00000000000..74a34311212 --- /dev/null +++ b/src/os/dirent_linux.go @@ -0,0 +1,51 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Ino), unsafe.Sizeof(syscall.Dirent{}.Ino)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + reclen, ok := direntReclen(buf) + if !ok { + return 0, false + } + return reclen - uint64(unsafe.Offsetof(syscall.Dirent{}.Name)), true +} + +func direntType(buf []byte) FileMode { + off := unsafe.Offsetof(syscall.Dirent{}.Type) + if off >= uintptr(len(buf)) { + return ^FileMode(0) // unknown + } + typ := buf[off] + switch typ { + case syscall.DT_BLK: + return ModeDevice + case syscall.DT_CHR: + return ModeDevice | ModeCharDevice + case syscall.DT_DIR: + return ModeDir + case syscall.DT_FIFO: + return ModeNamedPipe + case syscall.DT_LNK: + return ModeSymlink + case syscall.DT_REG: + return 0 + case syscall.DT_SOCK: + return ModeSocket + } + return ^FileMode(0) // unknown +} diff --git a/src/os/dirent_netbsd.go b/src/os/dirent_netbsd.go new file mode 100644 index 00000000000..d600837ebb1 --- /dev/null +++ b/src/os/dirent_netbsd.go @@ -0,0 +1,47 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Fileno), unsafe.Sizeof(syscall.Dirent{}.Fileno)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Namlen), unsafe.Sizeof(syscall.Dirent{}.Namlen)) +} + +func direntType(buf []byte) FileMode { + off := unsafe.Offsetof(syscall.Dirent{}.Type) + if off >= uintptr(len(buf)) { + return ^FileMode(0) // unknown + } + typ := buf[off] + switch typ { + case syscall.DT_BLK: + return ModeDevice + case syscall.DT_CHR: + return ModeDevice | ModeCharDevice + case syscall.DT_DIR: + return ModeDir + case syscall.DT_FIFO: + return ModeNamedPipe + case syscall.DT_LNK: + return ModeSymlink + case syscall.DT_REG: + return 0 + case syscall.DT_SOCK: + return ModeSocket + } + return ^FileMode(0) // unknown +} diff --git a/src/os/dirent_openbsd.go b/src/os/dirent_openbsd.go new file mode 100644 index 00000000000..d600837ebb1 --- /dev/null +++ b/src/os/dirent_openbsd.go @@ -0,0 +1,47 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Fileno), unsafe.Sizeof(syscall.Dirent{}.Fileno)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Namlen), unsafe.Sizeof(syscall.Dirent{}.Namlen)) +} + +func direntType(buf []byte) FileMode { + off := unsafe.Offsetof(syscall.Dirent{}.Type) + if off >= uintptr(len(buf)) { + return ^FileMode(0) // unknown + } + typ := buf[off] + switch typ { + case syscall.DT_BLK: + return ModeDevice + case syscall.DT_CHR: + return ModeDevice | ModeCharDevice + case syscall.DT_DIR: + return ModeDir + case syscall.DT_FIFO: + return ModeNamedPipe + case syscall.DT_LNK: + return ModeSymlink + case syscall.DT_REG: + return 0 + case syscall.DT_SOCK: + return ModeSocket + } + return ^FileMode(0) // unknown +} diff --git a/src/os/dirent_solaris.go b/src/os/dirent_solaris.go new file mode 100644 index 00000000000..5597b8af20e --- /dev/null +++ b/src/os/dirent_solaris.go @@ -0,0 +1,30 @@ +// Copyright 2020 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 os + +import ( + "syscall" + "unsafe" +) + +func direntIno(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Ino), unsafe.Sizeof(syscall.Dirent{}.Ino)) +} + +func direntReclen(buf []byte) (uint64, bool) { + return readInt(buf, unsafe.Offsetof(syscall.Dirent{}.Reclen), unsafe.Sizeof(syscall.Dirent{}.Reclen)) +} + +func direntNamlen(buf []byte) (uint64, bool) { + reclen, ok := direntReclen(buf) + if !ok { + return 0, false + } + return reclen - uint64(unsafe.Offsetof(syscall.Dirent{}.Name)), true +} + +func direntType(buf []byte) FileMode { + return ^FileMode(0) // unknown +} diff --git a/src/os/endian_big.go b/src/os/endian_big.go new file mode 100644 index 00000000000..c98f1247822 --- /dev/null +++ b/src/os/endian_big.go @@ -0,0 +1,9 @@ +// Copyright 2016 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. +// +// +build ppc64 s390x mips mips64 + +package os + +const isBigEndian = true diff --git a/src/os/endian_little.go b/src/os/endian_little.go new file mode 100644 index 00000000000..3efc5e0d8d4 --- /dev/null +++ b/src/os/endian_little.go @@ -0,0 +1,9 @@ +// Copyright 2016 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. +// +// +build 386 amd64 arm arm64 ppc64le mips64le mipsle riscv64 wasm + +package os + +const isBigEndian = false diff --git a/src/os/export_test.go b/src/os/export_test.go index 812432cee48..d66264a68f1 100644 --- a/src/os/export_test.go +++ b/src/os/export_test.go @@ -9,3 +9,4 @@ package os var Atime = atime var LstatP = &lstat var ErrWriteAtInAppendMode = errWriteAtInAppendMode +var TestingForceReadDirLstat = &testingForceReadDirLstat diff --git a/src/os/file_unix.go b/src/os/file_unix.go index e0f16d809d2..3cb4ffbf33e 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -9,7 +9,6 @@ package os import ( "internal/poll" "internal/syscall/unix" - "io" "runtime" "syscall" ) @@ -353,33 +352,6 @@ func Symlink(oldname, newname string) error { return nil } -func (f *File) readdir(n int) (fi []FileInfo, err error) { - dirname := f.name - if dirname == "" { - dirname = "." - } - names, err := f.Readdirnames(n) - fi = make([]FileInfo, 0, len(names)) - for _, filename := range names { - fip, lerr := lstat(dirname + "/" + filename) - if IsNotExist(lerr) { - // File disappeared between readdir + stat. - // Just treat it as if it didn't exist. - continue - } - if lerr != nil { - return fi, lerr - } - fi = append(fi, fip) - } - if len(fi) == 0 && err == nil && n > 0 { - // Per File.Readdir, the slice must be non-empty or err - // must be non-nil if n > 0. - err = io.EOF - } - return fi, err -} - // Readlink returns the destination of the named symbolic link. // If there is an error, it will be of type *PathError. func Readlink(name string) (string, error) { @@ -407,3 +379,41 @@ func Readlink(name string) (string, error) { } } } + +type unixDirent struct { + parent string + name string + typ FileMode + info FileInfo +} + +func (d *unixDirent) Name() string { return d.name } +func (d *unixDirent) IsDir() bool { return d.typ.IsDir() } +func (d *unixDirent) Type() FileMode { return d.typ } + +func (d *unixDirent) Info() (FileInfo, error) { + if d.info != nil { + return d.info, nil + } + return lstat(d.parent + "/" + d.name) +} + +func newUnixDirent(parent, name string, typ FileMode) (DirEntry, error) { + ude := &unixDirent{ + parent: parent, + name: name, + typ: typ, + } + if typ != ^FileMode(0) && !testingForceReadDirLstat { + return ude, nil + } + + info, err := lstat(parent + "/" + name) + if err != nil { + return nil, err + } + + ude.typ = info.Mode().Type() + ude.info = info + return ude, nil +} diff --git a/src/os/os_test.go b/src/os/os_test.go index 865dfcc0def..c692ba099f9 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -309,20 +309,21 @@ func testReaddirnames(dir string, contents []string, t *testing.T) { defer file.Close() s, err2 := file.Readdirnames(-1) if err2 != nil { - t.Fatalf("readdirnames %q failed: %v", dir, err2) + t.Fatalf("Readdirnames %q failed: %v", dir, err2) } for _, m := range contents { found := false for _, n := range s { if n == "." || n == ".." { - t.Errorf("got %s in directory", n) + t.Errorf("got %q in directory", n) } - if equal(m, n) { - if found { - t.Error("present twice:", m) - } - found = true + if !equal(m, n) { + continue } + if found { + t.Error("present twice:", m) + } + found = true } if !found { t.Error("could not find", m) @@ -338,16 +339,68 @@ func testReaddir(dir string, contents []string, t *testing.T) { defer file.Close() s, err2 := file.Readdir(-1) if err2 != nil { - t.Fatalf("readdir %q failed: %v", dir, err2) + t.Fatalf("Readdir %q failed: %v", dir, err2) } for _, m := range contents { found := false for _, n := range s { - if equal(m, n.Name()) { - if found { - t.Error("present twice:", m) - } - found = true + if n.Name() == "." || n.Name() == ".." { + t.Errorf("got %q in directory", n.Name()) + } + if !equal(m, n.Name()) { + continue + } + if found { + t.Error("present twice:", m) + } + found = true + } + if !found { + t.Error("could not find", m) + } + } +} + +func testReadDir(dir string, contents []string, t *testing.T) { + file, err := Open(dir) + if err != nil { + t.Fatalf("open %q failed: %v", dir, err) + } + defer file.Close() + s, err2 := file.ReadDir(-1) + if err2 != nil { + t.Fatalf("ReadDir %q failed: %v", dir, err2) + } + for _, m := range contents { + found := false + for _, n := range s { + if n.Name() == "." || n.Name() == ".." { + t.Errorf("got %q in directory", n) + } + if !equal(m, n.Name()) { + continue + } + if found { + t.Error("present twice:", m) + } + found = true + lstat, err := Lstat(dir + "/" + m) + if err != nil { + t.Fatal(err) + } + if n.IsDir() != lstat.IsDir() { + t.Errorf("%s: IsDir=%v, want %v", m, n.IsDir(), lstat.IsDir()) + } + if n.Type() != lstat.Mode().Type() { + t.Errorf("%s: IsDir=%v, want %v", m, n.Type(), lstat.Mode().Type()) + } + info, err := n.Info() + if err != nil { + t.Errorf("%s: Info: %v", m, err) + continue + } + if !SameFile(info, lstat) { + t.Errorf("%s: Info: SameFile(info, lstat) = false", m) } } if !found { @@ -366,6 +419,11 @@ func TestReaddir(t *testing.T) { testReaddir(sysdir.name, sysdir.files, t) } +func TestReadDir(t *testing.T) { + testReadDir(".", dot, t) + testReadDir(sysdir.name, sysdir.files, t) +} + func benchmarkReaddirname(path string, b *testing.B) { var nentries int for i := 0; i < b.N; i++ { @@ -400,6 +458,23 @@ func benchmarkReaddir(path string, b *testing.B) { b.Logf("benchmarkReaddir %q: %d entries", path, nentries) } +func benchmarkReadDir(path string, b *testing.B) { + var nentries int + for i := 0; i < b.N; i++ { + f, err := Open(path) + if err != nil { + b.Fatalf("open %q failed: %v", path, err) + } + fs, err := f.ReadDir(-1) + f.Close() + if err != nil { + b.Fatalf("readdir %q failed: %v", path, err) + } + nentries = len(fs) + } + b.Logf("benchmarkReadDir %q: %d entries", path, nentries) +} + func BenchmarkReaddirname(b *testing.B) { benchmarkReaddirname(".", b) } @@ -408,6 +483,10 @@ func BenchmarkReaddir(b *testing.B) { benchmarkReaddir(".", b) } +func BenchmarkReadDir(b *testing.B) { + benchmarkReadDir(".", b) +} + func benchmarkStat(b *testing.B, path string) { b.ResetTimer() for i := 0; i < b.N; i++ { @@ -547,7 +626,8 @@ func TestReaddirNValues(t *testing.T) { } } - readDirExpect := func(n, want int, wantErr error) { + readdirExpect := func(n, want int, wantErr error) { + t.Helper() fi, err := d.Readdir(n) if err != wantErr { t.Fatalf("Readdir of %d got error %v, want %v", n, err, wantErr) @@ -557,7 +637,19 @@ func TestReaddirNValues(t *testing.T) { } } - readDirNamesExpect := func(n, want int, wantErr error) { + readDirExpect := func(n, want int, wantErr error) { + t.Helper() + de, err := d.ReadDir(n) + if err != wantErr { + t.Fatalf("ReadDir of %d got error %v, want %v", n, err, wantErr) + } + if g, e := len(de), want; g != e { + t.Errorf("ReadDir of %d got %d files, want %d", n, g, e) + } + } + + readdirnamesExpect := func(n, want int, wantErr error) { + t.Helper() fi, err := d.Readdirnames(n) if err != wantErr { t.Fatalf("Readdirnames of %d got error %v, want %v", n, err, wantErr) @@ -567,7 +659,7 @@ func TestReaddirNValues(t *testing.T) { } } - for _, fn := range []func(int, int, error){readDirExpect, readDirNamesExpect} { + for _, fn := range []func(int, int, error){readdirExpect, readdirnamesExpect, readDirExpect} { // Test the slurp case openDir() fn(0, 105, nil) diff --git a/src/os/stat_plan9.go b/src/os/stat_plan9.go index b43339afa43..7ac2695df87 100644 --- a/src/os/stat_plan9.go +++ b/src/os/stat_plan9.go @@ -11,7 +11,7 @@ import ( const bitSize16 = 2 -func fileInfoFromStat(d *syscall.Dir) FileInfo { +func fileInfoFromStat(d *syscall.Dir) *fileStat { fs := &fileStat{ name: d.Name, size: d.Length, diff --git a/src/os/types.go b/src/os/types.go index 4b6c084838b..0f51a48286a 100644 --- a/src/os/types.go +++ b/src/os/types.go @@ -100,11 +100,16 @@ func (m FileMode) IsRegular() bool { return m&ModeType == 0 } -// Perm returns the Unix permission bits in m. +// Perm returns the Unix permission bits in m (m & ModePerm). func (m FileMode) Perm() FileMode { return m & ModePerm } +// Type returns type bits in m (m & ModeType). +func (m FileMode) Type() FileMode { + return m & ModeType +} + func (fs *fileStat) Name() string { return fs.name } func (fs *fileStat) IsDir() bool { return fs.Mode().IsDir() } From 2291cae2af659876e93a3e1f95c708abb1475d02 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 3 Jul 2020 12:25:49 -0400 Subject: [PATCH 016/403] os: use keyed literals for PathError Necessary to move PathError to io/fs. For #41190. Change-Id: I05e87675f38a22f0570d4366b751b6169f7a1b13 Reviewed-on: https://go-review.googlesource.com/c/go/+/243900 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Rob Pike Reviewed-by: Ian Lance Taylor --- src/os/dir_plan9.go | 8 +++---- src/os/dir_unix.go | 2 +- src/os/dir_windows.go | 4 ++-- src/os/exec_plan9.go | 2 +- src/os/exec_posix.go | 2 +- src/os/file.go | 12 +++++----- src/os/file_plan9.go | 50 ++++++++++++++++++++-------------------- src/os/file_posix.go | 8 +++---- src/os/file_unix.go | 10 ++++---- src/os/file_windows.go | 14 +++++------ src/os/path.go | 2 +- src/os/removeall_at.go | 14 +++++------ src/os/removeall_noat.go | 2 +- src/os/stat_plan9.go | 6 ++--- src/os/stat_unix.go | 6 ++--- src/os/stat_windows.go | 10 ++++---- src/os/types_windows.go | 6 ++--- 17 files changed, 79 insertions(+), 79 deletions(-) diff --git a/src/os/dir_plan9.go b/src/os/dir_plan9.go index 5e6376282ca..8f6b0d61098 100644 --- a/src/os/dir_plan9.go +++ b/src/os/dir_plan9.go @@ -32,10 +32,10 @@ func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []Di if err == io.EOF { break } - return names, dirents, infos, &PathError{"readdir", file.name, err} + return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err} } if nb < syscall.STATFIXLEN { - return names, dirents, infos, &PathError{"readdir", file.name, syscall.ErrShortStat} + return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat} } } @@ -43,12 +43,12 @@ func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []Di b := d.buf[d.bufp:] m := int(uint16(b[0])|uint16(b[1])<<8) + 2 if m < syscall.STATFIXLEN { - return names, dirents, infos, &PathError{"readdir", file.name, syscall.ErrShortStat} + return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: syscall.ErrShortStat} } dir, err := syscall.UnmarshalDir(b[:m]) if err != nil { - return names, dirents, infos, &PathError{"readdir", file.name, err} + return names, dirents, infos, &PathError{Op: "readdir", Path: file.name, Err: err} } if mode == readdirName { diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go index 22a4e715fe6..3e5a6983501 100644 --- a/src/os/dir_unix.go +++ b/src/os/dir_unix.go @@ -50,7 +50,7 @@ func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEn d.nbuf, errno = f.pfd.ReadDirent(d.buf) runtime.KeepAlive(f) if errno != nil { - return names, dirents, infos, &PathError{"readdirent", f.name, errno} + return names, dirents, infos, &PathError{Op: "readdirent", Path: f.name, Err: errno} } if d.nbuf <= 0 { break // EOF diff --git a/src/os/dir_windows.go b/src/os/dir_windows.go index 1c3f2f0d574..253adad0b90 100644 --- a/src/os/dir_windows.go +++ b/src/os/dir_windows.go @@ -12,7 +12,7 @@ import ( func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEntry, infos []FileInfo, err error) { if !file.isdir() { - return nil, nil, nil, &PathError{"readdir", file.name, syscall.ENOTDIR} + return nil, nil, nil, &PathError{Op: "readdir", Path: file.name, Err: syscall.ENOTDIR} } wantAll := n <= 0 if wantAll { @@ -27,7 +27,7 @@ func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []Di if e == syscall.ERROR_NO_MORE_FILES { break } else { - err = &PathError{"FindNextFile", file.name, e} + err = &PathError{Op: "FindNextFile", Path: file.name, Err: e} return } } diff --git a/src/os/exec_plan9.go b/src/os/exec_plan9.go index b0abf743ddb..ef8dad11b61 100644 --- a/src/os/exec_plan9.go +++ b/src/os/exec_plan9.go @@ -34,7 +34,7 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e pid, h, e := syscall.StartProcess(name, argv, sysattr) if e != nil { - return nil, &PathError{"fork/exec", name, e} + return nil, &PathError{Op: "fork/exec", Path: name, Err: e} } return newProcess(pid, h), nil diff --git a/src/os/exec_posix.go b/src/os/exec_posix.go index 45b47a542d6..7ecddaed374 100644 --- a/src/os/exec_posix.go +++ b/src/os/exec_posix.go @@ -56,7 +56,7 @@ func startProcess(name string, argv []string, attr *ProcAttr) (p *Process, err e runtime.KeepAlive(attr) if e != nil { - return nil, &PathError{"fork/exec", name, e} + return nil, &PathError{Op: "fork/exec", Path: name, Err: e} } return newProcess(pid, h), nil diff --git a/src/os/file.go b/src/os/file.go index 05d2f832831..5f16fc28eea 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -127,7 +127,7 @@ func (f *File) ReadAt(b []byte, off int64) (n int, err error) { } if off < 0 { - return 0, &PathError{"readat", f.name, errors.New("negative offset")} + return 0, &PathError{Op: "readat", Path: f.name, Err: errors.New("negative offset")} } for len(b) > 0 { @@ -203,7 +203,7 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) { } if off < 0 { - return 0, &PathError{"writeat", f.name, errors.New("negative offset")} + return 0, &PathError{Op: "writeat", Path: f.name, Err: errors.New("negative offset")} } for len(b) > 0 { @@ -253,7 +253,7 @@ func (f *File) WriteString(s string) (n int, err error) { // If there is an error, it will be of type *PathError. func Mkdir(name string, perm FileMode) error { if runtime.GOOS == "windows" && isWindowsNulName(name) { - return &PathError{"mkdir", name, syscall.ENOTDIR} + return &PathError{Op: "mkdir", Path: name, Err: syscall.ENOTDIR} } longName := fixLongPath(name) e := ignoringEINTR(func() error { @@ -261,7 +261,7 @@ func Mkdir(name string, perm FileMode) error { }) if e != nil { - return &PathError{"mkdir", name, e} + return &PathError{Op: "mkdir", Path: name, Err: e} } // mkdir(2) itself won't handle the sticky bit on *BSD and Solaris @@ -291,7 +291,7 @@ func setStickyBit(name string) error { func Chdir(dir string) error { if e := syscall.Chdir(dir); e != nil { testlog.Open(dir) // observe likely non-existent directory - return &PathError{"chdir", dir, e} + return &PathError{Op: "chdir", Path: dir, Err: e} } if log := testlog.Logger(); log != nil { wd, err := Getwd() @@ -366,7 +366,7 @@ func (f *File) wrapErr(op string, err error) error { if err == poll.ErrFileClosing { err = ErrClosed } - return &PathError{op, f.name, err} + return &PathError{Op: op, Path: f.name, Err: err} } // TempDir returns the default directory to use for temporary files. diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go index a1a51a1c06f..bbc732838a5 100644 --- a/src/os/file_plan9.go +++ b/src/os/file_plan9.go @@ -119,18 +119,18 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) { if IsNotExist(e) && create { fd, e = syscall.Create(name, flag, syscallMode(perm)) if e != nil { - return nil, &PathError{"create", name, e} + return nil, &PathError{Op: "create", Path: name, Err: e} } } } if e != nil { - return nil, &PathError{"open", name, e} + return nil, &PathError{Op: "open", Path: name, Err: e} } if append { if _, e = syscall.Seek(fd, 0, io.SeekEnd); e != nil { - return nil, &PathError{"seek", name, e} + return nil, &PathError{Op: "seek", Path: name, Err: e} } } @@ -154,7 +154,7 @@ func (file *file) close() error { } var err error if e := syscall.Close(file.fd); e != nil { - err = &PathError{"close", file.name, e} + err = &PathError{Op: "close", Path: file.name, Err: e} } file.fd = badFd // so it can't be closed again @@ -191,10 +191,10 @@ func (f *File) Truncate(size int64) error { var buf [syscall.STATFIXLEN]byte n, err := d.Marshal(buf[:]) if err != nil { - return &PathError{"truncate", f.name, err} + return &PathError{Op: "truncate", Path: f.name, Err: err} } if err = syscall.Fwstat(f.fd, buf[:n]); err != nil { - return &PathError{"truncate", f.name, err} + return &PathError{Op: "truncate", Path: f.name, Err: err} } return nil } @@ -209,7 +209,7 @@ func (f *File) chmod(mode FileMode) error { odir, e := dirstat(f) if e != nil { - return &PathError{"chmod", f.name, e} + return &PathError{Op: "chmod", Path: f.name, Err: e} } d.Null() d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask @@ -217,10 +217,10 @@ func (f *File) chmod(mode FileMode) error { var buf [syscall.STATFIXLEN]byte n, err := d.Marshal(buf[:]) if err != nil { - return &PathError{"chmod", f.name, err} + return &PathError{Op: "chmod", Path: f.name, Err: err} } if err = syscall.Fwstat(f.fd, buf[:n]); err != nil { - return &PathError{"chmod", f.name, err} + return &PathError{Op: "chmod", Path: f.name, Err: err} } return nil } @@ -238,10 +238,10 @@ func (f *File) Sync() error { var buf [syscall.STATFIXLEN]byte n, err := d.Marshal(buf[:]) if err != nil { - return &PathError{"sync", f.name, err} + return &PathError{Op: "sync", Path: f.name, Err: err} } if err = syscall.Fwstat(f.fd, buf[:n]); err != nil { - return &PathError{"sync", f.name, err} + return &PathError{Op: "sync", Path: f.name, Err: err} } return nil } @@ -314,10 +314,10 @@ func Truncate(name string, size int64) error { var buf [syscall.STATFIXLEN]byte n, err := d.Marshal(buf[:]) if err != nil { - return &PathError{"truncate", name, err} + return &PathError{Op: "truncate", Path: name, Err: err} } if err = syscall.Wstat(name, buf[:n]); err != nil { - return &PathError{"truncate", name, err} + return &PathError{Op: "truncate", Path: name, Err: err} } return nil } @@ -326,7 +326,7 @@ func Truncate(name string, size int64) error { // If there is an error, it will be of type *PathError. func Remove(name string) error { if e := syscall.Remove(name); e != nil { - return &PathError{"remove", name, e} + return &PathError{Op: "remove", Path: name, Err: e} } return nil } @@ -389,7 +389,7 @@ func chmod(name string, mode FileMode) error { odir, e := dirstat(name) if e != nil { - return &PathError{"chmod", name, e} + return &PathError{Op: "chmod", Path: name, Err: e} } d.Null() d.Mode = odir.Mode&^chmodMask | syscallMode(mode)&chmodMask @@ -397,10 +397,10 @@ func chmod(name string, mode FileMode) error { var buf [syscall.STATFIXLEN]byte n, err := d.Marshal(buf[:]) if err != nil { - return &PathError{"chmod", name, err} + return &PathError{Op: "chmod", Path: name, Err: err} } if err = syscall.Wstat(name, buf[:n]); err != nil { - return &PathError{"chmod", name, err} + return &PathError{Op: "chmod", Path: name, Err: err} } return nil } @@ -421,10 +421,10 @@ func Chtimes(name string, atime time.Time, mtime time.Time) error { var buf [syscall.STATFIXLEN]byte n, err := d.Marshal(buf[:]) if err != nil { - return &PathError{"chtimes", name, err} + return &PathError{Op: "chtimes", Path: name, Err: err} } if err = syscall.Wstat(name, buf[:n]); err != nil { - return &PathError{"chtimes", name, err} + return &PathError{Op: "chtimes", Path: name, Err: err} } return nil } @@ -458,7 +458,7 @@ func Symlink(oldname, newname string) error { // Readlink returns the destination of the named symbolic link. // If there is an error, it will be of type *PathError. func Readlink(name string) (string, error) { - return "", &PathError{"readlink", name, syscall.EPLAN9} + return "", &PathError{Op: "readlink", Path: name, Err: syscall.EPLAN9} } // Chown changes the numeric uid and gid of the named file. @@ -469,14 +469,14 @@ func Readlink(name string) (string, error) { // On Windows or Plan 9, Chown always returns the syscall.EWINDOWS or // EPLAN9 error, wrapped in *PathError. func Chown(name string, uid, gid int) error { - return &PathError{"chown", name, syscall.EPLAN9} + return &PathError{Op: "chown", Path: name, Err: syscall.EPLAN9} } // Lchown changes the numeric uid and gid of the named file. // If the file is a symbolic link, it changes the uid and gid of the link itself. // If there is an error, it will be of type *PathError. func Lchown(name string, uid, gid int) error { - return &PathError{"lchown", name, syscall.EPLAN9} + return &PathError{Op: "lchown", Path: name, Err: syscall.EPLAN9} } // Chown changes the numeric uid and gid of the named file. @@ -485,7 +485,7 @@ func (f *File) Chown(uid, gid int) error { if f == nil { return ErrInvalid } - return &PathError{"chown", f.name, syscall.EPLAN9} + return &PathError{Op: "chown", Path: f.name, Err: syscall.EPLAN9} } func tempDir() string { @@ -505,7 +505,7 @@ func (f *File) Chdir() error { return err } if e := syscall.Fchdir(f.fd); e != nil { - return &PathError{"chdir", f.name, e} + return &PathError{Op: "chdir", Path: f.name, Err: e} } return nil } @@ -541,7 +541,7 @@ func (f *File) checkValid(op string) error { return ErrInvalid } if f.fd == badFd { - return &PathError{op, f.name, ErrClosed} + return &PathError{Op: op, Path: f.name, Err: ErrClosed} } return nil } diff --git a/src/os/file_posix.go b/src/os/file_posix.go index ae23d22d0a7..795c547856a 100644 --- a/src/os/file_posix.go +++ b/src/os/file_posix.go @@ -81,7 +81,7 @@ func chmod(name string, mode FileMode) error { return syscall.Chmod(longName, syscallMode(mode)) }) if e != nil { - return &PathError{"chmod", name, e} + return &PathError{Op: "chmod", Path: name, Err: e} } return nil } @@ -109,7 +109,7 @@ func Chown(name string, uid, gid int) error { return syscall.Chown(name, uid, gid) }) if e != nil { - return &PathError{"chown", name, e} + return &PathError{Op: "chown", Path: name, Err: e} } return nil } @@ -125,7 +125,7 @@ func Lchown(name string, uid, gid int) error { return syscall.Lchown(name, uid, gid) }) if e != nil { - return &PathError{"lchown", name, e} + return &PathError{Op: "lchown", Path: name, Err: e} } return nil } @@ -182,7 +182,7 @@ func Chtimes(name string, atime time.Time, mtime time.Time) error { utimes[0] = syscall.NsecToTimespec(atime.UnixNano()) utimes[1] = syscall.NsecToTimespec(mtime.UnixNano()) if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil { - return &PathError{"chtimes", name, e} + return &PathError{Op: "chtimes", Path: name, Err: e} } return nil } diff --git a/src/os/file_unix.go b/src/os/file_unix.go index 3cb4ffbf33e..0dc7a5a0a29 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -215,7 +215,7 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) { continue } - return nil, &PathError{"open", name, e} + return nil, &PathError{Op: "open", Path: name, Err: e} } // open(2) itself won't handle the sticky bit on *BSD and Solaris @@ -244,7 +244,7 @@ func (file *file) close() error { if e == poll.ErrFileClosing { e = ErrClosed } - err = &PathError{"close", file.name, e} + err = &PathError{Op: "close", Path: file.name, Err: e} } // no need for a finalizer anymore @@ -276,7 +276,7 @@ func Truncate(name string, size int64) error { return syscall.Truncate(name, size) }) if e != nil { - return &PathError{"truncate", name, e} + return &PathError{Op: "truncate", Path: name, Err: e} } return nil } @@ -313,7 +313,7 @@ func Remove(name string) error { if e1 != syscall.ENOTDIR { e = e1 } - return &PathError{"remove", name, e} + return &PathError{Op: "remove", Path: name, Err: e} } func tempDir() string { @@ -372,7 +372,7 @@ func Readlink(name string) (string, error) { continue } if e != nil { - return "", &PathError{"readlink", name, e} + return "", &PathError{Op: "readlink", Path: name, Err: e} } if n < len { return string(b[0:n]), nil diff --git a/src/os/file_windows.go b/src/os/file_windows.go index f744a350231..dfc5fc6ce68 100644 --- a/src/os/file_windows.go +++ b/src/os/file_windows.go @@ -168,7 +168,7 @@ func openDir(name string) (file *File, err error) { // openFileNolog is the Windows implementation of OpenFile. func openFileNolog(name string, flag int, perm FileMode) (*File, error) { if name == "" { - return nil, &PathError{"open", name, syscall.ENOENT} + return nil, &PathError{Op: "open", Path: name, Err: syscall.ENOENT} } r, errf := openFile(name, flag, perm) if errf == nil { @@ -178,11 +178,11 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) { if errd == nil { if flag&O_WRONLY != 0 || flag&O_RDWR != 0 { r.Close() - return nil, &PathError{"open", name, syscall.EISDIR} + return nil, &PathError{Op: "open", Path: name, Err: syscall.EISDIR} } return r, nil } - return nil, &PathError{"open", name, errf} + return nil, &PathError{Op: "open", Path: name, Err: errf} } func (file *file) close() error { @@ -198,7 +198,7 @@ func (file *file) close() error { if e == poll.ErrFileClosing { e = ErrClosed } - err = &PathError{"close", file.name, e} + err = &PathError{Op: "close", Path: file.name, Err: e} } // no need for a finalizer anymore @@ -236,7 +236,7 @@ func Truncate(name string, size int64) error { func Remove(name string) error { p, e := syscall.UTF16PtrFromString(fixLongPath(name)) if e != nil { - return &PathError{"remove", name, e} + return &PathError{Op: "remove", Path: name, Err: e} } // Go file interface forces us to know whether @@ -267,7 +267,7 @@ func Remove(name string) error { } } } - return &PathError{"remove", name, e} + return &PathError{Op: "remove", Path: name, Err: e} } func rename(oldname, newname string) error { @@ -493,7 +493,7 @@ func readlink(path string) (string, error) { func Readlink(name string) (string, error) { s, err := readlink(fixLongPath(name)) if err != nil { - return "", &PathError{"readlink", name, err} + return "", &PathError{Op: "readlink", Path: name, Err: err} } return s, nil } diff --git a/src/os/path.go b/src/os/path.go index ba43ea35254..df87887b9be 100644 --- a/src/os/path.go +++ b/src/os/path.go @@ -22,7 +22,7 @@ func MkdirAll(path string, perm FileMode) error { if dir.IsDir() { return nil } - return &PathError{"mkdir", path, syscall.ENOTDIR} + return &PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} } // Slow path: make sure parent exists and then call Mkdir for path. diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go index 37bf1b8f2f6..c1a1b726aff 100644 --- a/src/os/removeall_at.go +++ b/src/os/removeall_at.go @@ -22,7 +22,7 @@ func removeAll(path string) error { // The rmdir system call does not permit removing ".", // so we don't permit it either. if endsWithDot(path) { - return &PathError{"RemoveAll", path, syscall.EINVAL} + return &PathError{Op: "RemoveAll", Path: path, Err: syscall.EINVAL} } // Simple case: if Remove works, we're done. @@ -70,7 +70,7 @@ func removeAllFrom(parent *File, base string) error { // whose contents need to be removed. // Otherwise just return the error. if err != syscall.EISDIR && err != syscall.EPERM && err != syscall.EACCES { - return &PathError{"unlinkat", base, err} + return &PathError{Op: "unlinkat", Path: base, Err: err} } // Is this a directory we need to recurse into? @@ -80,11 +80,11 @@ func removeAllFrom(parent *File, base string) error { if IsNotExist(statErr) { return nil } - return &PathError{"fstatat", base, statErr} + return &PathError{Op: "fstatat", Path: base, Err: statErr} } if statInfo.Mode&syscall.S_IFMT != syscall.S_IFDIR { // Not a directory; return the error from the unix.Unlinkat. - return &PathError{"unlinkat", base, err} + return &PathError{Op: "unlinkat", Path: base, Err: err} } // Remove the directory's entries. @@ -99,7 +99,7 @@ func removeAllFrom(parent *File, base string) error { if IsNotExist(err) { return nil } - recurseErr = &PathError{"openfdat", base, err} + recurseErr = &PathError{Op: "openfdat", Path: base, Err: err} break } @@ -113,7 +113,7 @@ func removeAllFrom(parent *File, base string) error { if IsNotExist(readErr) { return nil } - return &PathError{"readdirnames", base, readErr} + return &PathError{Op: "readdirnames", Path: base, Err: readErr} } respSize = len(names) @@ -159,7 +159,7 @@ func removeAllFrom(parent *File, base string) error { if recurseErr != nil { return recurseErr } - return &PathError{"unlinkat", base, unlinkError} + return &PathError{Op: "unlinkat", Path: base, Err: unlinkError} } // openFdAt opens path relative to the directory in fd. diff --git a/src/os/removeall_noat.go b/src/os/removeall_noat.go index c1b43e38075..7c888baaa99 100644 --- a/src/os/removeall_noat.go +++ b/src/os/removeall_noat.go @@ -23,7 +23,7 @@ func removeAll(path string) error { // so we don't permit it to remain consistent with the // "at" implementation of RemoveAll. if endsWithDot(path) { - return &PathError{"RemoveAll", path, syscall.EINVAL} + return &PathError{Op: "RemoveAll", Path: path, Err: syscall.EINVAL} } // Simple case: if Remove works, we're done. diff --git a/src/os/stat_plan9.go b/src/os/stat_plan9.go index 7ac2695df87..57ae6fb0bbd 100644 --- a/src/os/stat_plan9.go +++ b/src/os/stat_plan9.go @@ -65,7 +65,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) { } if n < bitSize16 { - return nil, &PathError{"stat", name, err} + return nil, &PathError{Op: "stat", Path: name, Err: err} } // Pull the real size out of the stat message. @@ -76,7 +76,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) { if size <= n { d, err := syscall.UnmarshalDir(buf[:n]) if err != nil { - return nil, &PathError{"stat", name, err} + return nil, &PathError{Op: "stat", Path: name, Err: err} } return d, nil } @@ -87,7 +87,7 @@ func dirstat(arg interface{}) (*syscall.Dir, error) { err = syscall.ErrBadStat } - return nil, &PathError{"stat", name, err} + return nil, &PathError{Op: "stat", Path: name, Err: err} } // statNolog implements Stat for Plan 9. diff --git a/src/os/stat_unix.go b/src/os/stat_unix.go index ef74a43758c..66c356fc620 100644 --- a/src/os/stat_unix.go +++ b/src/os/stat_unix.go @@ -19,7 +19,7 @@ func (f *File) Stat() (FileInfo, error) { var fs fileStat err := f.pfd.Fstat(&fs.sys) if err != nil { - return nil, &PathError{"stat", f.name, err} + return nil, &PathError{Op: "stat", Path: f.name, Err: err} } fillFileStatFromSys(&fs, f.name) return &fs, nil @@ -32,7 +32,7 @@ func statNolog(name string) (FileInfo, error) { return syscall.Stat(name, &fs.sys) }) if err != nil { - return nil, &PathError{"stat", name, err} + return nil, &PathError{Op: "stat", Path: name, Err: err} } fillFileStatFromSys(&fs, name) return &fs, nil @@ -45,7 +45,7 @@ func lstatNolog(name string) (FileInfo, error) { return syscall.Lstat(name, &fs.sys) }) if err != nil { - return nil, &PathError{"lstat", name, err} + return nil, &PathError{Op: "lstat", Path: name, Err: err} } fillFileStatFromSys(&fs, name) return &fs, nil diff --git a/src/os/stat_windows.go b/src/os/stat_windows.go index 3e0e0a59ede..da4c49090e2 100644 --- a/src/os/stat_windows.go +++ b/src/os/stat_windows.go @@ -27,7 +27,7 @@ func (file *File) Stat() (FileInfo, error) { ft, err := file.pfd.GetFileType() if err != nil { - return nil, &PathError{"GetFileType", file.name, err} + return nil, &PathError{Op: "GetFileType", Path: file.name, Err: err} } switch ft { case syscall.FILE_TYPE_PIPE, syscall.FILE_TYPE_CHAR: @@ -45,14 +45,14 @@ func (file *File) Stat() (FileInfo, error) { // stat implements both Stat and Lstat of a file. func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { if len(name) == 0 { - return nil, &PathError{funcname, name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} + return nil, &PathError{Op: funcname, Path: name, Err: syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} } if isWindowsNulName(name) { return &devNullStat, nil } namep, err := syscall.UTF16PtrFromString(fixLongPath(name)) if err != nil { - return nil, &PathError{funcname, name, err} + return nil, &PathError{Op: funcname, Path: name, Err: err} } // Try GetFileAttributesEx first, because it is faster than CreateFile. @@ -80,7 +80,7 @@ func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { var fd syscall.Win32finddata sh, err := syscall.FindFirstFile(namep, &fd) if err != nil { - return nil, &PathError{"FindFirstFile", name, err} + return nil, &PathError{Op: "FindFirstFile", Path: name, Err: err} } syscall.FindClose(sh) fs := newFileStatFromWin32finddata(&fd) @@ -94,7 +94,7 @@ func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { h, err := syscall.CreateFile(namep, 0, 0, nil, syscall.OPEN_EXISTING, createFileAttrs, 0) if err != nil { - return nil, &PathError{"CreateFile", name, err} + return nil, &PathError{Op: "CreateFile", Path: name, Err: err} } defer syscall.CloseHandle(h) diff --git a/src/os/types_windows.go b/src/os/types_windows.go index 3d1a6674b14..59bf5ca3814 100644 --- a/src/os/types_windows.go +++ b/src/os/types_windows.go @@ -45,7 +45,7 @@ func newFileStatFromGetFileInformationByHandle(path string, h syscall.Handle) (f var d syscall.ByHandleFileInformation err = syscall.GetFileInformationByHandle(h, &d) if err != nil { - return nil, &PathError{"GetFileInformationByHandle", path, err} + return nil, &PathError{Op: "GetFileInformationByHandle", Path: path, Err: err} } var ti windows.FILE_ATTRIBUTE_TAG_INFO @@ -58,7 +58,7 @@ func newFileStatFromGetFileInformationByHandle(path string, h syscall.Handle) (f // instance to indicate no symlinks are possible. ti.ReparseTag = 0 } else { - return nil, &PathError{"GetFileInformationByHandleEx", path, err} + return nil, &PathError{Op: "GetFileInformationByHandleEx", Path: path, Err: err} } } @@ -197,7 +197,7 @@ func (fs *fileStat) saveInfoFromPath(path string) error { var err error fs.path, err = syscall.FullPath(fs.path) if err != nil { - return &PathError{"FullPath", path, err} + return &PathError{Op: "FullPath", Path: path, Err: err} } } fs.name = basename(path) From a505312c89a0468081173da3042de6ac8582a3ba Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 15 Oct 2020 23:34:41 -0400 Subject: [PATCH 017/403] api: update next.txt A bunch of new API hasn't been added yet and is cluttering all.bash output. Change-Id: Ic7f255cce8c162716b9a1144f78b5f9ce6220b33 Reviewed-on: https://go-review.googlesource.com/c/go/+/262878 Trust: Russ Cox Trust: Rob Pike Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke --- api/next.txt | 246 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 241 insertions(+), 5 deletions(-) diff --git a/api/next.txt b/api/next.txt index 076f39ec341..59422cca4d4 100644 --- a/api/next.txt +++ b/api/next.txt @@ -1,8 +1,239 @@ -pkg unicode, const Version = "13.0.0" -pkg unicode, var Chorasmian *RangeTable -pkg unicode, var Dives_Akuru *RangeTable -pkg unicode, var Khitan_Small_Script *RangeTable -pkg unicode, var Yezidi *RangeTable +pkg debug/elf, const DT_ADDRRNGHI = 1879047935 +pkg debug/elf, const DT_ADDRRNGHI DynTag +pkg debug/elf, const DT_ADDRRNGLO = 1879047680 +pkg debug/elf, const DT_ADDRRNGLO DynTag +pkg debug/elf, const DT_AUDIT = 1879047932 +pkg debug/elf, const DT_AUDIT DynTag +pkg debug/elf, const DT_AUXILIARY = 2147483645 +pkg debug/elf, const DT_AUXILIARY DynTag +pkg debug/elf, const DT_CHECKSUM = 1879047672 +pkg debug/elf, const DT_CHECKSUM DynTag +pkg debug/elf, const DT_CONFIG = 1879047930 +pkg debug/elf, const DT_CONFIG DynTag +pkg debug/elf, const DT_DEPAUDIT = 1879047931 +pkg debug/elf, const DT_DEPAUDIT DynTag +pkg debug/elf, const DT_FEATURE = 1879047676 +pkg debug/elf, const DT_FEATURE DynTag +pkg debug/elf, const DT_FILTER = 2147483647 +pkg debug/elf, const DT_FILTER DynTag +pkg debug/elf, const DT_FLAGS_1 = 1879048187 +pkg debug/elf, const DT_FLAGS_1 DynTag +pkg debug/elf, const DT_GNU_CONFLICT = 1879047928 +pkg debug/elf, const DT_GNU_CONFLICT DynTag +pkg debug/elf, const DT_GNU_CONFLICTSZ = 1879047670 +pkg debug/elf, const DT_GNU_CONFLICTSZ DynTag +pkg debug/elf, const DT_GNU_HASH = 1879047925 +pkg debug/elf, const DT_GNU_HASH DynTag +pkg debug/elf, const DT_GNU_LIBLIST = 1879047929 +pkg debug/elf, const DT_GNU_LIBLIST DynTag +pkg debug/elf, const DT_GNU_LIBLISTSZ = 1879047671 +pkg debug/elf, const DT_GNU_LIBLISTSZ DynTag +pkg debug/elf, const DT_GNU_PRELINKED = 1879047669 +pkg debug/elf, const DT_GNU_PRELINKED DynTag +pkg debug/elf, const DT_MIPS_AUX_DYNAMIC = 1879048241 +pkg debug/elf, const DT_MIPS_AUX_DYNAMIC DynTag +pkg debug/elf, const DT_MIPS_BASE_ADDRESS = 1879048198 +pkg debug/elf, const DT_MIPS_BASE_ADDRESS DynTag +pkg debug/elf, const DT_MIPS_COMPACT_SIZE = 1879048239 +pkg debug/elf, const DT_MIPS_COMPACT_SIZE DynTag +pkg debug/elf, const DT_MIPS_CONFLICT = 1879048200 +pkg debug/elf, const DT_MIPS_CONFLICT DynTag +pkg debug/elf, const DT_MIPS_CONFLICTNO = 1879048203 +pkg debug/elf, const DT_MIPS_CONFLICTNO DynTag +pkg debug/elf, const DT_MIPS_CXX_FLAGS = 1879048226 +pkg debug/elf, const DT_MIPS_CXX_FLAGS DynTag +pkg debug/elf, const DT_MIPS_DELTA_CLASS = 1879048215 +pkg debug/elf, const DT_MIPS_DELTA_CLASS DynTag +pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM = 1879048224 +pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM DynTag +pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO = 1879048225 +pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO DynTag +pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO = 1879048216 +pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO DynTag +pkg debug/elf, const DT_MIPS_DELTA_INSTANCE = 1879048217 +pkg debug/elf, const DT_MIPS_DELTA_INSTANCE DynTag +pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO = 1879048218 +pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO DynTag +pkg debug/elf, const DT_MIPS_DELTA_RELOC = 1879048219 +pkg debug/elf, const DT_MIPS_DELTA_RELOC DynTag +pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO = 1879048220 +pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO DynTag +pkg debug/elf, const DT_MIPS_DELTA_SYM = 1879048221 +pkg debug/elf, const DT_MIPS_DELTA_SYM DynTag +pkg debug/elf, const DT_MIPS_DELTA_SYM_NO = 1879048222 +pkg debug/elf, const DT_MIPS_DELTA_SYM_NO DynTag +pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN = 1879048235 +pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN DynTag +pkg debug/elf, const DT_MIPS_FLAGS = 1879048197 +pkg debug/elf, const DT_MIPS_FLAGS DynTag +pkg debug/elf, const DT_MIPS_GOTSYM = 1879048211 +pkg debug/elf, const DT_MIPS_GOTSYM DynTag +pkg debug/elf, const DT_MIPS_GP_VALUE = 1879048240 +pkg debug/elf, const DT_MIPS_GP_VALUE DynTag +pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX = 1879048231 +pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX DynTag +pkg debug/elf, const DT_MIPS_HIPAGENO = 1879048212 +pkg debug/elf, const DT_MIPS_HIPAGENO DynTag +pkg debug/elf, const DT_MIPS_ICHECKSUM = 1879048195 +pkg debug/elf, const DT_MIPS_ICHECKSUM DynTag +pkg debug/elf, const DT_MIPS_INTERFACE = 1879048234 +pkg debug/elf, const DT_MIPS_INTERFACE DynTag +pkg debug/elf, const DT_MIPS_INTERFACE_SIZE = 1879048236 +pkg debug/elf, const DT_MIPS_INTERFACE_SIZE DynTag +pkg debug/elf, const DT_MIPS_IVERSION = 1879048196 +pkg debug/elf, const DT_MIPS_IVERSION DynTag +pkg debug/elf, const DT_MIPS_LIBLIST = 1879048201 +pkg debug/elf, const DT_MIPS_LIBLIST DynTag +pkg debug/elf, const DT_MIPS_LIBLISTNO = 1879048208 +pkg debug/elf, const DT_MIPS_LIBLISTNO DynTag +pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX = 1879048229 +pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX DynTag +pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX = 1879048230 +pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX DynTag +pkg debug/elf, const DT_MIPS_LOCAL_GOTNO = 1879048202 +pkg debug/elf, const DT_MIPS_LOCAL_GOTNO DynTag +pkg debug/elf, const DT_MIPS_MSYM = 1879048199 +pkg debug/elf, const DT_MIPS_MSYM DynTag +pkg debug/elf, const DT_MIPS_OPTIONS = 1879048233 +pkg debug/elf, const DT_MIPS_OPTIONS DynTag +pkg debug/elf, const DT_MIPS_PERF_SUFFIX = 1879048238 +pkg debug/elf, const DT_MIPS_PERF_SUFFIX DynTag +pkg debug/elf, const DT_MIPS_PIXIE_INIT = 1879048227 +pkg debug/elf, const DT_MIPS_PIXIE_INIT DynTag +pkg debug/elf, const DT_MIPS_PLTGOT = 1879048242 +pkg debug/elf, const DT_MIPS_PLTGOT DynTag +pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX = 1879048232 +pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX DynTag +pkg debug/elf, const DT_MIPS_RLD_MAP = 1879048214 +pkg debug/elf, const DT_MIPS_RLD_MAP DynTag +pkg debug/elf, const DT_MIPS_RLD_MAP_REL = 1879048245 +pkg debug/elf, const DT_MIPS_RLD_MAP_REL DynTag +pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 1879048237 +pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR DynTag +pkg debug/elf, const DT_MIPS_RLD_VERSION = 1879048193 +pkg debug/elf, const DT_MIPS_RLD_VERSION DynTag +pkg debug/elf, const DT_MIPS_RWPLT = 1879048244 +pkg debug/elf, const DT_MIPS_RWPLT DynTag +pkg debug/elf, const DT_MIPS_SYMBOL_LIB = 1879048228 +pkg debug/elf, const DT_MIPS_SYMBOL_LIB DynTag +pkg debug/elf, const DT_MIPS_SYMTABNO = 1879048209 +pkg debug/elf, const DT_MIPS_SYMTABNO DynTag +pkg debug/elf, const DT_MIPS_TIME_STAMP = 1879048194 +pkg debug/elf, const DT_MIPS_TIME_STAMP DynTag +pkg debug/elf, const DT_MIPS_UNREFEXTNO = 1879048210 +pkg debug/elf, const DT_MIPS_UNREFEXTNO DynTag +pkg debug/elf, const DT_MOVEENT = 1879047674 +pkg debug/elf, const DT_MOVEENT DynTag +pkg debug/elf, const DT_MOVESZ = 1879047675 +pkg debug/elf, const DT_MOVESZ DynTag +pkg debug/elf, const DT_MOVETAB = 1879047934 +pkg debug/elf, const DT_MOVETAB DynTag +pkg debug/elf, const DT_PLTPAD = 1879047933 +pkg debug/elf, const DT_PLTPAD DynTag +pkg debug/elf, const DT_PLTPADSZ = 1879047673 +pkg debug/elf, const DT_PLTPADSZ DynTag +pkg debug/elf, const DT_POSFLAG_1 = 1879047677 +pkg debug/elf, const DT_POSFLAG_1 DynTag +pkg debug/elf, const DT_PPC64_GLINK = 1879048192 +pkg debug/elf, const DT_PPC64_GLINK DynTag +pkg debug/elf, const DT_PPC64_OPD = 1879048193 +pkg debug/elf, const DT_PPC64_OPD DynTag +pkg debug/elf, const DT_PPC64_OPDSZ = 1879048194 +pkg debug/elf, const DT_PPC64_OPDSZ DynTag +pkg debug/elf, const DT_PPC64_OPT = 1879048195 +pkg debug/elf, const DT_PPC64_OPT DynTag +pkg debug/elf, const DT_PPC_GOT = 1879048192 +pkg debug/elf, const DT_PPC_GOT DynTag +pkg debug/elf, const DT_PPC_OPT = 1879048193 +pkg debug/elf, const DT_PPC_OPT DynTag +pkg debug/elf, const DT_RELACOUNT = 1879048185 +pkg debug/elf, const DT_RELACOUNT DynTag +pkg debug/elf, const DT_RELCOUNT = 1879048186 +pkg debug/elf, const DT_RELCOUNT DynTag +pkg debug/elf, const DT_SPARC_REGISTER = 1879048193 +pkg debug/elf, const DT_SPARC_REGISTER DynTag +pkg debug/elf, const DT_SYMINENT = 1879047679 +pkg debug/elf, const DT_SYMINENT DynTag +pkg debug/elf, const DT_SYMINFO = 1879047935 +pkg debug/elf, const DT_SYMINFO DynTag +pkg debug/elf, const DT_SYMINSZ = 1879047678 +pkg debug/elf, const DT_SYMINSZ DynTag +pkg debug/elf, const DT_SYMTAB_SHNDX = 34 +pkg debug/elf, const DT_SYMTAB_SHNDX DynTag +pkg debug/elf, const DT_TLSDESC_GOT = 1879047927 +pkg debug/elf, const DT_TLSDESC_GOT DynTag +pkg debug/elf, const DT_TLSDESC_PLT = 1879047926 +pkg debug/elf, const DT_TLSDESC_PLT DynTag +pkg debug/elf, const DT_USED = 2147483646 +pkg debug/elf, const DT_USED DynTag +pkg debug/elf, const DT_VALRNGHI = 1879047679 +pkg debug/elf, const DT_VALRNGHI DynTag +pkg debug/elf, const DT_VALRNGLO = 1879047424 +pkg debug/elf, const DT_VALRNGLO DynTag +pkg debug/elf, const DT_VERDEF = 1879048188 +pkg debug/elf, const DT_VERDEF DynTag +pkg debug/elf, const DT_VERDEFNUM = 1879048189 +pkg debug/elf, const DT_VERDEFNUM DynTag +pkg debug/elf, const PT_AARCH64_ARCHEXT = 1879048192 +pkg debug/elf, const PT_AARCH64_ARCHEXT ProgType +pkg debug/elf, const PT_AARCH64_UNWIND = 1879048193 +pkg debug/elf, const PT_AARCH64_UNWIND ProgType +pkg debug/elf, const PT_ARM_ARCHEXT = 1879048192 +pkg debug/elf, const PT_ARM_ARCHEXT ProgType +pkg debug/elf, const PT_ARM_EXIDX = 1879048193 +pkg debug/elf, const PT_ARM_EXIDX ProgType +pkg debug/elf, const PT_GNU_EH_FRAME = 1685382480 +pkg debug/elf, const PT_GNU_EH_FRAME ProgType +pkg debug/elf, const PT_GNU_MBIND_HI = 1685386580 +pkg debug/elf, const PT_GNU_MBIND_HI ProgType +pkg debug/elf, const PT_GNU_MBIND_LO = 1685382485 +pkg debug/elf, const PT_GNU_MBIND_LO ProgType +pkg debug/elf, const PT_GNU_PROPERTY = 1685382483 +pkg debug/elf, const PT_GNU_PROPERTY ProgType +pkg debug/elf, const PT_GNU_RELRO = 1685382482 +pkg debug/elf, const PT_GNU_RELRO ProgType +pkg debug/elf, const PT_GNU_STACK = 1685382481 +pkg debug/elf, const PT_GNU_STACK ProgType +pkg debug/elf, const PT_MIPS_ABIFLAGS = 1879048195 +pkg debug/elf, const PT_MIPS_ABIFLAGS ProgType +pkg debug/elf, const PT_MIPS_OPTIONS = 1879048194 +pkg debug/elf, const PT_MIPS_OPTIONS ProgType +pkg debug/elf, const PT_MIPS_REGINFO = 1879048192 +pkg debug/elf, const PT_MIPS_REGINFO ProgType +pkg debug/elf, const PT_MIPS_RTPROC = 1879048193 +pkg debug/elf, const PT_MIPS_RTPROC ProgType +pkg debug/elf, const PT_OPENBSD_BOOTDATA = 1705253862 +pkg debug/elf, const PT_OPENBSD_BOOTDATA ProgType +pkg debug/elf, const PT_OPENBSD_RANDOMIZE = 1705237478 +pkg debug/elf, const PT_OPENBSD_RANDOMIZE ProgType +pkg debug/elf, const PT_OPENBSD_WXNEEDED = 1705237479 +pkg debug/elf, const PT_OPENBSD_WXNEEDED ProgType +pkg debug/elf, const PT_PAX_FLAGS = 1694766464 +pkg debug/elf, const PT_PAX_FLAGS ProgType +pkg debug/elf, const PT_S390_PGSTE = 1879048192 +pkg debug/elf, const PT_S390_PGSTE ProgType +pkg debug/elf, const PT_SUNWSTACK = 1879048187 +pkg debug/elf, const PT_SUNWSTACK ProgType +pkg debug/elf, const PT_SUNW_EH_FRAME = 1685382480 +pkg debug/elf, const PT_SUNW_EH_FRAME ProgType +pkg flag, func Func(string, string, func(string) error) +pkg flag, method (*FlagSet) Func(string, string, func(string) error) +pkg go/build, type Package struct, IgnoredOtherFiles []string +pkg io, type ReadSeekCloser interface { Close, Read, Seek } +pkg io, type ReadSeekCloser interface, Close() error +pkg io, type ReadSeekCloser interface, Read([]uint8) (int, error) +pkg io, type ReadSeekCloser interface, Seek(int64, int) (int64, error) +pkg net, var ErrClosed error +pkg net/http, type Transport struct, GetProxyConnectHeader func(context.Context, *url.URL, string) (Header, error) +pkg os, method (*File) ReadDir(int) ([]DirEntry, error) +pkg os, method (FileMode) Type() FileMode +pkg os, type DirEntry interface { Info, IsDir, Name, Type } +pkg os, type DirEntry interface, Info() (FileInfo, error) +pkg os, type DirEntry interface, IsDir() bool +pkg os, type DirEntry interface, Name() string +pkg os, type DirEntry interface, Type() FileMode +pkg os/signal, func NotifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc) +pkg testing/iotest, func ErrReader(error) io.Reader pkg text/template/parse, const NodeComment = 20 pkg text/template/parse, const NodeComment NodeType pkg text/template/parse, const ParseComments = 1 @@ -17,3 +248,8 @@ pkg text/template/parse, type CommentNode struct, embedded NodeType pkg text/template/parse, type CommentNode struct, embedded Pos pkg text/template/parse, type Mode uint pkg text/template/parse, type Tree struct, Mode Mode +pkg unicode, const Version = "13.0.0" +pkg unicode, var Chorasmian *RangeTable +pkg unicode, var Dives_Akuru *RangeTable +pkg unicode, var Khitan_Small_Script *RangeTable +pkg unicode, var Yezidi *RangeTable From bccdd31252c9771ef2e8dae0402251163a081b56 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 19 Oct 2020 18:32:15 +0700 Subject: [PATCH 018/403] cmd/compile: use type position for error message in align.go This helps the compiler reports the right place where the type declared, instead of relying on global lineno, which maybe set to wrong value at the time the error is reported. Fixes #42058 Change-Id: I06d34aa9b0236d122f4a0d72e66675ded022baac Reviewed-on: https://go-review.googlesource.com/c/go/+/263597 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/align.go | 10 +++++----- src/go/types/stdlib_test.go | 2 ++ test/fixedbugs/issue42058a.go | 13 +++++++++++++ test/fixedbugs/issue42058b.go | 13 +++++++++++++ 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 test/fixedbugs/issue42058a.go create mode 100644 test/fixedbugs/issue42058b.go diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go index 4bc454df224..a3a0c8fce82 100644 --- a/src/cmd/compile/internal/gc/align.go +++ b/src/cmd/compile/internal/gc/align.go @@ -86,7 +86,7 @@ func expandiface(t *types.Type) { sort.Sort(methcmp(methods)) if int64(len(methods)) >= thearch.MAXWIDTH/int64(Widthptr) { - yyerror("interface too large") + yyerrorl(typePos(t), "interface too large") } for i, m := range methods { m.Offset = int64(i) * int64(Widthptr) @@ -150,7 +150,7 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 { maxwidth = 1<<31 - 1 } if o >= maxwidth { - yyerror("type %L too large", errtype) + yyerrorl(typePos(errtype), "type %L too large", errtype) o = 8 // small but nonzero } } @@ -381,7 +381,7 @@ func dowidth(t *types.Type) { t1 := t.ChanArgs() dowidth(t1) // just in case if t1.Elem().Width >= 1<<16 { - yyerror("channel element type too large (>64kB)") + yyerrorl(typePos(t1), "channel element type too large (>64kB)") } w = 1 // anything will do @@ -414,7 +414,7 @@ func dowidth(t *types.Type) { if t.Elem().Width != 0 { cap := (uint64(thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width) if uint64(t.NumElem()) > cap { - yyerror("type %L larger than address space", t) + yyerrorl(typePos(t), "type %L larger than address space", t) } } w = t.NumElem() * t.Elem().Width @@ -456,7 +456,7 @@ func dowidth(t *types.Type) { } if Widthptr == 4 && w != int64(int32(w)) { - yyerror("type %v too large", t) + yyerrorl(typePos(t), "type %v too large", t) } t.Width = w diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index f5a3273fa1c..669e7bec20f 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -183,6 +183,8 @@ func TestStdFixed(t *testing.T) { "issue31747.go", // go/types does not have constraints on language level (-lang=go1.12) (see #31793) "issue34329.go", // go/types does not have constraints on language level (-lang=go1.13) (see #31793) "bug251.go", // issue #34333 which was exposed with fix for #34151 + "issue42058a.go", // go/types does not have constraints on channel element size + "issue42058b.go", // go/types does not have constraints on channel element size ) } diff --git a/test/fixedbugs/issue42058a.go b/test/fixedbugs/issue42058a.go new file mode 100644 index 00000000000..67751a1b0c9 --- /dev/null +++ b/test/fixedbugs/issue42058a.go @@ -0,0 +1,13 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in +// the LICENSE file. + +package p + +var c chan [2 << 16]byte // ERROR "channel element type too large" + +type T [1 << 17]byte + +var x chan T // ERROR "channel element type too large" diff --git a/test/fixedbugs/issue42058b.go b/test/fixedbugs/issue42058b.go new file mode 100644 index 00000000000..03f86ee1b11 --- /dev/null +++ b/test/fixedbugs/issue42058b.go @@ -0,0 +1,13 @@ +// errorcheck + +// Copyright 2020 The Go Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in +// the LICENSE file. + +package p + +var c chan [2 << 16]byte // ERROR "channel element type too large" + +func f() { + _ = 42 +} From 627959eb04ee0edc4a985a7526ed7fe838ad2573 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 14 Oct 2020 21:15:37 -0400 Subject: [PATCH 019/403] cmd/link: support cgo internal/linking on darwin/arm64 Cgo programs work as well. Still not enabled by default for now. Enable internal linking tests. Updates #38485. Change-Id: I8324a5c263fba221eb4e67d71207ca84fa241e6c Reviewed-on: https://go-review.googlesource.com/c/go/+/263637 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Than McIntosh --- misc/cgo/test/issue4029.c | 2 +- misc/cgo/test/issue4029.go | 3 +- misc/cgo/test/issue4029w.go | 2 +- src/cmd/dist/test.go | 7 +- src/cmd/link/internal/arm64/asm.go | 91 +++++++++++++++++++++- src/cmd/link/internal/ld/config.go | 3 - src/cmd/link/internal/loader/loader.go | 8 +- src/cmd/link/internal/loadmacho/ldmacho.go | 57 ++++++++------ 8 files changed, 131 insertions(+), 42 deletions(-) diff --git a/misc/cgo/test/issue4029.c b/misc/cgo/test/issue4029.c index e6a777fe646..e79c5a709c8 100644 --- a/misc/cgo/test/issue4029.c +++ b/misc/cgo/test/issue4029.c @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build !windows,!static -// +build !darwin !internal_pie +// +build !darwin !internal_pie,!arm64 #include #include diff --git a/misc/cgo/test/issue4029.go b/misc/cgo/test/issue4029.go index 8602ce19e2d..b2d131833a9 100644 --- a/misc/cgo/test/issue4029.go +++ b/misc/cgo/test/issue4029.go @@ -3,10 +3,11 @@ // license that can be found in the LICENSE file. // +build !windows,!static -// +build !darwin !internal_pie +// +build !darwin !internal_pie,!arm64 // Excluded in darwin internal linking PIE mode, as dynamic export is not // supported. +// Excluded in internal linking mode on darwin/arm64, as it is always PIE. package cgotest diff --git a/misc/cgo/test/issue4029w.go b/misc/cgo/test/issue4029w.go index de0cf2138ae..b969bdd0fe8 100644 --- a/misc/cgo/test/issue4029w.go +++ b/misc/cgo/test/issue4029w.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. -// +build windows static darwin,internal_pie +// +build windows static darwin,internal_pie darwin,arm64 package cgotest diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index bcb12f29fbd..09d69f72ed6 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -946,9 +946,6 @@ func (t *tester) internalLink() bool { if goos == "ios" { return false } - if goos == "darwin" && goarch == "arm64" { - return false - } // Internally linking cgo is incomplete on some architectures. // https://golang.org/issue/10373 // https://golang.org/issue/14449 @@ -964,7 +961,7 @@ func (t *tester) internalLink() bool { func (t *tester) internalLinkPIE() bool { switch goos + "-" + goarch { - case "darwin-amd64", + case "darwin-amd64", "darwin-arm64", "linux-amd64", "linux-arm64", "android-arm64", "windows-amd64", "windows-386", "windows-arm": @@ -1088,7 +1085,7 @@ func (t *tester) cgoTest(dt *distTest) error { pair := gohostos + "-" + goarch switch pair { - case "darwin-amd64", + case "darwin-amd64", "darwin-arm64", "openbsd-386", "openbsd-amd64", "windows-386", "windows-amd64": // test linkmode=external, but __thread not supported, so skip testtls. diff --git a/src/cmd/link/internal/arm64/asm.go b/src/cmd/link/internal/arm64/asm.go index 585c96852f9..e4564111558 100644 --- a/src/cmd/link/internal/arm64/asm.go +++ b/src/cmd/link/internal/arm64/asm.go @@ -71,13 +71,13 @@ func gentext(ctxt *ld.Link, ldr *loader.Loader) { } func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool { - targ := r.Sym() var targType sym.SymKind if targ != 0 { targType = ldr.SymType(targ) } + const pcrel = 1 switch r.Type() { default: if r.Type() >= objabi.ElfRelocOffset { @@ -201,6 +201,75 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade su := ldr.MakeSymbolUpdater(s) su.SetRelocType(rIdx, objabi.R_ARM64_LDST128) return true + + // Handle relocations found in Mach-O object files. + case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_UNSIGNED*2: + if targType == sym.SDYNIMPORT { + ldr.Errorf(s, "unexpected reloc for dynamic symbol %s", ldr.SymName(targ)) + } + su := ldr.MakeSymbolUpdater(s) + su.SetRelocType(rIdx, objabi.R_ADDR) + if target.IsPIE() && target.IsInternal() { + // For internal linking PIE, this R_ADDR relocation cannot + // be resolved statically. We need to generate a dynamic + // relocation. Let the code below handle it. + break + } + return true + + case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_BRANCH26*2 + pcrel: + su := ldr.MakeSymbolUpdater(s) + su.SetRelocType(rIdx, objabi.R_CALLARM64) + if targType == sym.SDYNIMPORT { + addpltsym(target, ldr, syms, targ) + su.SetRelocSym(rIdx, syms.PLT) + su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ))) + } + return true + + case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_PAGE21*2 + pcrel, + objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_PAGEOFF12*2: + if targType == sym.SDYNIMPORT { + ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ)) + } + su := ldr.MakeSymbolUpdater(s) + su.SetRelocType(rIdx, objabi.R_ARM64_PCREL) + return true + + case objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGE21*2 + pcrel, + objabi.MachoRelocOffset + ld.MACHO_ARM64_RELOC_GOT_LOAD_PAGEOFF12*2: + if targType != sym.SDYNIMPORT { + // have symbol + // turn MOVD sym@GOT (adrp+ldr) into MOVD $sym (adrp+add) + data := ldr.Data(s) + off := r.Off() + if int(off+3) >= len(data) { + ldr.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", ldr.SymName(targ)) + return false + } + o := target.Arch.ByteOrder.Uint32(data[off:]) + su := ldr.MakeSymbolUpdater(s) + switch { + case (o>>24)&0x9f == 0x90: // adrp + // keep instruction unchanged, change relocation type below + case o>>24 == 0xf9: // ldr + // rewrite to add + o = (0x91 << 24) | (o & (1<<22 - 1)) + su.MakeWritable() + su.SetUint32(target.Arch, int64(off), o) + default: + ldr.Errorf(s, "unexpected GOT_LOAD reloc for non-dynamic symbol %s", ldr.SymName(targ)) + return false + } + su.SetRelocType(rIdx, objabi.R_ARM64_PCREL) + return true + } + ld.AddGotSym(target, ldr, syms, targ, 0) + su := ldr.MakeSymbolUpdater(s) + su.SetRelocType(rIdx, objabi.R_ARM64_GOT) + su.SetRelocSym(rIdx, syms.GOT) + su.SetRelocAdd(rIdx, int64(ldr.SymGot(targ))) + return true } // Reread the reloc to incorporate any changes in type above. @@ -671,14 +740,28 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade } o0 := (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5) return val | int64(o0), noExtReloc, isOk - } else if (val>>24)&0x91 == 0x91 { - // R_AARCH64_ADD_ABS_LO12_NC + } else if (val>>24)&0x9f == 0x91 { + // ELF R_AARCH64_ADD_ABS_LO12_NC or Mach-O ARM64_RELOC_PAGEOFF12 // patch instruction: add t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff) o1 := uint32(t&0xfff) << 10 return val | int64(o1), noExtReloc, isOk + } else if (val>>24)&0x3b == 0x39 { + // Mach-O ARM64_RELOC_PAGEOFF12 + // patch ldr/str(b/h/w/d/q) (integer or vector) instructions, which have different scaling factors. + // Mach-O uses same relocation type for them. + shift := uint32(val) >> 30 + if shift == 0 && (val>>20)&0x048 == 0x048 { // 128-bit vector load + shift = 4 + } + t := ldr.SymAddr(rs) + r.Add() - ((ldr.SymValue(s) + int64(r.Off())) &^ 0xfff) + if t&(1<> shift) << 10 + return val | int64(o1), noExtReloc, isOk } else { - ldr.Errorf(s, "unsupported instruction for %x R_PCRELARM64", val) + ldr.Errorf(s, "unsupported instruction for %x R_ARM64_PCREL", val) } case objabi.R_ARM64_LDST8: diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 834c87d06be..a54b96dd5d7 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -208,9 +208,6 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { if iscgo && objabi.GOOS == "android" { return true, objabi.GOOS + " does not support internal cgo" } - if iscgo && objabi.GOOS == "darwin" && objabi.GOARCH == "arm64" { - return true, objabi.GOOS + "/" + objabi.GOARCH + " does not support internal cgo" - } // When the race flag is set, the LLVM tsan relocatable file is linked // into the final binary, which means external linking is required because diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 47cac0441bc..d861efcb13a 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -2622,11 +2622,15 @@ func (l *Loader) Dump() { fmt.Println("Nsyms:", len(l.objSyms)) fmt.Println("syms") for i := Sym(1); i < Sym(len(l.objSyms)); i++ { - pi := interface{}("") + pi := "" if l.IsExternal(i) { pi = fmt.Sprintf("", l.extIndex(i)) } - fmt.Println(i, l.SymName(i), l.SymType(i), pi) + sect := "" + if l.SymSect(i) != nil { + sect = l.SymSect(i).Name + } + fmt.Printf("%v %v %v %v %x %v\n", i, l.SymName(i), l.SymType(i), pi, l.SymValue(i), sect) } fmt.Println("symsByName") for name, i := range l.symsByName[0] { diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index 864d80835b9..d12f2bc2ac7 100644 --- a/src/cmd/link/internal/loadmacho/ldmacho.go +++ b/src/cmd/link/internal/loadmacho/ldmacho.go @@ -43,7 +43,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -// TODO(crawshaw): de-duplicate these symbols with cmd/internal/ld +// TODO(crawshaw): de-duplicate these symbols with cmd/link/internal/ld const ( MACHO_X86_64_RELOC_UNSIGNED = 0 MACHO_X86_64_RELOC_SIGNED = 1 @@ -172,11 +172,12 @@ const ( LdMachoCpuVax = 1 LdMachoCpu68000 = 6 LdMachoCpu386 = 7 - LdMachoCpuAmd64 = 0x1000007 + LdMachoCpuAmd64 = 1<<24 | 7 LdMachoCpuMips = 8 LdMachoCpu98000 = 10 LdMachoCpuHppa = 11 LdMachoCpuArm = 12 + LdMachoCpuArm64 = 1<<24 | 12 LdMachoCpu88000 = 13 LdMachoCpuSparc = 14 LdMachoCpu860 = 15 @@ -471,11 +472,14 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, switch arch.Family { default: return errorf("mach-o %s unimplemented", arch.Name) - case sys.AMD64: if e != binary.LittleEndian || m.cputype != LdMachoCpuAmd64 { return errorf("mach-o object but not amd64") } + case sys.ARM64: + if e != binary.LittleEndian || m.cputype != LdMachoCpuArm64 { + return errorf("mach-o object but not arm64") + } } m.cmd = make([]ldMachoCmd, ncmd) @@ -633,7 +637,9 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, } bld.SetType(l.SymType(outer)) - l.AddInteriorSym(outer, s) + if l.SymSize(outer) != 0 { // skip empty section (0-sized symbol) + l.AddInteriorSym(outer, s) + } bld.SetValue(int64(machsym.value - sect.addr)) if !l.AttrCgoExportDynamic(s) { @@ -722,27 +728,28 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, // Handle X86_64_RELOC_SIGNED referencing a section (rel.extrn == 0). p := l.Data(s) - if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_SIGNED { - // Calculate the addend as the offset into the section. - // - // The rip-relative offset stored in the object file is encoded - // as follows: - // - // movsd 0x00000360(%rip),%xmm0 - // - // To get the absolute address of the value this rip-relative address is pointing - // to, we must add the address of the next instruction to it. This is done by - // taking the address of the relocation and adding 4 to it (since the rip-relative - // offset can at most be 32 bits long). To calculate the offset into the section the - // relocation is referencing, we subtract the vaddr of the start of the referenced - // section found in the original object file. - // - // [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h] - secaddr := c.seg.sect[rel.symnum-1].addr - - rAdd = int64(uint64(int64(int32(e.Uint32(p[rOff:])))+int64(rOff)+4) - secaddr) - } else { - rAdd = int64(int32(e.Uint32(p[rOff:]))) + if arch.Family == sys.AMD64 { + if rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_SIGNED { + // Calculate the addend as the offset into the section. + // + // The rip-relative offset stored in the object file is encoded + // as follows: + // + // movsd 0x00000360(%rip),%xmm0 + // + // To get the absolute address of the value this rip-relative address is pointing + // to, we must add the address of the next instruction to it. This is done by + // taking the address of the relocation and adding 4 to it (since the rip-relative + // offset can at most be 32 bits long). To calculate the offset into the section the + // relocation is referencing, we subtract the vaddr of the start of the referenced + // section found in the original object file. + // + // [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h] + secaddr := c.seg.sect[rel.symnum-1].addr + rAdd = int64(uint64(int64(int32(e.Uint32(p[rOff:])))+int64(rOff)+4) - secaddr) + } else { + rAdd = int64(int32(e.Uint32(p[rOff:]))) + } } // An unsigned internal relocation has a value offset From d4da735091986868015369e01c63794af9cc9b84 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 09:49:20 -0400 Subject: [PATCH 020/403] io/fs: move FileInfo, FileMode, PathError, ErrInvalid, ... from os to io/fs First step of creating the new io/fs package. For #41190. Change-Id: I1339b1abdd533b0f1deab283628088b2f706fb5b Reviewed-on: https://go-review.googlesource.com/c/go/+/243906 Trust: Russ Cox Run-TryBot: Russ Cox Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Reviewed-by: Rob Pike Reviewed-by: Emmanuel Odeke --- api/except.txt | 228 ++++++++++++++++++++++++++----------------- api/next.txt | 88 ++++++++++++++++- src/cmd/api/goapi.go | 20 +++- src/io/fs/fs.go | 140 ++++++++++++++++++++++++++ src/os/error.go | 32 ++---- src/os/types.go | 91 ++++------------- 6 files changed, 406 insertions(+), 193 deletions(-) create mode 100644 src/io/fs/fs.go diff --git a/api/except.txt b/api/except.txt index 962bb14271d..6f6f839ba60 100644 --- a/api/except.txt +++ b/api/except.txt @@ -2,12 +2,56 @@ pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error) pkg math/big, const MaxBase = 36 pkg math/big, type Word uintptr pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error) +pkg os (linux-arm), const O_SYNC = 1052672 +pkg os (linux-arm), const O_SYNC = 4096 +pkg os (linux-arm-cgo), const O_SYNC = 1052672 +pkg os (linux-arm-cgo), const O_SYNC = 4096 +pkg os, const ModeAppend FileMode +pkg os, const ModeCharDevice FileMode +pkg os, const ModeDevice FileMode +pkg os, const ModeDir FileMode +pkg os, const ModeExclusive FileMode +pkg os, const ModeIrregular FileMode +pkg os, const ModeNamedPipe FileMode +pkg os, const ModePerm FileMode +pkg os, const ModeSetgid FileMode +pkg os, const ModeSetuid FileMode +pkg os, const ModeSocket FileMode +pkg os, const ModeSticky FileMode +pkg os, const ModeSymlink FileMode +pkg os, const ModeTemporary FileMode pkg os, const ModeType = 2399141888 pkg os, const ModeType = 2399666176 -pkg os (linux-arm), const O_SYNC = 4096 -pkg os (linux-arm-cgo), const O_SYNC = 4096 -pkg os (linux-arm), const O_SYNC = 1052672 -pkg os (linux-arm-cgo), const O_SYNC = 1052672 +pkg os, const ModeType FileMode +pkg os, func Chmod(string, FileMode) error +pkg os, func Lstat(string) (FileInfo, error) +pkg os, func Mkdir(string, FileMode) error +pkg os, func MkdirAll(string, FileMode) error +pkg os, func OpenFile(string, int, FileMode) (*File, error) +pkg os, func SameFile(FileInfo, FileInfo) bool +pkg os, func Stat(string) (FileInfo, error) +pkg os, method (*File) Chmod(FileMode) error +pkg os, method (*File) Readdir(int) ([]FileInfo, error) +pkg os, method (*File) Stat() (FileInfo, error) +pkg os, method (*PathError) Error() string +pkg os, method (*PathError) Timeout() bool +pkg os, method (*PathError) Unwrap() error +pkg os, method (FileMode) IsDir() bool +pkg os, method (FileMode) IsRegular() bool +pkg os, method (FileMode) Perm() FileMode +pkg os, method (FileMode) String() string +pkg os, type FileInfo interface { IsDir, ModTime, Mode, Name, Size, Sys } +pkg os, type FileInfo interface, IsDir() bool +pkg os, type FileInfo interface, ModTime() time.Time +pkg os, type FileInfo interface, Mode() FileMode +pkg os, type FileInfo interface, Name() string +pkg os, type FileInfo interface, Size() int64 +pkg os, type FileInfo interface, Sys() interface{} +pkg os, type FileMode uint32 +pkg os, type PathError struct +pkg os, type PathError struct, Err error +pkg os, type PathError struct, Op string +pkg os, type PathError struct, Path string pkg syscall (darwin-amd64), const ImplementsGetwd = false pkg syscall (darwin-amd64), func Fchflags(string, int) error pkg syscall (darwin-amd64-cgo), const ImplementsGetwd = false @@ -18,22 +62,72 @@ pkg syscall (freebsd-386), const ELAST = 94 pkg syscall (freebsd-386), const ImplementsGetwd = false pkg syscall (freebsd-386), const O_CLOEXEC = 0 pkg syscall (freebsd-386), func Fchflags(string, int) error +pkg syscall (freebsd-386), func Mknod(string, uint32, int) error +pkg syscall (freebsd-386), type Dirent struct, Fileno uint32 +pkg syscall (freebsd-386), type Dirent struct, Namlen uint8 +pkg syscall (freebsd-386), type Stat_t struct, Blksize uint32 +pkg syscall (freebsd-386), type Stat_t struct, Dev uint32 +pkg syscall (freebsd-386), type Stat_t struct, Gen uint32 +pkg syscall (freebsd-386), type Stat_t struct, Ino uint32 +pkg syscall (freebsd-386), type Stat_t struct, Lspare int32 +pkg syscall (freebsd-386), type Stat_t struct, Nlink uint16 +pkg syscall (freebsd-386), type Stat_t struct, Pad_cgo_0 [8]uint8 +pkg syscall (freebsd-386), type Stat_t struct, Rdev uint32 +pkg syscall (freebsd-386), type Statfs_t struct, Mntfromname [88]int8 +pkg syscall (freebsd-386), type Statfs_t struct, Mntonname [88]int8 pkg syscall (freebsd-386-cgo), const AF_MAX = 38 pkg syscall (freebsd-386-cgo), const DLT_MATCHING_MAX = 242 pkg syscall (freebsd-386-cgo), const ELAST = 94 pkg syscall (freebsd-386-cgo), const ImplementsGetwd = false pkg syscall (freebsd-386-cgo), const O_CLOEXEC = 0 +pkg syscall (freebsd-386-cgo), func Mknod(string, uint32, int) error +pkg syscall (freebsd-386-cgo), type Dirent struct, Fileno uint32 +pkg syscall (freebsd-386-cgo), type Dirent struct, Namlen uint8 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Blksize uint32 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Dev uint32 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Gen uint32 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Ino uint32 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Lspare int32 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Nlink uint16 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Pad_cgo_0 [8]uint8 +pkg syscall (freebsd-386-cgo), type Stat_t struct, Rdev uint32 +pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntfromname [88]int8 +pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntonname [88]int8 pkg syscall (freebsd-amd64), const AF_MAX = 38 pkg syscall (freebsd-amd64), const DLT_MATCHING_MAX = 242 pkg syscall (freebsd-amd64), const ELAST = 94 pkg syscall (freebsd-amd64), const ImplementsGetwd = false pkg syscall (freebsd-amd64), const O_CLOEXEC = 0 pkg syscall (freebsd-amd64), func Fchflags(string, int) error +pkg syscall (freebsd-amd64), func Mknod(string, uint32, int) error +pkg syscall (freebsd-amd64), type Dirent struct, Fileno uint32 +pkg syscall (freebsd-amd64), type Dirent struct, Namlen uint8 +pkg syscall (freebsd-amd64), type Stat_t struct, Blksize uint32 +pkg syscall (freebsd-amd64), type Stat_t struct, Dev uint32 +pkg syscall (freebsd-amd64), type Stat_t struct, Gen uint32 +pkg syscall (freebsd-amd64), type Stat_t struct, Ino uint32 +pkg syscall (freebsd-amd64), type Stat_t struct, Lspare int32 +pkg syscall (freebsd-amd64), type Stat_t struct, Nlink uint16 +pkg syscall (freebsd-amd64), type Stat_t struct, Rdev uint32 +pkg syscall (freebsd-amd64), type Statfs_t struct, Mntfromname [88]int8 +pkg syscall (freebsd-amd64), type Statfs_t struct, Mntonname [88]int8 pkg syscall (freebsd-amd64-cgo), const AF_MAX = 38 pkg syscall (freebsd-amd64-cgo), const DLT_MATCHING_MAX = 242 pkg syscall (freebsd-amd64-cgo), const ELAST = 94 pkg syscall (freebsd-amd64-cgo), const ImplementsGetwd = false pkg syscall (freebsd-amd64-cgo), const O_CLOEXEC = 0 +pkg syscall (freebsd-amd64-cgo), func Mknod(string, uint32, int) error +pkg syscall (freebsd-amd64-cgo), type Dirent struct, Fileno uint32 +pkg syscall (freebsd-amd64-cgo), type Dirent struct, Namlen uint8 +pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Blksize uint32 +pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Dev uint32 +pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Gen uint32 +pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Ino uint32 +pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Lspare int32 +pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Nlink uint16 +pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Rdev uint32 +pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntfromname [88]int8 +pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntonname [88]int8 pkg syscall (freebsd-arm), const AF_MAX = 38 pkg syscall (freebsd-arm), const BIOCGRTIMEOUT = 1074545262 pkg syscall (freebsd-arm), const BIOCSRTIMEOUT = 2148287085 @@ -62,10 +156,22 @@ pkg syscall (freebsd-arm), const SizeofSockaddrDatalink = 56 pkg syscall (freebsd-arm), const SizeofSockaddrUnix = 108 pkg syscall (freebsd-arm), const TIOCTIMESTAMP = 1074558041 pkg syscall (freebsd-arm), func Fchflags(string, int) error +pkg syscall (freebsd-arm), func Mknod(string, uint32, int) error pkg syscall (freebsd-arm), type BpfHdr struct, Pad_cgo_0 [2]uint8 +pkg syscall (freebsd-arm), type Dirent struct, Fileno uint32 +pkg syscall (freebsd-arm), type Dirent struct, Namlen uint8 pkg syscall (freebsd-arm), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8 pkg syscall (freebsd-arm), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8 +pkg syscall (freebsd-arm), type Stat_t struct, Blksize uint32 +pkg syscall (freebsd-arm), type Stat_t struct, Dev uint32 +pkg syscall (freebsd-arm), type Stat_t struct, Gen uint32 +pkg syscall (freebsd-arm), type Stat_t struct, Ino uint32 +pkg syscall (freebsd-arm), type Stat_t struct, Lspare int32 +pkg syscall (freebsd-arm), type Stat_t struct, Nlink uint16 pkg syscall (freebsd-arm), type Stat_t struct, Pad_cgo_0 [4]uint8 +pkg syscall (freebsd-arm), type Stat_t struct, Rdev uint32 +pkg syscall (freebsd-arm), type Statfs_t struct, Mntfromname [88]int8 +pkg syscall (freebsd-arm), type Statfs_t struct, Mntonname [88]int8 pkg syscall (freebsd-arm-cgo), const AF_MAX = 38 pkg syscall (freebsd-arm-cgo), const BIOCGRTIMEOUT = 1074545262 pkg syscall (freebsd-arm-cgo), const BIOCSRTIMEOUT = 2148287085 @@ -94,10 +200,22 @@ pkg syscall (freebsd-arm-cgo), const SizeofSockaddrDatalink = 56 pkg syscall (freebsd-arm-cgo), const SizeofSockaddrUnix = 108 pkg syscall (freebsd-arm-cgo), const TIOCTIMESTAMP = 1074558041 pkg syscall (freebsd-arm-cgo), func Fchflags(string, int) error +pkg syscall (freebsd-arm-cgo), func Mknod(string, uint32, int) error pkg syscall (freebsd-arm-cgo), type BpfHdr struct, Pad_cgo_0 [2]uint8 +pkg syscall (freebsd-arm-cgo), type Dirent struct, Fileno uint32 +pkg syscall (freebsd-arm-cgo), type Dirent struct, Namlen uint8 pkg syscall (freebsd-arm-cgo), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8 pkg syscall (freebsd-arm-cgo), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8 +pkg syscall (freebsd-arm-cgo), type Stat_t struct, Blksize uint32 +pkg syscall (freebsd-arm-cgo), type Stat_t struct, Dev uint32 +pkg syscall (freebsd-arm-cgo), type Stat_t struct, Gen uint32 +pkg syscall (freebsd-arm-cgo), type Stat_t struct, Ino uint32 +pkg syscall (freebsd-arm-cgo), type Stat_t struct, Lspare int32 +pkg syscall (freebsd-arm-cgo), type Stat_t struct, Nlink uint16 pkg syscall (freebsd-arm-cgo), type Stat_t struct, Pad_cgo_0 [4]uint8 +pkg syscall (freebsd-arm-cgo), type Stat_t struct, Rdev uint32 +pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntfromname [88]int8 +pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntonname [88]int8 pkg syscall (linux-386), type Cmsghdr struct, X__cmsg_data [0]uint8 pkg syscall (linux-386-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8 pkg syscall (linux-amd64), type Cmsghdr struct, X__cmsg_data [0]uint8 @@ -109,10 +227,10 @@ pkg syscall (netbsd-386-cgo), const ImplementsGetwd = false pkg syscall (netbsd-amd64), const ImplementsGetwd = false pkg syscall (netbsd-amd64-cgo), const ImplementsGetwd = false pkg syscall (netbsd-arm), const ImplementsGetwd = false -pkg syscall (netbsd-arm-cgo), const ImplementsGetwd = false pkg syscall (netbsd-arm), const SizeofIfData = 132 pkg syscall (netbsd-arm), func Fchflags(string, int) error pkg syscall (netbsd-arm), type IfMsghdr struct, Pad_cgo_1 [4]uint8 +pkg syscall (netbsd-arm-cgo), const ImplementsGetwd = false pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132 pkg syscall (netbsd-arm-cgo), func Fchflags(string, int) error pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8 @@ -140,6 +258,7 @@ pkg syscall (openbsd-386), const SYS_GETITIMER = 86 pkg syscall (openbsd-386), const SYS_GETRUSAGE = 117 pkg syscall (openbsd-386), const SYS_GETTIMEOFDAY = 116 pkg syscall (openbsd-386), const SYS_KEVENT = 270 +pkg syscall (openbsd-386), const SYS_KILL = 37 pkg syscall (openbsd-386), const SYS_LSTAT = 293 pkg syscall (openbsd-386), const SYS_NANOSLEEP = 240 pkg syscall (openbsd-386), const SYS_SELECT = 93 @@ -193,6 +312,7 @@ pkg syscall (openbsd-386-cgo), const SYS_GETITIMER = 86 pkg syscall (openbsd-386-cgo), const SYS_GETRUSAGE = 117 pkg syscall (openbsd-386-cgo), const SYS_GETTIMEOFDAY = 116 pkg syscall (openbsd-386-cgo), const SYS_KEVENT = 270 +pkg syscall (openbsd-386-cgo), const SYS_KILL = 37 pkg syscall (openbsd-386-cgo), const SYS_LSTAT = 293 pkg syscall (openbsd-386-cgo), const SYS_NANOSLEEP = 240 pkg syscall (openbsd-386-cgo), const SYS_SELECT = 93 @@ -257,6 +377,7 @@ pkg syscall (openbsd-amd64), const SYS_GETITIMER = 86 pkg syscall (openbsd-amd64), const SYS_GETRUSAGE = 117 pkg syscall (openbsd-amd64), const SYS_GETTIMEOFDAY = 116 pkg syscall (openbsd-amd64), const SYS_KEVENT = 270 +pkg syscall (openbsd-amd64), const SYS_KILL = 37 pkg syscall (openbsd-amd64), const SYS_LSTAT = 293 pkg syscall (openbsd-amd64), const SYS_NANOSLEEP = 240 pkg syscall (openbsd-amd64), const SYS_SELECT = 93 @@ -320,6 +441,7 @@ pkg syscall (openbsd-amd64-cgo), const SYS_GETITIMER = 86 pkg syscall (openbsd-amd64-cgo), const SYS_GETRUSAGE = 117 pkg syscall (openbsd-amd64-cgo), const SYS_GETTIMEOFDAY = 116 pkg syscall (openbsd-amd64-cgo), const SYS_KEVENT = 270 +pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37 pkg syscall (openbsd-amd64-cgo), const SYS_LSTAT = 293 pkg syscall (openbsd-amd64-cgo), const SYS_NANOSLEEP = 240 pkg syscall (openbsd-amd64-cgo), const SYS_SELECT = 93 @@ -348,19 +470,6 @@ pkg syscall (openbsd-amd64-cgo), type Statfs_t struct, F_spare [3]uint32 pkg syscall (openbsd-amd64-cgo), type Statfs_t struct, Pad_cgo_1 [4]uint8 pkg syscall (openbsd-amd64-cgo), type Timespec struct, Pad_cgo_0 [4]uint8 pkg syscall (openbsd-amd64-cgo), type Timespec struct, Sec int32 -pkg testing, func RegisterCover(Cover) -pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M -pkg text/template/parse, type DotNode bool -pkg text/template/parse, type Node interface { Copy, String, Type } -pkg unicode, const Version = "6.2.0" -pkg unicode, const Version = "6.3.0" -pkg unicode, const Version = "7.0.0" -pkg unicode, const Version = "8.0.0" -pkg syscall (openbsd-386), const SYS_KILL = 37 -pkg syscall (openbsd-386-cgo), const SYS_KILL = 37 -pkg syscall (openbsd-amd64), const SYS_KILL = 37 -pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37 -pkg unicode, const Version = "9.0.0" pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983295 pkg syscall (windows-386), type AddrinfoW struct, Addr uintptr pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara uintptr @@ -379,81 +488,16 @@ pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr pkg syscall (windows-amd64), type RawSockaddrAny struct, Pad [96]int8 -pkg syscall (freebsd-386), func Mknod(string, uint32, int) error -pkg syscall (freebsd-386), type Dirent struct, Fileno uint32 -pkg syscall (freebsd-386), type Dirent struct, Namlen uint8 -pkg syscall (freebsd-386), type Stat_t struct, Blksize uint32 -pkg syscall (freebsd-386), type Stat_t struct, Dev uint32 -pkg syscall (freebsd-386), type Stat_t struct, Gen uint32 -pkg syscall (freebsd-386), type Stat_t struct, Ino uint32 -pkg syscall (freebsd-386), type Stat_t struct, Lspare int32 -pkg syscall (freebsd-386), type Stat_t struct, Nlink uint16 -pkg syscall (freebsd-386), type Stat_t struct, Pad_cgo_0 [8]uint8 -pkg syscall (freebsd-386), type Stat_t struct, Rdev uint32 -pkg syscall (freebsd-386), type Statfs_t struct, Mntfromname [88]int8 -pkg syscall (freebsd-386), type Statfs_t struct, Mntonname [88]int8 -pkg syscall (freebsd-386-cgo), func Mknod(string, uint32, int) error -pkg syscall (freebsd-386-cgo), type Dirent struct, Fileno uint32 -pkg syscall (freebsd-386-cgo), type Dirent struct, Namlen uint8 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Blksize uint32 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Dev uint32 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Gen uint32 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Ino uint32 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Lspare int32 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Nlink uint16 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Pad_cgo_0 [8]uint8 -pkg syscall (freebsd-386-cgo), type Stat_t struct, Rdev uint32 -pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntfromname [88]int8 -pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntonname [88]int8 -pkg syscall (freebsd-amd64), func Mknod(string, uint32, int) error -pkg syscall (freebsd-amd64), type Dirent struct, Fileno uint32 -pkg syscall (freebsd-amd64), type Dirent struct, Namlen uint8 -pkg syscall (freebsd-amd64), type Stat_t struct, Blksize uint32 -pkg syscall (freebsd-amd64), type Stat_t struct, Dev uint32 -pkg syscall (freebsd-amd64), type Stat_t struct, Gen uint32 -pkg syscall (freebsd-amd64), type Stat_t struct, Ino uint32 -pkg syscall (freebsd-amd64), type Stat_t struct, Lspare int32 -pkg syscall (freebsd-amd64), type Stat_t struct, Nlink uint16 -pkg syscall (freebsd-amd64), type Stat_t struct, Rdev uint32 -pkg syscall (freebsd-amd64), type Statfs_t struct, Mntfromname [88]int8 -pkg syscall (freebsd-amd64), type Statfs_t struct, Mntonname [88]int8 -pkg syscall (freebsd-amd64-cgo), func Mknod(string, uint32, int) error -pkg syscall (freebsd-amd64-cgo), type Dirent struct, Fileno uint32 -pkg syscall (freebsd-amd64-cgo), type Dirent struct, Namlen uint8 -pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Blksize uint32 -pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Dev uint32 -pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Gen uint32 -pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Ino uint32 -pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Lspare int32 -pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Nlink uint16 -pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Rdev uint32 -pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntfromname [88]int8 -pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntonname [88]int8 -pkg syscall (freebsd-arm), func Mknod(string, uint32, int) error -pkg syscall (freebsd-arm), type Dirent struct, Fileno uint32 -pkg syscall (freebsd-arm), type Dirent struct, Namlen uint8 -pkg syscall (freebsd-arm), type Stat_t struct, Blksize uint32 -pkg syscall (freebsd-arm), type Stat_t struct, Dev uint32 -pkg syscall (freebsd-arm), type Stat_t struct, Gen uint32 -pkg syscall (freebsd-arm), type Stat_t struct, Ino uint32 -pkg syscall (freebsd-arm), type Stat_t struct, Lspare int32 -pkg syscall (freebsd-arm), type Stat_t struct, Nlink uint16 -pkg syscall (freebsd-arm), type Stat_t struct, Rdev uint32 -pkg syscall (freebsd-arm), type Statfs_t struct, Mntfromname [88]int8 -pkg syscall (freebsd-arm), type Statfs_t struct, Mntonname [88]int8 -pkg syscall (freebsd-arm-cgo), func Mknod(string, uint32, int) error -pkg syscall (freebsd-arm-cgo), type Dirent struct, Fileno uint32 -pkg syscall (freebsd-arm-cgo), type Dirent struct, Namlen uint8 -pkg syscall (freebsd-arm-cgo), type Stat_t struct, Blksize uint32 -pkg syscall (freebsd-arm-cgo), type Stat_t struct, Dev uint32 -pkg syscall (freebsd-arm-cgo), type Stat_t struct, Gen uint32 -pkg syscall (freebsd-arm-cgo), type Stat_t struct, Ino uint32 -pkg syscall (freebsd-arm-cgo), type Stat_t struct, Lspare int32 -pkg syscall (freebsd-arm-cgo), type Stat_t struct, Nlink uint16 -pkg syscall (freebsd-arm-cgo), type Stat_t struct, Rdev uint32 -pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntfromname [88]int8 -pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntonname [88]int8 +pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M +pkg testing, func RegisterCover(Cover) pkg text/scanner, const GoTokens = 1012 +pkg text/template/parse, type DotNode bool +pkg text/template/parse, type Node interface { Copy, String, Type } pkg unicode, const Version = "10.0.0" pkg unicode, const Version = "11.0.0" pkg unicode, const Version = "12.0.0" +pkg unicode, const Version = "6.2.0" +pkg unicode, const Version = "6.3.0" +pkg unicode, const Version = "7.0.0" +pkg unicode, const Version = "8.0.0" +pkg unicode, const Version = "9.0.0" diff --git a/api/next.txt b/api/next.txt index 59422cca4d4..3184a8ceaed 100644 --- a/api/next.txt +++ b/api/next.txt @@ -223,15 +223,97 @@ pkg io, type ReadSeekCloser interface { Close, Read, Seek } pkg io, type ReadSeekCloser interface, Close() error pkg io, type ReadSeekCloser interface, Read([]uint8) (int, error) pkg io, type ReadSeekCloser interface, Seek(int64, int) (int64, error) +pkg io/fs, const ModeAppend = 1073741824 +pkg io/fs, const ModeAppend FileMode +pkg io/fs, const ModeCharDevice = 2097152 +pkg io/fs, const ModeCharDevice FileMode +pkg io/fs, const ModeDevice = 67108864 +pkg io/fs, const ModeDevice FileMode +pkg io/fs, const ModeDir = 2147483648 +pkg io/fs, const ModeDir FileMode +pkg io/fs, const ModeExclusive = 536870912 +pkg io/fs, const ModeExclusive FileMode +pkg io/fs, const ModeIrregular = 524288 +pkg io/fs, const ModeIrregular FileMode +pkg io/fs, const ModeNamedPipe = 33554432 +pkg io/fs, const ModeNamedPipe FileMode +pkg io/fs, const ModePerm = 511 +pkg io/fs, const ModePerm FileMode +pkg io/fs, const ModeSetgid = 4194304 +pkg io/fs, const ModeSetgid FileMode +pkg io/fs, const ModeSetuid = 8388608 +pkg io/fs, const ModeSetuid FileMode +pkg io/fs, const ModeSocket = 16777216 +pkg io/fs, const ModeSocket FileMode +pkg io/fs, const ModeSticky = 1048576 +pkg io/fs, const ModeSticky FileMode +pkg io/fs, const ModeSymlink = 134217728 +pkg io/fs, const ModeSymlink FileMode +pkg io/fs, const ModeTemporary = 268435456 +pkg io/fs, const ModeTemporary FileMode +pkg io/fs, const ModeType = 2401763328 +pkg io/fs, const ModeType FileMode +pkg io/fs, method (*PathError) Error() string +pkg io/fs, method (*PathError) Timeout() bool +pkg io/fs, method (*PathError) Unwrap() error +pkg io/fs, method (FileMode) IsDir() bool +pkg io/fs, method (FileMode) IsRegular() bool +pkg io/fs, method (FileMode) Perm() FileMode +pkg io/fs, method (FileMode) String() string +pkg io/fs, method (FileMode) Type() FileMode +pkg io/fs, type FileInfo interface { IsDir, ModTime, Mode, Name, Size, Sys } +pkg io/fs, type FileInfo interface, IsDir() bool +pkg io/fs, type FileInfo interface, ModTime() time.Time +pkg io/fs, type FileInfo interface, Mode() FileMode +pkg io/fs, type FileInfo interface, Name() string +pkg io/fs, type FileInfo interface, Size() int64 +pkg io/fs, type FileInfo interface, Sys() interface{} +pkg io/fs, type FileMode uint32 +pkg io/fs, type PathError struct +pkg io/fs, type PathError struct, Err error +pkg io/fs, type PathError struct, Op string +pkg io/fs, type PathError struct, Path string +pkg io/fs, var ErrClosed error +pkg io/fs, var ErrExist error +pkg io/fs, var ErrInvalid error +pkg io/fs, var ErrNotExist error +pkg io/fs, var ErrPermission error pkg net, var ErrClosed error pkg net/http, type Transport struct, GetProxyConnectHeader func(context.Context, *url.URL, string) (Header, error) +pkg os, const ModeAppend fs.FileMode +pkg os, const ModeCharDevice fs.FileMode +pkg os, const ModeDevice fs.FileMode +pkg os, const ModeDir fs.FileMode +pkg os, const ModeExclusive fs.FileMode +pkg os, const ModeIrregular fs.FileMode +pkg os, const ModeNamedPipe fs.FileMode +pkg os, const ModePerm fs.FileMode +pkg os, const ModeSetgid fs.FileMode +pkg os, const ModeSetuid fs.FileMode +pkg os, const ModeSocket fs.FileMode +pkg os, const ModeSticky fs.FileMode +pkg os, const ModeSymlink fs.FileMode +pkg os, const ModeTemporary fs.FileMode +pkg os, const ModeType fs.FileMode +pkg os, func Chmod(string, fs.FileMode) error +pkg os, func Lstat(string) (fs.FileInfo, error) +pkg os, func Mkdir(string, fs.FileMode) error +pkg os, func MkdirAll(string, fs.FileMode) error +pkg os, func OpenFile(string, int, fs.FileMode) (*File, error) +pkg os, func SameFile(fs.FileInfo, fs.FileInfo) bool +pkg os, func Stat(string) (fs.FileInfo, error) +pkg os, method (*File) Chmod(fs.FileMode) error pkg os, method (*File) ReadDir(int) ([]DirEntry, error) -pkg os, method (FileMode) Type() FileMode +pkg os, method (*File) Readdir(int) ([]fs.FileInfo, error) +pkg os, method (*File) Stat() (fs.FileInfo, error) pkg os, type DirEntry interface { Info, IsDir, Name, Type } -pkg os, type DirEntry interface, Info() (FileInfo, error) +pkg os, type DirEntry interface, Info() (fs.FileInfo, error) pkg os, type DirEntry interface, IsDir() bool pkg os, type DirEntry interface, Name() string -pkg os, type DirEntry interface, Type() FileMode +pkg os, type DirEntry interface, Type() fs.FileMode +pkg os, type FileInfo = fs.FileInfo +pkg os, type FileMode = fs.FileMode +pkg os, type PathError = fs.PathError pkg os/signal, func NotifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc) pkg testing/iotest, func ErrReader(error) io.Reader pkg text/template/parse, const NodeComment = 20 diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 6a80ed269b4..b14d57c2368 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -326,6 +326,18 @@ func compareAPI(w io.Writer, features, required, optional, exception []string, a return } +// aliasReplacer applies type aliases to earlier API files, +// to avoid misleading negative results. +// This makes all the references to os.FileInfo in go1.txt +// be read as if they said fs.FileInfo, since os.FileInfo is now an alias. +// If there are many of these, we could do a more general solution, +// but for now the replacer is fine. +var aliasReplacer = strings.NewReplacer( + "os.FileInfo", "fs.FileInfo", + "os.FileMode", "fs.FileMode", + "os.PathError", "fs.PathError", +) + func fileFeatures(filename string) []string { if filename == "" { return nil @@ -334,7 +346,9 @@ func fileFeatures(filename string) []string { if err != nil { log.Fatalf("Error reading file %s: %v", filename, err) } - lines := strings.Split(string(bs), "\n") + s := string(bs) + s = aliasReplacer.Replace(s) + lines := strings.Split(s, "\n") var nonblank []string for _, line := range lines { line = strings.TrimSpace(line) @@ -856,6 +870,10 @@ func (w *Walker) emitObj(obj types.Object) { func (w *Walker) emitType(obj *types.TypeName) { name := obj.Name() typ := obj.Type() + if obj.IsAlias() { + w.emitf("type %s = %s", name, w.typeString(typ)) + return + } switch typ := typ.Underlying().(type) { case *types.Struct: w.emitStructType(name, typ) diff --git a/src/io/fs/fs.go b/src/io/fs/fs.go new file mode 100644 index 00000000000..de5c465d9d3 --- /dev/null +++ b/src/io/fs/fs.go @@ -0,0 +1,140 @@ +// Copyright 2020 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 fs defines basic interfaces to a file system. +// A file system can be provided by the host operating system +// but also by other packages. +package fs + +import ( + "internal/oserror" + "time" +) + +// Generic file system errors. +// Errors returned by file systems can be tested against these errors +// using errors.Is. +var ( + ErrInvalid = errInvalid() // "invalid argument" + ErrPermission = errPermission() // "permission denied" + ErrExist = errExist() // "file already exists" + ErrNotExist = errNotExist() // "file does not exist" + ErrClosed = errClosed() // "file already closed" +) + +func errInvalid() error { return oserror.ErrInvalid } +func errPermission() error { return oserror.ErrPermission } +func errExist() error { return oserror.ErrExist } +func errNotExist() error { return oserror.ErrNotExist } +func errClosed() error { return oserror.ErrClosed } + +// A FileInfo describes a file and is returned by Stat. +type FileInfo interface { + Name() string // base name of the file + Size() int64 // length in bytes for regular files; system-dependent for others + Mode() FileMode // file mode bits + ModTime() time.Time // modification time + IsDir() bool // abbreviation for Mode().IsDir() + Sys() interface{} // underlying data source (can return nil) +} + +// A FileMode represents a file's mode and permission bits. +// The bits have the same definition on all systems, so that +// information about files can be moved from one system +// to another portably. Not all bits apply to all systems. +// The only required bit is ModeDir for directories. +type FileMode uint32 + +// The defined file mode bits are the most significant bits of the FileMode. +// The nine least-significant bits are the standard Unix rwxrwxrwx permissions. +// The values of these bits should be considered part of the public API and +// may be used in wire protocols or disk representations: they must not be +// changed, although new bits might be added. +const ( + // The single letters are the abbreviations + // used by the String method's formatting. + ModeDir FileMode = 1 << (32 - 1 - iota) // d: is a directory + ModeAppend // a: append-only + ModeExclusive // l: exclusive use + ModeTemporary // T: temporary file; Plan 9 only + ModeSymlink // L: symbolic link + ModeDevice // D: device file + ModeNamedPipe // p: named pipe (FIFO) + ModeSocket // S: Unix domain socket + ModeSetuid // u: setuid + ModeSetgid // g: setgid + ModeCharDevice // c: Unix character device, when ModeDevice is set + ModeSticky // t: sticky + ModeIrregular // ?: non-regular file; nothing else is known about this file + + // Mask for the type bits. For regular files, none will be set. + ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregular + + ModePerm FileMode = 0777 // Unix permission bits +) + +func (m FileMode) String() string { + const str = "dalTLDpSugct?" + var buf [32]byte // Mode is uint32. + w := 0 + for i, c := range str { + if m&(1< Date: Tue, 7 Jul 2020 13:49:21 -0400 Subject: [PATCH 021/403] all: update references to symbols moved from os to io/fs The old os references are still valid, but update our code to reflect best practices and get used to the new locations. Code compiled with the bootstrap toolchain (cmd/asm, cmd/dist, cmd/compile, debug/elf) must remain Go 1.4-compatible and is excluded. For #41190. Change-Id: I8f9526977867c10a221e2f392f78d7dec073f1bd Reviewed-on: https://go-review.googlesource.com/c/go/+/243907 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/archive/tar/common.go | 68 +++++++++--------- src/archive/tar/stat_unix.go | 4 +- src/archive/tar/tar_test.go | 19 ++--- src/archive/zip/reader_test.go | 11 +-- src/archive/zip/struct.go | 72 +++++++++---------- src/archive/zip/writer_test.go | 10 +-- src/cmd/doc/pkg.go | 10 +-- src/cmd/fix/main.go | 5 +- src/cmd/go/go_test.go | 7 +- src/cmd/go/internal/cache/cache.go | 3 +- src/cmd/go/internal/fsys/fsys.go | 41 +++++------ src/cmd/go/internal/fsys/fsys_test.go | 39 +++++----- src/cmd/go/internal/imports/scan.go | 3 +- src/cmd/go/internal/load/pkg.go | 5 +- .../lockedfile/internal/filelock/filelock.go | 5 +- .../internal/filelock/filelock_fcntl.go | 6 +- .../internal/filelock/filelock_other.go | 6 +- .../internal/filelock/filelock_plan9.go | 8 +-- .../internal/filelock/filelock_unix.go | 4 +- .../internal/filelock/filelock_windows.go | 6 +- src/cmd/go/internal/lockedfile/lockedfile.go | 9 +-- .../lockedfile/lockedfile_filelock.go | 3 +- .../internal/lockedfile/lockedfile_plan9.go | 9 +-- src/cmd/go/internal/modcmd/vendor.go | 7 +- src/cmd/go/internal/modcmd/verify.go | 9 +-- src/cmd/go/internal/modfetch/cache.go | 7 +- .../go/internal/modfetch/codehost/codehost.go | 9 +-- src/cmd/go/internal/modfetch/codehost/git.go | 15 ++-- .../go/internal/modfetch/codehost/git_test.go | 3 +- src/cmd/go/internal/modfetch/codehost/vcs.go | 3 +- src/cmd/go/internal/modfetch/coderepo.go | 7 +- src/cmd/go/internal/modfetch/fetch.go | 11 +-- src/cmd/go/internal/modfetch/proxy.go | 8 +-- src/cmd/go/internal/modfetch/repo.go | 5 +- src/cmd/go/internal/modfetch/sumdb.go | 7 +- src/cmd/go/internal/modload/import.go | 3 +- src/cmd/go/internal/modload/load.go | 3 +- src/cmd/go/internal/modload/query.go | 11 +-- src/cmd/go/internal/modload/search.go | 5 +- src/cmd/go/internal/modload/stat_openfile.go | 3 +- src/cmd/go/internal/modload/stat_unix.go | 3 +- src/cmd/go/internal/modload/stat_windows.go | 6 +- src/cmd/go/internal/modload/vendor.go | 4 +- src/cmd/go/internal/renameio/renameio.go | 7 +- src/cmd/go/internal/renameio/umask_test.go | 5 +- src/cmd/go/internal/search/search.go | 7 +- src/cmd/go/internal/test/test.go | 3 +- src/cmd/go/internal/vcs/vcs.go | 5 +- src/cmd/go/internal/version/version.go | 11 +-- src/cmd/go/internal/web/api.go | 6 +- src/cmd/go/internal/web/file_test.go | 5 +- src/cmd/go/internal/work/build_test.go | 3 +- src/cmd/go/internal/work/exec.go | 9 +-- src/cmd/go/proxy_test.go | 5 +- src/cmd/go/script_test.go | 7 +- src/cmd/go/testdata/addmod.go | 3 +- src/cmd/go/testdata/savedir.go | 3 +- src/cmd/gofmt/gofmt.go | 9 +-- src/cmd/gofmt/long_test.go | 3 +- src/cmd/internal/buildid/buildid.go | 9 +-- src/cmd/internal/buildid/note.go | 7 +- src/cmd/internal/moddeps/moddeps_test.go | 3 +- src/cmd/pack/pack.go | 3 +- src/cmd/pack/pack_test.go | 11 +-- src/compress/gzip/issue14937_test.go | 3 +- src/crypto/rand/eagain.go | 4 +- src/crypto/x509/root_unix.go | 7 +- src/errors/errors.go | 12 ++-- src/errors/wrap.go | 4 +- src/errors/wrap_test.go | 11 +-- src/go/build/build.go | 9 +-- src/go/build/deps_test.go | 3 +- src/go/doc/doc_test.go | 6 +- src/go/doc/headscan.go | 5 +- src/go/parser/interface.go | 6 +- src/go/parser/parser_test.go | 4 +- src/index/suffixarray/suffixarray_test.go | 4 +- src/internal/poll/error_test.go | 3 +- .../reflectlite/reflect_mirror_test.go | 3 +- src/io/ioutil/ioutil.go | 5 +- src/io/ioutil/tempfile_test.go | 3 +- src/net/conf_test.go | 8 +-- src/net/dnsconfig_unix_test.go | 3 +- src/net/error_test.go | 13 ++-- src/net/http/example_filesystem_test.go | 14 ++-- src/net/http/fs.go | 9 +-- src/net/http/fs_test.go | 27 +++---- src/net/ipsock_plan9.go | 3 +- src/os/error_test.go | 55 +++++++------- src/os/error_unix_test.go | 11 +-- src/os/error_windows_test.go | 11 +-- src/os/example_test.go | 5 +- src/os/exec/exec_plan9.go | 4 +- src/os/exec/exec_unix.go | 4 +- src/os/exec/exec_windows.go | 4 +- src/os/exec/lp_plan9.go | 3 +- src/os/exec/lp_unix.go | 3 +- src/os/exec/lp_windows.go | 5 +- src/os/os_test.go | 2 +- src/os/os_windows_test.go | 11 +-- src/os/pipe_test.go | 17 ++--- src/os/removeall_test.go | 2 +- src/os/signal/signal_cgo_test.go | 3 +- src/os/stat_test.go | 19 ++--- src/path/filepath/example_unix_walk_test.go | 3 +- src/path/filepath/path.go | 7 +- src/path/filepath/path_test.go | 15 ++-- src/path/filepath/path_windows_test.go | 3 +- src/path/filepath/symlink.go | 3 +- src/runtime/testdata/testprogcgo/exec.go | 3 +- src/syscall/syscall_js.go | 2 +- src/syscall/syscall_linux_test.go | 3 +- src/syscall/syscall_plan9.go | 2 +- src/syscall/syscall_unix.go | 2 +- src/syscall/syscall_windows.go | 2 +- 115 files changed, 529 insertions(+), 450 deletions(-) diff --git a/src/archive/tar/common.go b/src/archive/tar/common.go index dee9e47e4ae..c667cfc8720 100644 --- a/src/archive/tar/common.go +++ b/src/archive/tar/common.go @@ -13,8 +13,8 @@ package tar import ( "errors" "fmt" + "io/fs" "math" - "os" "path" "reflect" "strconv" @@ -525,12 +525,12 @@ func (h Header) allowedFormats() (format Format, paxHdrs map[string]string, err return format, paxHdrs, err } -// FileInfo returns an os.FileInfo for the Header. -func (h *Header) FileInfo() os.FileInfo { +// FileInfo returns an fs.FileInfo for the Header. +func (h *Header) FileInfo() fs.FileInfo { return headerFileInfo{h} } -// headerFileInfo implements os.FileInfo. +// headerFileInfo implements fs.FileInfo. type headerFileInfo struct { h *Header } @@ -549,57 +549,57 @@ func (fi headerFileInfo) Name() string { } // Mode returns the permission and mode bits for the headerFileInfo. -func (fi headerFileInfo) Mode() (mode os.FileMode) { +func (fi headerFileInfo) Mode() (mode fs.FileMode) { // Set file permission bits. - mode = os.FileMode(fi.h.Mode).Perm() + mode = fs.FileMode(fi.h.Mode).Perm() // Set setuid, setgid and sticky bits. if fi.h.Mode&c_ISUID != 0 { - mode |= os.ModeSetuid + mode |= fs.ModeSetuid } if fi.h.Mode&c_ISGID != 0 { - mode |= os.ModeSetgid + mode |= fs.ModeSetgid } if fi.h.Mode&c_ISVTX != 0 { - mode |= os.ModeSticky + mode |= fs.ModeSticky } // Set file mode bits; clear perm, setuid, setgid, and sticky bits. - switch m := os.FileMode(fi.h.Mode) &^ 07777; m { + switch m := fs.FileMode(fi.h.Mode) &^ 07777; m { case c_ISDIR: - mode |= os.ModeDir + mode |= fs.ModeDir case c_ISFIFO: - mode |= os.ModeNamedPipe + mode |= fs.ModeNamedPipe case c_ISLNK: - mode |= os.ModeSymlink + mode |= fs.ModeSymlink case c_ISBLK: - mode |= os.ModeDevice + mode |= fs.ModeDevice case c_ISCHR: - mode |= os.ModeDevice - mode |= os.ModeCharDevice + mode |= fs.ModeDevice + mode |= fs.ModeCharDevice case c_ISSOCK: - mode |= os.ModeSocket + mode |= fs.ModeSocket } switch fi.h.Typeflag { case TypeSymlink: - mode |= os.ModeSymlink + mode |= fs.ModeSymlink case TypeChar: - mode |= os.ModeDevice - mode |= os.ModeCharDevice + mode |= fs.ModeDevice + mode |= fs.ModeCharDevice case TypeBlock: - mode |= os.ModeDevice + mode |= fs.ModeDevice case TypeDir: - mode |= os.ModeDir + mode |= fs.ModeDir case TypeFifo: - mode |= os.ModeNamedPipe + mode |= fs.ModeNamedPipe } return mode } // sysStat, if non-nil, populates h from system-dependent fields of fi. -var sysStat func(fi os.FileInfo, h *Header) error +var sysStat func(fi fs.FileInfo, h *Header) error const ( // Mode constants from the USTAR spec: @@ -623,10 +623,10 @@ const ( // If fi describes a symlink, FileInfoHeader records link as the link target. // If fi describes a directory, a slash is appended to the name. // -// Since os.FileInfo's Name method only returns the base name of +// Since fs.FileInfo's Name method only returns the base name of // the file it describes, it may be necessary to modify Header.Name // to provide the full path name of the file. -func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { +func FileInfoHeader(fi fs.FileInfo, link string) (*Header, error) { if fi == nil { return nil, errors.New("archive/tar: FileInfo is nil") } @@ -643,29 +643,29 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) { case fi.IsDir(): h.Typeflag = TypeDir h.Name += "/" - case fm&os.ModeSymlink != 0: + case fm&fs.ModeSymlink != 0: h.Typeflag = TypeSymlink h.Linkname = link - case fm&os.ModeDevice != 0: - if fm&os.ModeCharDevice != 0 { + case fm&fs.ModeDevice != 0: + if fm&fs.ModeCharDevice != 0 { h.Typeflag = TypeChar } else { h.Typeflag = TypeBlock } - case fm&os.ModeNamedPipe != 0: + case fm&fs.ModeNamedPipe != 0: h.Typeflag = TypeFifo - case fm&os.ModeSocket != 0: + case fm&fs.ModeSocket != 0: return nil, fmt.Errorf("archive/tar: sockets not supported") default: return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm) } - if fm&os.ModeSetuid != 0 { + if fm&fs.ModeSetuid != 0 { h.Mode |= c_ISUID } - if fm&os.ModeSetgid != 0 { + if fm&fs.ModeSetgid != 0 { h.Mode |= c_ISGID } - if fm&os.ModeSticky != 0 { + if fm&fs.ModeSticky != 0 { h.Mode |= c_ISVTX } // If possible, populate additional fields from OS-specific diff --git a/src/archive/tar/stat_unix.go b/src/archive/tar/stat_unix.go index 8df36169902..581d87dca9d 100644 --- a/src/archive/tar/stat_unix.go +++ b/src/archive/tar/stat_unix.go @@ -7,7 +7,7 @@ package tar import ( - "os" + "io/fs" "os/user" "runtime" "strconv" @@ -23,7 +23,7 @@ func init() { // The downside is that renaming uname or gname by the OS never takes effect. var userMap, groupMap sync.Map // map[int]string -func statUnix(fi os.FileInfo, h *Header) error { +func statUnix(fi fs.FileInfo, h *Header) error { sys, ok := fi.Sys().(*syscall.Stat_t) if !ok { return nil diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go index 2676853122a..f605dae9044 100644 --- a/src/archive/tar/tar_test.go +++ b/src/archive/tar/tar_test.go @@ -10,6 +10,7 @@ import ( "fmt" "internal/testenv" "io" + "io/fs" "io/ioutil" "math" "os" @@ -338,7 +339,7 @@ func TestRoundTrip(t *testing.T) { type headerRoundTripTest struct { h *Header - fm os.FileMode + fm fs.FileMode } func TestHeaderRoundTrip(t *testing.T) { @@ -361,7 +362,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1360600852, 0), Typeflag: TypeSymlink, }, - fm: 0777 | os.ModeSymlink, + fm: 0777 | fs.ModeSymlink, }, { // character device node. h: &Header{ @@ -371,7 +372,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1360578951, 0), Typeflag: TypeChar, }, - fm: 0666 | os.ModeDevice | os.ModeCharDevice, + fm: 0666 | fs.ModeDevice | fs.ModeCharDevice, }, { // block device node. h: &Header{ @@ -381,7 +382,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1360578954, 0), Typeflag: TypeBlock, }, - fm: 0660 | os.ModeDevice, + fm: 0660 | fs.ModeDevice, }, { // directory. h: &Header{ @@ -391,7 +392,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1360601116, 0), Typeflag: TypeDir, }, - fm: 0755 | os.ModeDir, + fm: 0755 | fs.ModeDir, }, { // fifo node. h: &Header{ @@ -401,7 +402,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1360578949, 0), Typeflag: TypeFifo, }, - fm: 0600 | os.ModeNamedPipe, + fm: 0600 | fs.ModeNamedPipe, }, { // setuid. h: &Header{ @@ -411,7 +412,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1355405093, 0), Typeflag: TypeReg, }, - fm: 0755 | os.ModeSetuid, + fm: 0755 | fs.ModeSetuid, }, { // setguid. h: &Header{ @@ -421,7 +422,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1360602346, 0), Typeflag: TypeReg, }, - fm: 0750 | os.ModeSetgid, + fm: 0750 | fs.ModeSetgid, }, { // sticky. h: &Header{ @@ -431,7 +432,7 @@ func TestHeaderRoundTrip(t *testing.T) { ModTime: time.Unix(1360602540, 0), Typeflag: TypeReg, }, - fm: 0600 | os.ModeSticky, + fm: 0600 | fs.ModeSticky, }, { // hard link. h: &Header{ diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index adca87a8b38..8a32d9c7dc9 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -10,6 +10,7 @@ import ( "encoding/hex" "internal/obscuretestdata" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -30,7 +31,7 @@ type ZipTest struct { type ZipTestFile struct { Name string - Mode os.FileMode + Mode fs.FileMode NonUTF8 bool ModTime time.Time Modified time.Time @@ -107,7 +108,7 @@ var tests = []ZipTest{ Name: "symlink", Content: []byte("../target"), Modified: time.Date(2012, 2, 3, 19, 56, 48, 0, timeZone(-2*time.Hour)), - Mode: 0777 | os.ModeSymlink, + Mode: 0777 | fs.ModeSymlink, }, }, }, @@ -149,7 +150,7 @@ var tests = []ZipTest{ Name: "dir/empty/", Content: []byte{}, Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, time.UTC), - Mode: os.ModeDir | 0777, + Mode: fs.ModeDir | 0777, }, { Name: "readonly", @@ -179,7 +180,7 @@ var tests = []ZipTest{ Name: "dir/empty/", Content: []byte{}, Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, timeZone(0)), - Mode: os.ModeDir | 0777, + Mode: fs.ModeDir | 0777, }, { Name: "readonly", @@ -645,7 +646,7 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) { } } -func testFileMode(t *testing.T, f *File, want os.FileMode) { +func testFileMode(t *testing.T, f *File, want fs.FileMode) { mode := f.Mode() if want == 0 { t.Errorf("%s mode: got %v, want none", f.Name, mode) diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go index 686e79781ac..355c57051bf 100644 --- a/src/archive/zip/struct.go +++ b/src/archive/zip/struct.go @@ -20,7 +20,7 @@ fields must be used instead. package zip import ( - "os" + "io/fs" "path" "time" ) @@ -137,12 +137,12 @@ type FileHeader struct { ExternalAttrs uint32 // Meaning depends on CreatorVersion } -// FileInfo returns an os.FileInfo for the FileHeader. -func (h *FileHeader) FileInfo() os.FileInfo { +// FileInfo returns an fs.FileInfo for the FileHeader. +func (h *FileHeader) FileInfo() fs.FileInfo { return headerFileInfo{h} } -// headerFileInfo implements os.FileInfo. +// headerFileInfo implements fs.FileInfo. type headerFileInfo struct { fh *FileHeader } @@ -161,17 +161,17 @@ func (fi headerFileInfo) ModTime() time.Time { } return fi.fh.Modified.UTC() } -func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() } +func (fi headerFileInfo) Mode() fs.FileMode { return fi.fh.Mode() } func (fi headerFileInfo) Sys() interface{} { return fi.fh } // FileInfoHeader creates a partially-populated FileHeader from an -// os.FileInfo. -// Because os.FileInfo's Name method returns only the base name of +// fs.FileInfo. +// Because fs.FileInfo's Name method returns only the base name of // the file it describes, it may be necessary to modify the Name field // of the returned header to provide the full path name of the file. // If compression is desired, callers should set the FileHeader.Method // field; it is unset by default. -func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) { +func FileInfoHeader(fi fs.FileInfo) (*FileHeader, error) { size := fi.Size() fh := &FileHeader{ Name: fi.Name(), @@ -280,7 +280,7 @@ const ( ) // Mode returns the permission and mode bits for the FileHeader. -func (h *FileHeader) Mode() (mode os.FileMode) { +func (h *FileHeader) Mode() (mode fs.FileMode) { switch h.CreatorVersion >> 8 { case creatorUnix, creatorMacOSX: mode = unixModeToFileMode(h.ExternalAttrs >> 16) @@ -288,18 +288,18 @@ func (h *FileHeader) Mode() (mode os.FileMode) { mode = msdosModeToFileMode(h.ExternalAttrs) } if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' { - mode |= os.ModeDir + mode |= fs.ModeDir } return mode } // SetMode changes the permission and mode bits for the FileHeader. -func (h *FileHeader) SetMode(mode os.FileMode) { +func (h *FileHeader) SetMode(mode fs.FileMode) { h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8 h.ExternalAttrs = fileModeToUnixMode(mode) << 16 // set MSDOS attributes too, as the original zip does. - if mode&os.ModeDir != 0 { + if mode&fs.ModeDir != 0 { h.ExternalAttrs |= msdosDir } if mode&0200 == 0 { @@ -312,9 +312,9 @@ func (h *FileHeader) isZip64() bool { return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max } -func msdosModeToFileMode(m uint32) (mode os.FileMode) { +func msdosModeToFileMode(m uint32) (mode fs.FileMode) { if m&msdosDir != 0 { - mode = os.ModeDir | 0777 + mode = fs.ModeDir | 0777 } else { mode = 0666 } @@ -324,64 +324,64 @@ func msdosModeToFileMode(m uint32) (mode os.FileMode) { return mode } -func fileModeToUnixMode(mode os.FileMode) uint32 { +func fileModeToUnixMode(mode fs.FileMode) uint32 { var m uint32 - switch mode & os.ModeType { + switch mode & fs.ModeType { default: m = s_IFREG - case os.ModeDir: + case fs.ModeDir: m = s_IFDIR - case os.ModeSymlink: + case fs.ModeSymlink: m = s_IFLNK - case os.ModeNamedPipe: + case fs.ModeNamedPipe: m = s_IFIFO - case os.ModeSocket: + case fs.ModeSocket: m = s_IFSOCK - case os.ModeDevice: - if mode&os.ModeCharDevice != 0 { + case fs.ModeDevice: + if mode&fs.ModeCharDevice != 0 { m = s_IFCHR } else { m = s_IFBLK } } - if mode&os.ModeSetuid != 0 { + if mode&fs.ModeSetuid != 0 { m |= s_ISUID } - if mode&os.ModeSetgid != 0 { + if mode&fs.ModeSetgid != 0 { m |= s_ISGID } - if mode&os.ModeSticky != 0 { + if mode&fs.ModeSticky != 0 { m |= s_ISVTX } return m | uint32(mode&0777) } -func unixModeToFileMode(m uint32) os.FileMode { - mode := os.FileMode(m & 0777) +func unixModeToFileMode(m uint32) fs.FileMode { + mode := fs.FileMode(m & 0777) switch m & s_IFMT { case s_IFBLK: - mode |= os.ModeDevice + mode |= fs.ModeDevice case s_IFCHR: - mode |= os.ModeDevice | os.ModeCharDevice + mode |= fs.ModeDevice | fs.ModeCharDevice case s_IFDIR: - mode |= os.ModeDir + mode |= fs.ModeDir case s_IFIFO: - mode |= os.ModeNamedPipe + mode |= fs.ModeNamedPipe case s_IFLNK: - mode |= os.ModeSymlink + mode |= fs.ModeSymlink case s_IFREG: // nothing to do case s_IFSOCK: - mode |= os.ModeSocket + mode |= fs.ModeSocket } if m&s_ISGID != 0 { - mode |= os.ModeSetgid + mode |= fs.ModeSetgid } if m&s_ISUID != 0 { - mode |= os.ModeSetuid + mode |= fs.ModeSetuid } if m&s_ISVTX != 0 { - mode |= os.ModeSticky + mode |= fs.ModeSticky } return mode } diff --git a/src/archive/zip/writer_test.go b/src/archive/zip/writer_test.go index 1fedfd85e82..282f9ec2163 100644 --- a/src/archive/zip/writer_test.go +++ b/src/archive/zip/writer_test.go @@ -9,9 +9,9 @@ import ( "encoding/binary" "fmt" "io" + "io/fs" "io/ioutil" "math/rand" - "os" "strings" "testing" "time" @@ -23,7 +23,7 @@ type WriteTest struct { Name string Data []byte Method uint16 - Mode os.FileMode + Mode fs.FileMode } var writeTests = []WriteTest{ @@ -43,19 +43,19 @@ var writeTests = []WriteTest{ Name: "setuid", Data: []byte("setuid file"), Method: Deflate, - Mode: 0755 | os.ModeSetuid, + Mode: 0755 | fs.ModeSetuid, }, { Name: "setgid", Data: []byte("setgid file"), Method: Deflate, - Mode: 0755 | os.ModeSetgid, + Mode: 0755 | fs.ModeSetgid, }, { Name: "symlink", Data: []byte("../link/target"), Method: Deflate, - Mode: 0755 | os.ModeSymlink, + Mode: 0755 | fs.ModeSymlink, }, } diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index ffc302c78c7..c2e06ebc8b0 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -16,8 +16,8 @@ import ( "go/printer" "go/token" "io" + "io/fs" "log" - "os" "path/filepath" "strings" "unicode" @@ -129,11 +129,10 @@ func (pkg *Package) Fatalf(format string, args ...interface{}) { // parsePackage turns the build package we found into a parsed package // we can then use to generate documentation. func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Package { - fs := token.NewFileSet() // include tells parser.ParseDir which files to include. // That means the file must be in the build package's GoFiles or CgoFiles // list only (no tag-ignored files, tests, swig or other non-Go files). - include := func(info os.FileInfo) bool { + include := func(info fs.FileInfo) bool { for _, name := range pkg.GoFiles { if name == info.Name() { return true @@ -146,7 +145,8 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag } return false } - pkgs, err := parser.ParseDir(fs, pkg.Dir, include, parser.ParseComments) + fset := token.NewFileSet() + pkgs, err := parser.ParseDir(fset, pkg.Dir, include, parser.ParseComments) if err != nil { log.Fatal(err) } @@ -203,7 +203,7 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag typedValue: typedValue, constructor: constructor, build: pkg, - fs: fs, + fs: fset, } p.buf.pkg = p return p diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go index d19dde6b4ae..dfba902f483 100644 --- a/src/cmd/fix/main.go +++ b/src/cmd/fix/main.go @@ -13,6 +13,7 @@ import ( "go/parser" "go/scanner" "go/token" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -235,7 +236,7 @@ func walkDir(path string) { filepath.Walk(path, visitFile) } -func visitFile(path string, f os.FileInfo, err error) error { +func visitFile(path string, f fs.FileInfo, err error) error { if err == nil && isGoFile(f) { err = processFile(path, false) } @@ -245,7 +246,7 @@ func visitFile(path string, f os.FileInfo, err error) error { return nil } -func isGoFile(f os.FileInfo) bool { +func isGoFile(f fs.FileInfo) bool { // ignore non-Go files name := f.Name() return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 093ea2ffa13..2c11d169596 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -15,6 +15,7 @@ import ( "internal/race" "internal/testenv" "io" + "io/fs" "io/ioutil" "log" "os" @@ -813,7 +814,7 @@ func (tg *testgoData) cleanup() { func removeAll(dir string) error { // module cache has 0444 directories; // make them writable in order to remove content. - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { // chmod not only directories, but also things that we couldn't even stat // due to permission errors: they may also be unreadable directories. if err != nil || info.IsDir() { @@ -860,7 +861,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { srcdir := filepath.Join(testGOROOT, copydir) tg.tempDir(filepath.Join("goroot", copydir)) err := filepath.Walk(srcdir, - func(path string, info os.FileInfo, err error) error { + func(path string, info fs.FileInfo, err error) error { if err != nil { return err } @@ -2018,7 +2019,7 @@ func main() { tg.run("build", "-o", exe, "p") } -func copyFile(src, dst string, perm os.FileMode) error { +func copyFile(src, dst string, perm fs.FileMode) error { sf, err := os.Open(src) if err != nil { return err diff --git a/src/cmd/go/internal/cache/cache.go b/src/cmd/go/internal/cache/cache.go index 15545ac31f8..5464fe5685c 100644 --- a/src/cmd/go/internal/cache/cache.go +++ b/src/cmd/go/internal/cache/cache.go @@ -12,6 +12,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -54,7 +55,7 @@ func Open(dir string) (*Cache, error) { return nil, err } if !info.IsDir() { - return nil, &os.PathError{Op: "open", Path: dir, Err: fmt.Errorf("not a directory")} + return nil, &fs.PathError{Op: "open", Path: dir, Err: fmt.Errorf("not a directory")} } for i := 0; i < 256; i++ { name := filepath.Join(dir, fmt.Sprintf("%02x", i)) diff --git a/src/cmd/go/internal/fsys/fsys.go b/src/cmd/go/internal/fsys/fsys.go index 489af93496f..67359ffb6da 100644 --- a/src/cmd/go/internal/fsys/fsys.go +++ b/src/cmd/go/internal/fsys/fsys.go @@ -6,6 +6,7 @@ import ( "encoding/json" "errors" "fmt" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -240,7 +241,7 @@ var errNotDir = errors.New("not a directory") // readDir reads a dir on disk, returning an error that is errNotDir if the dir is not a directory. // Unfortunately, the error returned by ioutil.ReadDir if dir is not a directory // can vary depending on the OS (Linux, Mac, Windows return ENOTDIR; BSD returns EINVAL). -func readDir(dir string) ([]os.FileInfo, error) { +func readDir(dir string) ([]fs.FileInfo, error) { fis, err := ioutil.ReadDir(dir) if err == nil { return fis, nil @@ -249,25 +250,25 @@ func readDir(dir string) ([]os.FileInfo, error) { if os.IsNotExist(err) { return nil, err } else if dirfi, staterr := os.Stat(dir); staterr == nil && !dirfi.IsDir() { - return nil, &os.PathError{Op: "ReadDir", Path: dir, Err: errNotDir} + return nil, &fs.PathError{Op: "ReadDir", Path: dir, Err: errNotDir} } else { return nil, err } } -// ReadDir provides a slice of os.FileInfo entries corresponding +// ReadDir provides a slice of fs.FileInfo entries corresponding // to the overlaid files in the directory. -func ReadDir(dir string) ([]os.FileInfo, error) { +func ReadDir(dir string) ([]fs.FileInfo, error) { dir = canonicalize(dir) if _, ok := parentIsOverlayFile(dir); ok { - return nil, &os.PathError{Op: "ReadDir", Path: dir, Err: errNotDir} + return nil, &fs.PathError{Op: "ReadDir", Path: dir, Err: errNotDir} } dirNode := overlay[dir] if dirNode == nil { return readDir(dir) } else if dirNode.isDeleted() { - return nil, &os.PathError{Op: "ReadDir", Path: dir, Err: os.ErrNotExist} + return nil, &fs.PathError{Op: "ReadDir", Path: dir, Err: fs.ErrNotExist} } diskfis, err := readDir(dir) if err != nil && !os.IsNotExist(err) && !errors.Is(err, errNotDir) { @@ -275,7 +276,7 @@ func ReadDir(dir string) ([]os.FileInfo, error) { } // Stat files in overlay to make composite list of fileinfos - files := make(map[string]os.FileInfo) + files := make(map[string]fs.FileInfo) for _, f := range diskfis { files[f.Name()] = f } @@ -327,14 +328,14 @@ func Open(path string) (*os.File, error) { cpath := canonicalize(path) if node, ok := overlay[cpath]; ok { if node.isDir() { - return nil, &os.PathError{Op: "Open", Path: path, Err: errors.New("fsys.Open doesn't support opening directories yet")} + return nil, &fs.PathError{Op: "Open", Path: path, Err: errors.New("fsys.Open doesn't support opening directories yet")} } return os.Open(node.actualFilePath) } else if parent, ok := parentIsOverlayFile(filepath.Dir(cpath)); ok { // The file is deleted explicitly in the Replace map, // or implicitly because one of its parent directories was // replaced by a file. - return nil, &os.PathError{ + return nil, &fs.PathError{ Op: "Open", Path: path, Err: fmt.Errorf("file %s does not exist: parent directory %s is replaced by a file in overlay", path, parent)} @@ -387,7 +388,7 @@ func IsDirWithGoFiles(dir string) (bool, error) { // walk recursively descends path, calling walkFn. Copied, with some // modifications from path/filepath.walk. -func walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { +func walk(path string, info fs.FileInfo, walkFn filepath.WalkFunc) error { if !info.IsDir() { return walkFn(path, info, nil) } @@ -432,11 +433,11 @@ func Walk(root string, walkFn filepath.WalkFunc) error { } // lstat implements a version of os.Lstat that operates on the overlay filesystem. -func lstat(path string) (os.FileInfo, error) { +func lstat(path string) (fs.FileInfo, error) { cpath := canonicalize(path) if _, ok := parentIsOverlayFile(filepath.Dir(cpath)); ok { - return nil, &os.PathError{Op: "lstat", Path: cpath, Err: os.ErrNotExist} + return nil, &fs.PathError{Op: "lstat", Path: cpath, Err: fs.ErrNotExist} } node, ok := overlay[cpath] @@ -447,7 +448,7 @@ func lstat(path string) (os.FileInfo, error) { switch { case node.isDeleted(): - return nil, &os.PathError{Op: "lstat", Path: cpath, Err: os.ErrNotExist} + return nil, &fs.PathError{Op: "lstat", Path: cpath, Err: fs.ErrNotExist} case node.isDir(): return fakeDir(filepath.Base(cpath)), nil default: @@ -459,22 +460,22 @@ func lstat(path string) (os.FileInfo, error) { } } -// fakeFile provides an os.FileInfo implementation for an overlaid file, +// fakeFile provides an fs.FileInfo implementation for an overlaid file, // so that the file has the name of the overlaid file, but takes all // other characteristics of the replacement file. type fakeFile struct { name string - real os.FileInfo + real fs.FileInfo } func (f fakeFile) Name() string { return f.name } func (f fakeFile) Size() int64 { return f.real.Size() } -func (f fakeFile) Mode() os.FileMode { return f.real.Mode() } +func (f fakeFile) Mode() fs.FileMode { return f.real.Mode() } func (f fakeFile) ModTime() time.Time { return f.real.ModTime() } func (f fakeFile) IsDir() bool { return f.real.IsDir() } func (f fakeFile) Sys() interface{} { return f.real.Sys() } -// missingFile provides an os.FileInfo for an overlaid file where the +// missingFile provides an fs.FileInfo for an overlaid file where the // destination file in the overlay doesn't exist. It returns zero values // for the fileInfo methods other than Name, set to the file's name, and Mode // set to ModeIrregular. @@ -482,19 +483,19 @@ type missingFile string func (f missingFile) Name() string { return string(f) } func (f missingFile) Size() int64 { return 0 } -func (f missingFile) Mode() os.FileMode { return os.ModeIrregular } +func (f missingFile) Mode() fs.FileMode { return fs.ModeIrregular } func (f missingFile) ModTime() time.Time { return time.Unix(0, 0) } func (f missingFile) IsDir() bool { return false } func (f missingFile) Sys() interface{} { return nil } -// fakeDir provides an os.FileInfo implementation for directories that are +// fakeDir provides an fs.FileInfo implementation for directories that are // implicitly created by overlaid files. Each directory in the // path of an overlaid file is considered to exist in the overlay filesystem. type fakeDir string func (f fakeDir) Name() string { return string(f) } func (f fakeDir) Size() int64 { return 0 } -func (f fakeDir) Mode() os.FileMode { return os.ModeDir | 0500 } +func (f fakeDir) Mode() fs.FileMode { return fs.ModeDir | 0500 } func (f fakeDir) ModTime() time.Time { return time.Unix(0, 0) } func (f fakeDir) IsDir() bool { return true } func (f fakeDir) Sys() interface{} { return nil } diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go index 6cf59fba47d..ba9f05d00b9 100644 --- a/src/cmd/go/internal/fsys/fsys_test.go +++ b/src/cmd/go/internal/fsys/fsys_test.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "internal/testenv" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -291,8 +292,8 @@ x _, gotErr := ReadDir(dir) if gotErr == nil { t.Errorf("ReadDir(%q): got no error, want error", dir) - } else if _, ok := gotErr.(*os.PathError); !ok { - t.Errorf("ReadDir(%q): got error with string %q and type %T, want os.PathError", dir, gotErr.Error(), gotErr) + } else if _, ok := gotErr.(*fs.PathError); !ok { + t.Errorf("ReadDir(%q): got error with string %q and type %T, want fs.PathError", dir, gotErr.Error(), gotErr) } } } @@ -489,7 +490,7 @@ func TestWalk(t *testing.T) { path string name string size int64 - mode os.FileMode + mode fs.FileMode isDir bool } testCases := []struct { @@ -504,7 +505,7 @@ func TestWalk(t *testing.T) { `, ".", []file{ - {".", "root", 0, os.ModeDir | 0700, true}, + {".", "root", 0, fs.ModeDir | 0700, true}, {"file.txt", "file.txt", 0, 0600, false}, }, }, @@ -520,7 +521,7 @@ contents of other file `, ".", []file{ - {".", "root", 0, os.ModeDir | 0500, true}, + {".", "root", 0, fs.ModeDir | 0500, true}, {"file.txt", "file.txt", 23, 0600, false}, {"other.txt", "other.txt", 23, 0600, false}, }, @@ -536,7 +537,7 @@ contents of other file `, ".", []file{ - {".", "root", 0, os.ModeDir | 0500, true}, + {".", "root", 0, fs.ModeDir | 0500, true}, {"file.txt", "file.txt", 23, 0600, false}, {"other.txt", "other.txt", 23, 0600, false}, }, @@ -552,8 +553,8 @@ contents of other file `, ".", []file{ - {".", "root", 0, os.ModeDir | 0500, true}, - {"dir", "dir", 0, os.ModeDir | 0500, true}, + {".", "root", 0, fs.ModeDir | 0500, true}, + {"dir", "dir", 0, fs.ModeDir | 0500, true}, {"dir" + string(filepath.Separator) + "file.txt", "file.txt", 23, 0600, false}, {"other.txt", "other.txt", 23, 0600, false}, }, @@ -565,7 +566,7 @@ contents of other file initOverlay(t, tc.overlay) var got []file - Walk(tc.root, func(path string, info os.FileInfo, err error) error { + Walk(tc.root, func(path string, info fs.FileInfo, err error) error { got = append(got, file{path, info.Name(), info.Size(), info.Mode(), info.IsDir()}) return nil }) @@ -580,8 +581,8 @@ contents of other file if got[i].name != tc.wantFiles[i].name { t.Errorf("name of file #%v in walk, got %q, want %q", i, got[i].name, tc.wantFiles[i].name) } - if got[i].mode&(os.ModeDir|0700) != tc.wantFiles[i].mode { - t.Errorf("mode&(os.ModeDir|0700) for mode of file #%v in walk, got %v, want %v", i, got[i].mode&(os.ModeDir|0700), tc.wantFiles[i].mode) + if got[i].mode&(fs.ModeDir|0700) != tc.wantFiles[i].mode { + t.Errorf("mode&(fs.ModeDir|0700) for mode of file #%v in walk, got %v, want %v", i, got[i].mode&(fs.ModeDir|0700), tc.wantFiles[i].mode) } if got[i].isDir != tc.wantFiles[i].isDir { t.Errorf("isDir for file #%v in walk, got %v, want %v", i, got[i].isDir, tc.wantFiles[i].isDir) @@ -610,7 +611,7 @@ func TestWalk_SkipDir(t *testing.T) { `) var seen []string - Walk(".", func(path string, info os.FileInfo, err error) error { + Walk(".", func(path string, info fs.FileInfo, err error) error { seen = append(seen, path) if path == "skipthisdir" || path == filepath.Join("dontskip", "skip") { return filepath.SkipDir @@ -635,7 +636,7 @@ func TestWalk_Error(t *testing.T) { initOverlay(t, "{}") alreadyCalled := false - err := Walk("foo", func(path string, info os.FileInfo, err error) error { + err := Walk("foo", func(path string, info fs.FileInfo, err error) error { if alreadyCalled { t.Fatal("expected walk function to be called exactly once, but it was called more than once") } @@ -683,7 +684,7 @@ func TestWalk_Symlink(t *testing.T) { t.Run(tc.name, func(t *testing.T) { var got []string - err := Walk(tc.dir, func(path string, info os.FileInfo, err error) error { + err := Walk(tc.dir, func(path string, info fs.FileInfo, err error) error { got = append(got, path) if err != nil { t.Errorf("walkfn: got non nil err argument: %v, want nil err argument", err) @@ -706,7 +707,7 @@ func TestLstat(t *testing.T) { type file struct { name string size int64 - mode os.FileMode // mode & (os.ModeDir|0x700): only check 'user' permissions + mode fs.FileMode // mode & (fs.ModeDir|0x700): only check 'user' permissions isDir bool } @@ -771,7 +772,7 @@ contents`, -- dir/foo.txt -- `, "dir", - file{"dir", 0, 0700 | os.ModeDir, true}, + file{"dir", 0, 0700 | fs.ModeDir, true}, false, }, { @@ -780,7 +781,7 @@ contents`, -- dummy.txt -- `, "dir", - file{"dir", 0, 0500 | os.ModeDir, true}, + file{"dir", 0, 0500 | fs.ModeDir, true}, false, }, } @@ -801,8 +802,8 @@ contents`, if got.Name() != tc.want.name { t.Errorf("lstat(%q).Name(): got %q, want %q", tc.path, got.Name(), tc.want.name) } - if got.Mode()&(os.ModeDir|0700) != tc.want.mode { - t.Errorf("lstat(%q).Mode()&(os.ModeDir|0700): got %v, want %v", tc.path, got.Mode()&(os.ModeDir|0700), tc.want.mode) + if got.Mode()&(fs.ModeDir|0700) != tc.want.mode { + t.Errorf("lstat(%q).Mode()&(fs.ModeDir|0700): got %v, want %v", tc.path, got.Mode()&(fs.ModeDir|0700), tc.want.mode) } if got.IsDir() != tc.want.isDir { t.Errorf("lstat(%q).IsDir(): got %v, want %v", tc.path, got.IsDir(), tc.want.isDir) diff --git a/src/cmd/go/internal/imports/scan.go b/src/cmd/go/internal/imports/scan.go index 42ee49aaaac..d45393f36c5 100644 --- a/src/cmd/go/internal/imports/scan.go +++ b/src/cmd/go/internal/imports/scan.go @@ -6,6 +6,7 @@ package imports import ( "fmt" + "io/fs" "os" "path/filepath" "sort" @@ -26,7 +27,7 @@ func ScanDir(dir string, tags map[string]bool) ([]string, []string, error) { // If the directory entry is a symlink, stat it to obtain the info for the // link target instead of the link itself. - if info.Mode()&os.ModeSymlink != 0 { + if info.Mode()&fs.ModeSymlink != 0 { info, err = os.Stat(filepath.Join(dir, name)) if err != nil { continue // Ignore broken symlinks. diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index f73b79d089b..066ff6c9815 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -14,6 +14,7 @@ import ( "go/build" "go/scanner" "go/token" + "io/fs" "io/ioutil" "os" pathpkg "path" @@ -2300,7 +2301,7 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package { // to make it look like this is a standard package or // command directory. So that local imports resolve // consistently, the files must all be in the same directory. - var dirent []os.FileInfo + var dirent []fs.FileInfo var dir string for _, file := range gofiles { fi, err := os.Stat(file) @@ -2321,7 +2322,7 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package { } dirent = append(dirent, fi) } - ctxt.ReadDir = func(string) ([]os.FileInfo, error) { return dirent, nil } + ctxt.ReadDir = func(string) ([]fs.FileInfo, error) { return dirent, nil } if cfg.ModulesEnabled { modload.ImportFromFiles(ctx, gofiles) diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock.go index aba3eed7767..05f27c321a8 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock.go @@ -9,6 +9,7 @@ package filelock import ( "errors" + "io/fs" "os" ) @@ -24,7 +25,7 @@ type File interface { Fd() uintptr // Stat returns the FileInfo structure describing file. - Stat() (os.FileInfo, error) + Stat() (fs.FileInfo, error) } // Lock places an advisory write lock on the file, blocking until it can be @@ -87,7 +88,7 @@ var ErrNotSupported = errors.New("operation not supported") // underlyingError returns the underlying error for known os error types. func underlyingError(err error) error { switch err := err.(type) { - case *os.PathError: + case *fs.PathError: return err.Err case *os.LinkError: return err.Err diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go index 8776c5741c7..1fa4327a89d 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go @@ -18,8 +18,8 @@ package filelock import ( "errors" "io" + "io/fs" "math/rand" - "os" "sync" "syscall" "time" @@ -61,7 +61,7 @@ func lock(f File, lt lockType) (err error) { mu.Lock() if i, dup := inodes[f]; dup && i != ino { mu.Unlock() - return &os.PathError{ + return &fs.PathError{ Op: lt.String(), Path: f.Name(), Err: errors.New("inode for file changed since last Lock or RLock"), @@ -152,7 +152,7 @@ func lock(f File, lt lockType) (err error) { if err != nil { unlock(f) - return &os.PathError{ + return &fs.PathError{ Op: lt.String(), Path: f.Name(), Err: err, diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go index 107611e1ce8..bc480343fc3 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_other.go @@ -6,7 +6,7 @@ package filelock -import "os" +import "io/fs" type lockType int8 @@ -16,7 +16,7 @@ const ( ) func lock(f File, lt lockType) error { - return &os.PathError{ + return &fs.PathError{ Op: lt.String(), Path: f.Name(), Err: ErrNotSupported, @@ -24,7 +24,7 @@ func lock(f File, lt lockType) error { } func unlock(f File) error { - return &os.PathError{ + return &fs.PathError{ Op: "Unlock", Path: f.Name(), Err: ErrNotSupported, diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go index afdffe323fc..0798ee469a4 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_plan9.go @@ -6,9 +6,7 @@ package filelock -import ( - "os" -) +import "io/fs" type lockType int8 @@ -18,7 +16,7 @@ const ( ) func lock(f File, lt lockType) error { - return &os.PathError{ + return &fs.PathError{ Op: lt.String(), Path: f.Name(), Err: ErrNotSupported, @@ -26,7 +24,7 @@ func lock(f File, lt lockType) error { } func unlock(f File) error { - return &os.PathError{ + return &fs.PathError{ Op: "Unlock", Path: f.Name(), Err: ErrNotSupported, diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go index 78f2c51129e..ed07bac6088 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_unix.go @@ -7,7 +7,7 @@ package filelock import ( - "os" + "io/fs" "syscall" ) @@ -26,7 +26,7 @@ func lock(f File, lt lockType) (err error) { } } if err != nil { - return &os.PathError{ + return &fs.PathError{ Op: lt.String(), Path: f.Name(), Err: err, diff --git a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go index 43e85e450ec..19de27eb9b6 100644 --- a/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go +++ b/src/cmd/go/internal/lockedfile/internal/filelock/filelock_windows.go @@ -8,7 +8,7 @@ package filelock import ( "internal/syscall/windows" - "os" + "io/fs" "syscall" ) @@ -34,7 +34,7 @@ func lock(f File, lt lockType) error { err := windows.LockFileEx(syscall.Handle(f.Fd()), uint32(lt), reserved, allBytes, allBytes, ol) if err != nil { - return &os.PathError{ + return &fs.PathError{ Op: lt.String(), Path: f.Name(), Err: err, @@ -47,7 +47,7 @@ func unlock(f File) error { ol := new(syscall.Overlapped) err := windows.UnlockFileEx(syscall.Handle(f.Fd()), reserved, allBytes, allBytes, ol) if err != nil { - return &os.PathError{ + return &fs.PathError{ Op: "Unlock", Path: f.Name(), Err: err, diff --git a/src/cmd/go/internal/lockedfile/lockedfile.go b/src/cmd/go/internal/lockedfile/lockedfile.go index 59b2dba44cd..503024da4bf 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile.go +++ b/src/cmd/go/internal/lockedfile/lockedfile.go @@ -9,6 +9,7 @@ package lockedfile import ( "fmt" "io" + "io/fs" "io/ioutil" "os" "runtime" @@ -35,7 +36,7 @@ type osFile struct { // OpenFile is like os.OpenFile, but returns a locked file. // If flag includes os.O_WRONLY or os.O_RDWR, the file is write-locked; // otherwise, it is read-locked. -func OpenFile(name string, flag int, perm os.FileMode) (*File, error) { +func OpenFile(name string, flag int, perm fs.FileMode) (*File, error) { var ( f = new(File) err error @@ -82,10 +83,10 @@ func Edit(name string) (*File, error) { // non-nil error. func (f *File) Close() error { if f.closed { - return &os.PathError{ + return &fs.PathError{ Op: "close", Path: f.Name(), - Err: os.ErrClosed, + Err: fs.ErrClosed, } } f.closed = true @@ -108,7 +109,7 @@ func Read(name string) ([]byte, error) { // Write opens the named file (creating it with the given permissions if needed), // then write-locks it and overwrites it with the given content. -func Write(name string, content io.Reader, perm os.FileMode) (err error) { +func Write(name string, content io.Reader, perm fs.FileMode) (err error) { f, err := OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) if err != nil { return err diff --git a/src/cmd/go/internal/lockedfile/lockedfile_filelock.go b/src/cmd/go/internal/lockedfile/lockedfile_filelock.go index f63dd8664b0..10e1240efdd 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile_filelock.go +++ b/src/cmd/go/internal/lockedfile/lockedfile_filelock.go @@ -7,12 +7,13 @@ package lockedfile import ( + "io/fs" "os" "cmd/go/internal/lockedfile/internal/filelock" ) -func openFile(name string, flag int, perm os.FileMode) (*os.File, error) { +func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) { // On BSD systems, we could add the O_SHLOCK or O_EXLOCK flag to the OpenFile // call instead of locking separately, but we have to support separate locking // calls for Linux and Windows anyway, so it's simpler to use that approach diff --git a/src/cmd/go/internal/lockedfile/lockedfile_plan9.go b/src/cmd/go/internal/lockedfile/lockedfile_plan9.go index 4a52c949763..51681381d76 100644 --- a/src/cmd/go/internal/lockedfile/lockedfile_plan9.go +++ b/src/cmd/go/internal/lockedfile/lockedfile_plan9.go @@ -7,6 +7,7 @@ package lockedfile import ( + "io/fs" "math/rand" "os" "strings" @@ -41,7 +42,7 @@ func isLocked(err error) bool { return false } -func openFile(name string, flag int, perm os.FileMode) (*os.File, error) { +func openFile(name string, flag int, perm fs.FileMode) (*os.File, error) { // Plan 9 uses a mode bit instead of explicit lock/unlock syscalls. // // Per http://man.cat-v.org/plan_9/5/stat: “Exclusive use files may be open @@ -56,8 +57,8 @@ func openFile(name string, flag int, perm os.FileMode) (*os.File, error) { // have the ModeExclusive bit set. Set it before we call OpenFile, so that we // can be confident that a successful OpenFile implies exclusive use. if fi, err := os.Stat(name); err == nil { - if fi.Mode()&os.ModeExclusive == 0 { - if err := os.Chmod(name, fi.Mode()|os.ModeExclusive); err != nil { + if fi.Mode()&fs.ModeExclusive == 0 { + if err := os.Chmod(name, fi.Mode()|fs.ModeExclusive); err != nil { return nil, err } } @@ -68,7 +69,7 @@ func openFile(name string, flag int, perm os.FileMode) (*os.File, error) { nextSleep := 1 * time.Millisecond const maxSleep = 500 * time.Millisecond for { - f, err := os.OpenFile(name, flag, perm|os.ModeExclusive) + f, err := os.OpenFile(name, flag, perm|fs.ModeExclusive) if err == nil { return f, nil } diff --git a/src/cmd/go/internal/modcmd/vendor.go b/src/cmd/go/internal/modcmd/vendor.go index 1bc4ab3defe..1b9ce605294 100644 --- a/src/cmd/go/internal/modcmd/vendor.go +++ b/src/cmd/go/internal/modcmd/vendor.go @@ -9,6 +9,7 @@ import ( "context" "fmt" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -232,7 +233,7 @@ var metaPrefixes = []string{ } // matchMetadata reports whether info is a metadata file. -func matchMetadata(dir string, info os.FileInfo) bool { +func matchMetadata(dir string, info fs.FileInfo) bool { name := info.Name() for _, p := range metaPrefixes { if strings.HasPrefix(name, p) { @@ -243,7 +244,7 @@ func matchMetadata(dir string, info os.FileInfo) bool { } // matchPotentialSourceFile reports whether info may be relevant to a build operation. -func matchPotentialSourceFile(dir string, info os.FileInfo) bool { +func matchPotentialSourceFile(dir string, info fs.FileInfo) bool { if strings.HasSuffix(info.Name(), "_test.go") { return false } @@ -269,7 +270,7 @@ func matchPotentialSourceFile(dir string, info os.FileInfo) bool { } // copyDir copies all regular files satisfying match(info) from src to dst. -func copyDir(dst, src string, match func(dir string, info os.FileInfo) bool) { +func copyDir(dst, src string, match func(dir string, info fs.FileInfo) bool) { files, err := ioutil.ReadDir(src) if err != nil { base.Fatalf("go mod vendor: %v", err) diff --git a/src/cmd/go/internal/modcmd/verify.go b/src/cmd/go/internal/modcmd/verify.go index bd591d3f32e..ce24793929d 100644 --- a/src/cmd/go/internal/modcmd/verify.go +++ b/src/cmd/go/internal/modcmd/verify.go @@ -9,6 +9,7 @@ import ( "context" "errors" "fmt" + "io/fs" "io/ioutil" "os" "runtime" @@ -88,8 +89,8 @@ func verifyMod(mod module.Version) []error { dir, dirErr := modfetch.DownloadDir(mod) data, err := ioutil.ReadFile(zip + "hash") if err != nil { - if zipErr != nil && errors.Is(zipErr, os.ErrNotExist) && - dirErr != nil && errors.Is(dirErr, os.ErrNotExist) { + if zipErr != nil && errors.Is(zipErr, fs.ErrNotExist) && + dirErr != nil && errors.Is(dirErr, fs.ErrNotExist) { // Nothing downloaded yet. Nothing to verify. return nil } @@ -98,7 +99,7 @@ func verifyMod(mod module.Version) []error { } h := string(bytes.TrimSpace(data)) - if zipErr != nil && errors.Is(zipErr, os.ErrNotExist) { + if zipErr != nil && errors.Is(zipErr, fs.ErrNotExist) { // ok } else { hZ, err := dirhash.HashZip(zip, dirhash.DefaultHash) @@ -109,7 +110,7 @@ func verifyMod(mod module.Version) []error { errs = append(errs, fmt.Errorf("%s %s: zip has been modified (%v)", mod.Path, mod.Version, zip)) } } - if dirErr != nil && errors.Is(dirErr, os.ErrNotExist) { + if dirErr != nil && errors.Is(dirErr, fs.ErrNotExist) { // ok } else { hD, err := dirhash.HashDir(dir, mod.Path+"@"+mod.Version, dirhash.DefaultHash) diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go index 6eadb026c9f..b7aa670250c 100644 --- a/src/cmd/go/internal/modfetch/cache.go +++ b/src/cmd/go/internal/modfetch/cache.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -60,7 +61,7 @@ func CachePath(m module.Version, suffix string) (string, error) { // DownloadDir returns the directory to which m should have been downloaded. // An error will be returned if the module path or version cannot be escaped. -// An error satisfying errors.Is(err, os.ErrNotExist) will be returned +// An error satisfying errors.Is(err, fs.ErrNotExist) will be returned // along with the directory if the directory does not exist or if the directory // is not completely populated. func DownloadDir(m module.Version) (string, error) { @@ -107,14 +108,14 @@ func DownloadDir(m module.Version) (string, error) { // DownloadDirPartialError is returned by DownloadDir if a module directory // exists but was not completely populated. // -// DownloadDirPartialError is equivalent to os.ErrNotExist. +// DownloadDirPartialError is equivalent to fs.ErrNotExist. type DownloadDirPartialError struct { Dir string Err error } func (e *DownloadDirPartialError) Error() string { return fmt.Sprintf("%s: %v", e.Dir, e.Err) } -func (e *DownloadDirPartialError) Is(err error) bool { return err == os.ErrNotExist } +func (e *DownloadDirPartialError) Is(err error) bool { return err == fs.ErrNotExist } // lockVersion locks a file within the module cache that guards the downloading // and extraction of the zipfile for the given module version. diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index df4cfdab1af..c5fbb31b2b7 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -11,6 +11,7 @@ import ( "crypto/sha256" "fmt" "io" + "io/fs" "io/ioutil" "os" "os/exec" @@ -105,7 +106,7 @@ type FileRev struct { Err error // error if any; os.IsNotExist(Err)==true if rev exists but file does not exist in that rev } -// UnknownRevisionError is an error equivalent to os.ErrNotExist, but for a +// UnknownRevisionError is an error equivalent to fs.ErrNotExist, but for a // revision rather than a file. type UnknownRevisionError struct { Rev string @@ -115,10 +116,10 @@ func (e *UnknownRevisionError) Error() string { return "unknown revision " + e.Rev } func (UnknownRevisionError) Is(err error) bool { - return err == os.ErrNotExist + return err == fs.ErrNotExist } -// ErrNoCommits is an error equivalent to os.ErrNotExist indicating that a given +// ErrNoCommits is an error equivalent to fs.ErrNotExist indicating that a given // repository or module contains no commits. var ErrNoCommits error = noCommitsError{} @@ -128,7 +129,7 @@ func (noCommitsError) Error() string { return "no commits" } func (noCommitsError) Is(err error) bool { - return err == os.ErrNotExist + return err == fs.ErrNotExist } // AllHex reports whether the revision rev is entirely lower-case hexadecimal digits. diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go index 5a35829c98c..58b4b2f2d3e 100644 --- a/src/cmd/go/internal/modfetch/codehost/git.go +++ b/src/cmd/go/internal/modfetch/codehost/git.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "net/url" "os" @@ -34,13 +35,13 @@ func LocalGitRepo(remote string) (Repo, error) { } // A notExistError wraps another error to retain its original text -// but makes it opaquely equivalent to os.ErrNotExist. +// but makes it opaquely equivalent to fs.ErrNotExist. type notExistError struct { err error } func (e notExistError) Error() string { return e.err.Error() } -func (notExistError) Is(err error) bool { return err == os.ErrNotExist } +func (notExistError) Is(err error) bool { return err == fs.ErrNotExist } const gitWorkDirType = "git3" @@ -188,7 +189,7 @@ func (r *gitRepo) loadRefs() { // For HTTP and HTTPS, that's easy to detect: we'll try to fetch the URL // ourselves and see what code it serves. if u, err := url.Parse(r.remoteURL); err == nil && (u.Scheme == "http" || u.Scheme == "https") { - if _, err := web.GetBytes(u); errors.Is(err, os.ErrNotExist) { + if _, err := web.GetBytes(u); errors.Is(err, fs.ErrNotExist) { gitErr = notExistError{gitErr} } } @@ -505,7 +506,7 @@ func (r *gitRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) { } out, err := Run(r.dir, "git", "cat-file", "blob", info.Name+":"+file) if err != nil { - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } return out, nil } @@ -629,9 +630,9 @@ func (r *gitRepo) readFileRevs(tags []string, file string, fileMap map[string]*F case "tag", "commit": switch fileType { default: - f.Err = &os.PathError{Path: tag + ":" + file, Op: "read", Err: fmt.Errorf("unexpected non-blob type %q", fileType)} + f.Err = &fs.PathError{Path: tag + ":" + file, Op: "read", Err: fmt.Errorf("unexpected non-blob type %q", fileType)} case "missing": - f.Err = &os.PathError{Path: tag + ":" + file, Op: "read", Err: os.ErrNotExist} + f.Err = &fs.PathError{Path: tag + ":" + file, Op: "read", Err: fs.ErrNotExist} case "blob": f.Data = fileData } @@ -826,7 +827,7 @@ func (r *gitRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser, archive, err := Run(r.dir, "git", "-c", "core.autocrlf=input", "-c", "core.eol=lf", "archive", "--format=zip", "--prefix=prefix/", info.Name, args) if err != nil { if bytes.Contains(err.(*RunError).Stderr, []byte("did not match any files")) { - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } return nil, err } diff --git a/src/cmd/go/internal/modfetch/codehost/git_test.go b/src/cmd/go/internal/modfetch/codehost/git_test.go index ba27c70f5a0..16908b3e849 100644 --- a/src/cmd/go/internal/modfetch/codehost/git_test.go +++ b/src/cmd/go/internal/modfetch/codehost/git_test.go @@ -10,6 +10,7 @@ import ( "flag" "fmt" "internal/testenv" + "io/fs" "io/ioutil" "log" "os" @@ -210,7 +211,7 @@ var readFileTests = []struct { repo: gitrepo1, rev: "v2.3.4", file: "another.txt", - err: os.ErrNotExist.Error(), + err: fs.ErrNotExist.Error(), }, } diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index 6278cb21e13..ec97fc7e1bd 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -9,6 +9,7 @@ import ( "fmt" "internal/lazyregexp" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -377,7 +378,7 @@ func (r *vcsRepo) ReadFile(rev, file string, maxSize int64) ([]byte, error) { out, err := Run(r.dir, r.cmd.readFile(rev, file, r.remote)) if err != nil { - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } return out, nil } diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index d99a31d3605..7f44e18a702 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "os" "path" @@ -1040,7 +1041,7 @@ type zipFile struct { } func (f zipFile) Path() string { return f.name } -func (f zipFile) Lstat() (os.FileInfo, error) { return f.f.FileInfo(), nil } +func (f zipFile) Lstat() (fs.FileInfo, error) { return f.f.FileInfo(), nil } func (f zipFile) Open() (io.ReadCloser, error) { return f.f.Open() } type dataFile struct { @@ -1049,7 +1050,7 @@ type dataFile struct { } func (f dataFile) Path() string { return f.name } -func (f dataFile) Lstat() (os.FileInfo, error) { return dataFileInfo{f}, nil } +func (f dataFile) Lstat() (fs.FileInfo, error) { return dataFileInfo{f}, nil } func (f dataFile) Open() (io.ReadCloser, error) { return ioutil.NopCloser(bytes.NewReader(f.data)), nil } @@ -1060,7 +1061,7 @@ type dataFileInfo struct { func (fi dataFileInfo) Name() string { return path.Base(fi.f.name) } func (fi dataFileInfo) Size() int64 { return int64(len(fi.f.data)) } -func (fi dataFileInfo) Mode() os.FileMode { return 0644 } +func (fi dataFileInfo) Mode() fs.FileMode { return 0644 } func (fi dataFileInfo) ModTime() time.Time { return time.Time{} } func (fi dataFileInfo) IsDir() bool { return false } func (fi dataFileInfo) Sys() interface{} { return nil } diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index 599419977a8..6ff455e89ce 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -67,7 +68,7 @@ func download(ctx context.Context, mod module.Version) (dir string, err error) { if err == nil { // The directory has already been completely extracted (no .partial file exists). return dir, nil - } else if dir == "" || !errors.Is(err, os.ErrNotExist) { + } else if dir == "" || !errors.Is(err, fs.ErrNotExist) { return "", err } @@ -314,10 +315,10 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e func makeDirsReadOnly(dir string) { type pathMode struct { path string - mode os.FileMode + mode fs.FileMode } var dirs []pathMode // in lexical order - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { if err == nil && info.Mode()&0222 != 0 { if info.IsDir() { dirs = append(dirs, pathMode{path, info.Mode()}) @@ -336,7 +337,7 @@ func makeDirsReadOnly(dir string) { // any permission changes needed to do so. func RemoveAll(dir string) error { // Module cache has 0555 directories; make them writable in order to remove content. - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { if err != nil { return nil // ignore errors walking in file system } @@ -441,7 +442,7 @@ func checkMod(mod module.Version) { } data, err := renameio.ReadFile(ziphash) if err != nil { - if errors.Is(err, os.ErrNotExist) { + if errors.Is(err, fs.ErrNotExist) { // This can happen if someone does rm -rf GOPATH/src/cache/download. So it goes. return } diff --git a/src/cmd/go/internal/modfetch/proxy.go b/src/cmd/go/internal/modfetch/proxy.go index 4ac26650a9b..819990b4030 100644 --- a/src/cmd/go/internal/modfetch/proxy.go +++ b/src/cmd/go/internal/modfetch/proxy.go @@ -9,9 +9,9 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "net/url" - "os" "path" pathpkg "path" "path/filepath" @@ -186,7 +186,7 @@ func proxyList() ([]proxySpec, error) { // TryProxies iterates f over each configured proxy (including "noproxy" and // "direct" if applicable) until f returns no error or until f returns an -// error that is not equivalent to os.ErrNotExist on a proxy configured +// error that is not equivalent to fs.ErrNotExist on a proxy configured // not to fall back on errors. // // TryProxies then returns that final error. @@ -222,7 +222,7 @@ func TryProxies(f func(proxy string) error) error { if err == nil { return nil } - isNotExistErr := errors.Is(err, os.ErrNotExist) + isNotExistErr := errors.Is(err, fs.ErrNotExist) if proxy.url == "direct" || (proxy.url == "noproxy" && err != errUseProxy) { bestErr = err @@ -428,7 +428,7 @@ func (p *proxyRepo) Stat(rev string) (*RevInfo, error) { func (p *proxyRepo) Latest() (*RevInfo, error) { data, err := p.getBytes("@latest") if err != nil { - if !errors.Is(err, os.ErrNotExist) { + if !errors.Is(err, fs.ErrNotExist) { return nil, p.versionError("", err) } return p.latest() diff --git a/src/cmd/go/internal/modfetch/repo.go b/src/cmd/go/internal/modfetch/repo.go index c7cf5595bd0..af9e24cefdc 100644 --- a/src/cmd/go/internal/modfetch/repo.go +++ b/src/cmd/go/internal/modfetch/repo.go @@ -7,6 +7,7 @@ package modfetch import ( "fmt" "io" + "io/fs" "os" "sort" "strconv" @@ -432,7 +433,7 @@ func (r errRepo) Latest() (*RevInfo, error) { return nil func (r errRepo) GoMod(version string) ([]byte, error) { return nil, r.err } func (r errRepo) Zip(dst io.Writer, version string) error { return r.err } -// A notExistError is like os.ErrNotExist, but with a custom message +// A notExistError is like fs.ErrNotExist, but with a custom message type notExistError struct { err error } @@ -446,7 +447,7 @@ func (e notExistError) Error() string { } func (notExistError) Is(target error) bool { - return target == os.ErrNotExist + return target == fs.ErrNotExist } func (e notExistError) Unwrap() error { diff --git a/src/cmd/go/internal/modfetch/sumdb.go b/src/cmd/go/internal/modfetch/sumdb.go index 47a25715314..5108961a334 100644 --- a/src/cmd/go/internal/modfetch/sumdb.go +++ b/src/cmd/go/internal/modfetch/sumdb.go @@ -12,6 +12,7 @@ import ( "bytes" "errors" "fmt" + "io/fs" "io/ioutil" "net/url" "os" @@ -182,7 +183,7 @@ func (c *dbClient) initBase() { return nil } }) - if errors.Is(err, os.ErrNotExist) { + if errors.Is(err, fs.ErrNotExist) { // No proxies, or all proxies failed (with 404, 410, or were were allowed // to fall back), or we reached an explicit "direct" or "off". c.base = c.direct @@ -203,7 +204,7 @@ func (c *dbClient) ReadConfig(file string) (data []byte, err error) { } targ := filepath.Join(cfg.SumdbDir, file) data, err = lockedfile.Read(targ) - if errors.Is(err, os.ErrNotExist) { + if errors.Is(err, fs.ErrNotExist) { // Treat non-existent as empty, to bootstrap the "latest" file // the first time we connect to a given database. return []byte{}, nil @@ -257,7 +258,7 @@ func (*dbClient) ReadCache(file string) ([]byte, error) { // during which the empty file can be locked for reading. // Treat observing an empty file as file not found. if err == nil && len(data) == 0 { - err = &os.PathError{Op: "read", Path: targ, Err: os.ErrNotExist} + err = &fs.PathError{Op: "read", Path: targ, Err: fs.ErrNotExist} } return data, err } diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 6d0d8de9445..bcbc9b0c3ad 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -10,6 +10,7 @@ import ( "fmt" "go/build" "internal/goroot" + "io/fs" "os" "path/filepath" "sort" @@ -347,7 +348,7 @@ func queryImport(ctx context.Context, path string) (module.Version, error) { candidates, err := QueryPattern(ctx, path, "latest", Selected, CheckAllowed) if err != nil { - if errors.Is(err, os.ErrNotExist) { + if errors.Is(err, fs.ErrNotExist) { // Return "cannot find module providing package […]" instead of whatever // low-level error QueryPattern produced. return module.Version{}, &ImportMissingError{Path: path, QueryErr: err} diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 4ddb817cf10..4b3ded83266 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -98,6 +98,7 @@ import ( "errors" "fmt" "go/build" + "io/fs" "os" "path" pathpkg "path" @@ -364,7 +365,7 @@ func resolveLocalPackage(dir string) (string, error) { if os.IsNotExist(err) { // Canonicalize OS-specific errors to errDirectoryNotFound so that error // messages will be easier for users to search for. - return "", &os.PathError{Op: "stat", Path: absDir, Err: errDirectoryNotFound} + return "", &fs.PathError{Op: "stat", Path: absDir, Err: errDirectoryNotFound} } return "", err } diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 3b27e66d019..6b147683888 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -8,6 +8,7 @@ import ( "context" "errors" "fmt" + "io/fs" "os" pathpkg "path" "path/filepath" @@ -145,7 +146,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed canonicalQuery := module.CanonicalVersion(query) if canonicalQuery != "" && query != canonicalQuery { info, err = repo.Stat(canonicalQuery) - if err != nil && !errors.Is(err, os.ErrNotExist) { + if err != nil && !errors.Is(err, fs.ErrNotExist) { return info, err } } @@ -230,7 +231,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed if qm.allowsVersion(ctx, latest.Version) { return lookup(latest.Version) } - } else if !errors.Is(err, os.ErrNotExist) { + } else if !errors.Is(err, fs.ErrNotExist) { return nil, err } } @@ -701,7 +702,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod noVersion = rErr } default: - if errors.Is(rErr, os.ErrNotExist) { + if errors.Is(rErr, fs.ErrNotExist) { if notExistErr == nil { notExistErr = rErr } @@ -744,7 +745,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod // A NoMatchingVersionError indicates that Query found a module at the requested // path, but not at any versions satisfying the query string and allow-function. // -// NOTE: NoMatchingVersionError MUST NOT implement Is(os.ErrNotExist). +// NOTE: NoMatchingVersionError MUST NOT implement Is(fs.ErrNotExist). // // If the module came from a proxy, that proxy had to return a successful status // code for the versions it knows about, and thus did not have the opportunity @@ -765,7 +766,7 @@ func (e *NoMatchingVersionError) Error() string { // module at the requested version, but that module did not contain any packages // matching the requested pattern. // -// NOTE: PackageNotInModuleError MUST NOT implement Is(os.ErrNotExist). +// NOTE: PackageNotInModuleError MUST NOT implement Is(fs.ErrNotExist). // // If the module came from a proxy, that proxy had to return a successful status // code for the versions it knows about, and thus did not have the opportunity diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go index 0f820267320..19289ceb9ce 100644 --- a/src/cmd/go/internal/modload/search.go +++ b/src/cmd/go/internal/modload/search.go @@ -7,6 +7,7 @@ package modload import ( "context" "fmt" + "io/fs" "os" "path/filepath" "strings" @@ -54,7 +55,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f walkPkgs := func(root, importPathRoot string, prune pruning) { root = filepath.Clean(root) - err := fsys.Walk(root, func(path string, fi os.FileInfo, err error) error { + err := fsys.Walk(root, func(path string, fi fs.FileInfo, err error) error { if err != nil { m.AddError(err) return nil @@ -85,7 +86,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } if !fi.IsDir() { - if fi.Mode()&os.ModeSymlink != 0 && want { + if fi.Mode()&fs.ModeSymlink != 0 && want { if target, err := os.Stat(path); err == nil && target.IsDir() { fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) } diff --git a/src/cmd/go/internal/modload/stat_openfile.go b/src/cmd/go/internal/modload/stat_openfile.go index 931aaf1577b..7cdeaf47a2f 100644 --- a/src/cmd/go/internal/modload/stat_openfile.go +++ b/src/cmd/go/internal/modload/stat_openfile.go @@ -13,12 +13,13 @@ package modload import ( + "io/fs" "os" ) // hasWritePerm reports whether the current user has permission to write to the // file with the given info. -func hasWritePerm(path string, _ os.FileInfo) bool { +func hasWritePerm(path string, _ fs.FileInfo) bool { if f, err := os.OpenFile(path, os.O_WRONLY, 0); err == nil { f.Close() return true diff --git a/src/cmd/go/internal/modload/stat_unix.go b/src/cmd/go/internal/modload/stat_unix.go index ea3b801f2c9..65068444d06 100644 --- a/src/cmd/go/internal/modload/stat_unix.go +++ b/src/cmd/go/internal/modload/stat_unix.go @@ -7,6 +7,7 @@ package modload import ( + "io/fs" "os" "syscall" ) @@ -17,7 +18,7 @@ import ( // Although the root user on most Unix systems can write to files even without // permission, hasWritePerm reports false if no appropriate permission bit is // set even if the current user is root. -func hasWritePerm(path string, fi os.FileInfo) bool { +func hasWritePerm(path string, fi fs.FileInfo) bool { if os.Getuid() == 0 { // The root user can access any file, but we still want to default to // read-only mode if the go.mod file is marked as globally non-writable. diff --git a/src/cmd/go/internal/modload/stat_windows.go b/src/cmd/go/internal/modload/stat_windows.go index d7826cfc6b8..0ac23913475 100644 --- a/src/cmd/go/internal/modload/stat_windows.go +++ b/src/cmd/go/internal/modload/stat_windows.go @@ -6,13 +6,11 @@ package modload -import ( - "os" -) +import "io/fs" // hasWritePerm reports whether the current user has permission to write to the // file with the given info. -func hasWritePerm(_ string, fi os.FileInfo) bool { +func hasWritePerm(_ string, fi fs.FileInfo) bool { // Windows has a read-only attribute independent of ACLs, so use that to // determine whether the file is intended to be overwritten. // diff --git a/src/cmd/go/internal/modload/vendor.go b/src/cmd/go/internal/modload/vendor.go index 9f34b829fc2..ab29d4d0144 100644 --- a/src/cmd/go/internal/modload/vendor.go +++ b/src/cmd/go/internal/modload/vendor.go @@ -7,8 +7,8 @@ package modload import ( "errors" "fmt" + "io/fs" "io/ioutil" - "os" "path/filepath" "strings" "sync" @@ -42,7 +42,7 @@ func readVendorList() { vendorMeta = make(map[module.Version]vendorMetadata) data, err := ioutil.ReadFile(filepath.Join(ModRoot(), "vendor/modules.txt")) if err != nil { - if !errors.Is(err, os.ErrNotExist) { + if !errors.Is(err, fs.ErrNotExist) { base.Fatalf("go: %s", err) } return diff --git a/src/cmd/go/internal/renameio/renameio.go b/src/cmd/go/internal/renameio/renameio.go index d573cc690d2..60a7138a760 100644 --- a/src/cmd/go/internal/renameio/renameio.go +++ b/src/cmd/go/internal/renameio/renameio.go @@ -8,6 +8,7 @@ package renameio import ( "bytes" "io" + "io/fs" "math/rand" "os" "path/filepath" @@ -29,13 +30,13 @@ func Pattern(filename string) string { // final name. // // That ensures that the final location, if it exists, is always a complete file. -func WriteFile(filename string, data []byte, perm os.FileMode) (err error) { +func WriteFile(filename string, data []byte, perm fs.FileMode) (err error) { return WriteToFile(filename, bytes.NewReader(data), perm) } // WriteToFile is a variant of WriteFile that accepts the data as an io.Reader // instead of a slice. -func WriteToFile(filename string, data io.Reader, perm os.FileMode) (err error) { +func WriteToFile(filename string, data io.Reader, perm fs.FileMode) (err error) { f, err := tempFile(filepath.Dir(filename), filepath.Base(filename), perm) if err != nil { return err @@ -80,7 +81,7 @@ func ReadFile(filename string) ([]byte, error) { } // tempFile creates a new temporary file with given permission bits. -func tempFile(dir, prefix string, perm os.FileMode) (f *os.File, err error) { +func tempFile(dir, prefix string, perm fs.FileMode) (f *os.File, err error) { for i := 0; i < 10000; i++ { name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+patternSuffix) f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) diff --git a/src/cmd/go/internal/renameio/umask_test.go b/src/cmd/go/internal/renameio/umask_test.go index d75d67c9a93..19e217c548d 100644 --- a/src/cmd/go/internal/renameio/umask_test.go +++ b/src/cmd/go/internal/renameio/umask_test.go @@ -7,6 +7,7 @@ package renameio import ( + "io/fs" "io/ioutil" "os" "path/filepath" @@ -36,7 +37,7 @@ func TestWriteFileModeAppliesUmask(t *testing.T) { t.Fatalf("Stat %q (looking for mode %#o): %s", file, mode, err) } - if fi.Mode()&os.ModePerm != 0640 { - t.Errorf("Stat %q: mode %#o want %#o", file, fi.Mode()&os.ModePerm, 0640) + if fi.Mode()&fs.ModePerm != 0640 { + t.Errorf("Stat %q: mode %#o want %#o", file, fi.Mode()&fs.ModePerm, 0640) } } diff --git a/src/cmd/go/internal/search/search.go b/src/cmd/go/internal/search/search.go index b1d2a9376b2..e4784e94783 100644 --- a/src/cmd/go/internal/search/search.go +++ b/src/cmd/go/internal/search/search.go @@ -10,6 +10,7 @@ import ( "cmd/go/internal/fsys" "fmt" "go/build" + "io/fs" "os" "path" "path/filepath" @@ -128,7 +129,7 @@ func (m *Match) MatchPackages() { if m.pattern == "cmd" { root += "cmd" + string(filepath.Separator) } - err := fsys.Walk(root, func(path string, fi os.FileInfo, err error) error { + err := fsys.Walk(root, func(path string, fi fs.FileInfo, err error) error { if err != nil { return err // Likely a permission error, which could interfere with matching. } @@ -154,7 +155,7 @@ func (m *Match) MatchPackages() { } if !fi.IsDir() { - if fi.Mode()&os.ModeSymlink != 0 && want { + if fi.Mode()&fs.ModeSymlink != 0 && want { if target, err := os.Stat(path); err == nil && target.IsDir() { fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) } @@ -264,7 +265,7 @@ func (m *Match) MatchDirs() { } } - err := fsys.Walk(dir, func(path string, fi os.FileInfo, err error) error { + err := fsys.Walk(dir, func(path string, fi fs.FileInfo, err error) error { if err != nil { return err // Likely a permission error, which could interfere with matching. } diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 51d333d8669..00da9770dfe 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -12,6 +12,7 @@ import ( "fmt" "go/build" "io" + "io/fs" "io/ioutil" "os" "os/exec" @@ -1598,7 +1599,7 @@ func hashStat(name string) cache.ActionID { return h.Sum() } -func hashWriteStat(h io.Writer, info os.FileInfo) { +func hashWriteStat(h io.Writer, info fs.FileInfo) { fmt.Fprintf(h, "stat %d %x %v %v\n", info.Size(), uint64(info.Mode()), info.ModTime(), info.IsDir()) } diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 90bf10244d6..7812afd4888 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -10,6 +10,7 @@ import ( "fmt" "internal/lazyregexp" "internal/singleflight" + "io/fs" "log" urlpkg "net/url" "os" @@ -404,9 +405,9 @@ func (v *Cmd) run1(dir string, cmdline string, keyval []string, verbose bool) ([ if len(args) >= 2 && args[0] == "-go-internal-mkdir" { var err error if filepath.IsAbs(args[1]) { - err = os.Mkdir(args[1], os.ModePerm) + err = os.Mkdir(args[1], fs.ModePerm) } else { - err = os.Mkdir(filepath.Join(dir, args[1]), os.ModePerm) + err = os.Mkdir(filepath.Join(dir, args[1]), fs.ModePerm) } if err != nil { return nil, err diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go index 5aa0f8e7ed8..44ac24c62d4 100644 --- a/src/cmd/go/internal/version/version.go +++ b/src/cmd/go/internal/version/version.go @@ -10,6 +10,7 @@ import ( "context" "encoding/binary" "fmt" + "io/fs" "os" "path/filepath" "runtime" @@ -87,8 +88,8 @@ func runVersion(ctx context.Context, cmd *base.Command, args []string) { // scanDir scans a directory for executables to run scanFile on. func scanDir(dir string) { - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if info.Mode().IsRegular() || info.Mode()&os.ModeSymlink != 0 { + filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { + if info.Mode().IsRegular() || info.Mode()&fs.ModeSymlink != 0 { scanFile(path, info, *versionV) } return nil @@ -96,7 +97,7 @@ func scanDir(dir string) { } // isExe reports whether the file should be considered executable. -func isExe(file string, info os.FileInfo) bool { +func isExe(file string, info fs.FileInfo) bool { if runtime.GOOS == "windows" { return strings.HasSuffix(strings.ToLower(file), ".exe") } @@ -107,8 +108,8 @@ func isExe(file string, info os.FileInfo) bool { // If mustPrint is true, scanFile will report any error reading file. // Otherwise (mustPrint is false, because scanFile is being called // by scanDir) scanFile prints nothing for non-Go executables. -func scanFile(file string, info os.FileInfo, mustPrint bool) { - if info.Mode()&os.ModeSymlink != 0 { +func scanFile(file string, info fs.FileInfo, mustPrint bool) { + if info.Mode()&fs.ModeSymlink != 0 { // Accept file symlinks only. i, err := os.Stat(file) if err != nil || !i.Mode().IsRegular() { diff --git a/src/cmd/go/internal/web/api.go b/src/cmd/go/internal/web/api.go index 570818843ba..f7d3ed60f69 100644 --- a/src/cmd/go/internal/web/api.go +++ b/src/cmd/go/internal/web/api.go @@ -13,9 +13,9 @@ import ( "bytes" "fmt" "io" + "io/fs" "io/ioutil" "net/url" - "os" "strings" "unicode" "unicode/utf8" @@ -56,7 +56,7 @@ func (e *HTTPError) Error() string { } if err := e.Err; err != nil { - if pErr, ok := e.Err.(*os.PathError); ok && strings.HasSuffix(e.URL, pErr.Path) { + if pErr, ok := e.Err.(*fs.PathError); ok && strings.HasSuffix(e.URL, pErr.Path) { // Remove the redundant copy of the path. err = pErr.Err } @@ -67,7 +67,7 @@ func (e *HTTPError) Error() string { } func (e *HTTPError) Is(target error) bool { - return target == os.ErrNotExist && (e.StatusCode == 404 || e.StatusCode == 410) + return target == fs.ErrNotExist && (e.StatusCode == 404 || e.StatusCode == 410) } func (e *HTTPError) Unwrap() error { diff --git a/src/cmd/go/internal/web/file_test.go b/src/cmd/go/internal/web/file_test.go index 63394690453..a1bb080e074 100644 --- a/src/cmd/go/internal/web/file_test.go +++ b/src/cmd/go/internal/web/file_test.go @@ -6,6 +6,7 @@ package web import ( "errors" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -54,7 +55,7 @@ func TestGetNonexistentFile(t *testing.T) { } b, err := GetBytes(u) - if !errors.Is(err, os.ErrNotExist) { - t.Fatalf("GetBytes(%v) = %q, %v; want _, os.ErrNotExist", u, b, err) + if !errors.Is(err, fs.ErrNotExist) { + t.Fatalf("GetBytes(%v) = %q, %v; want _, fs.ErrNotExist", u, b, err) } } diff --git a/src/cmd/go/internal/work/build_test.go b/src/cmd/go/internal/work/build_test.go index 904aee0684c..e941729734f 100644 --- a/src/cmd/go/internal/work/build_test.go +++ b/src/cmd/go/internal/work/build_test.go @@ -7,6 +7,7 @@ package work import ( "bytes" "fmt" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -253,7 +254,7 @@ func TestRespectSetgidDir(t *testing.T) { } // Change setgiddir's permissions to include the SetGID bit. - if err := os.Chmod(setgiddir, 0755|os.ModeSetgid); err != nil { + if err := os.Chmod(setgiddir, 0755|fs.ModeSetgid); err != nil { t.Fatal(err) } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 824a4b5a0a1..717b0cc3afe 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -14,6 +14,7 @@ import ( "fmt" "internal/lazyregexp" "io" + "io/fs" "io/ioutil" "log" "math/rand" @@ -1560,7 +1561,7 @@ func BuildInstallFunc(b *Builder, ctx context.Context, a *Action) (err error) { return err } - perm := os.FileMode(0666) + perm := fs.FileMode(0666) if a1.Mode == "link" { switch cfg.BuildBuildmode { case "c-archive", "c-shared", "plugin": @@ -1609,7 +1610,7 @@ func (b *Builder) cleanup(a *Action) { } // moveOrCopyFile is like 'mv src dst' or 'cp src dst'. -func (b *Builder) moveOrCopyFile(dst, src string, perm os.FileMode, force bool) error { +func (b *Builder) moveOrCopyFile(dst, src string, perm fs.FileMode, force bool) error { if cfg.BuildN { b.Showcmd("", "mv %s %s", src, dst) return nil @@ -1635,7 +1636,7 @@ func (b *Builder) moveOrCopyFile(dst, src string, perm os.FileMode, force bool) // we have to copy the file to retain the correct permissions. // https://golang.org/issue/18878 if fi, err := os.Stat(filepath.Dir(dst)); err == nil { - if fi.IsDir() && (fi.Mode()&os.ModeSetgid) != 0 { + if fi.IsDir() && (fi.Mode()&fs.ModeSetgid) != 0 { return b.copyFile(dst, src, perm, force) } } @@ -1670,7 +1671,7 @@ func (b *Builder) moveOrCopyFile(dst, src string, perm os.FileMode, force bool) } // copyFile is like 'cp src dst'. -func (b *Builder) copyFile(dst, src string, perm os.FileMode, force bool) error { +func (b *Builder) copyFile(dst, src string, perm fs.FileMode, force bool) error { if cfg.BuildN || cfg.BuildX { b.Showcmd("", "cp %s %s", src, dst) if cfg.BuildN { diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go index 42972f5b2a1..8b0dbb74b2b 100644 --- a/src/cmd/go/proxy_test.go +++ b/src/cmd/go/proxy_test.go @@ -12,6 +12,7 @@ import ( "flag" "fmt" "io" + "io/fs" "io/ioutil" "log" "net" @@ -335,7 +336,7 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) { if testing.Verbose() { fmt.Fprintf(os.Stderr, "go proxy: no archive %s %s: %v\n", path, vers, err) } - if errors.Is(err, os.ErrNotExist) { + if errors.Is(err, fs.ErrNotExist) { http.NotFound(w, r) } else { http.Error(w, "cannot load archive", 500) @@ -443,7 +444,7 @@ func readArchive(path, vers string) (*txtar.Archive, error) { return a }).(*txtar.Archive) if a == nil { - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } return a, nil } diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index 986646252a1..a31561cd869 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -14,6 +14,7 @@ import ( "fmt" "go/build" "internal/testenv" + "io/fs" "io/ioutil" "os" "os/exec" @@ -500,7 +501,7 @@ func (ts *testScript) cmdChmod(want simpleStatus, args []string) { ts.fatalf("usage: chmod perm paths...") } perm, err := strconv.ParseUint(args[0], 0, 32) - if err != nil || perm&uint64(os.ModePerm) != perm { + if err != nil || perm&uint64(fs.ModePerm) != perm { ts.fatalf("invalid mode: %s", args[0]) } for _, arg := range args[1:] { @@ -508,7 +509,7 @@ func (ts *testScript) cmdChmod(want simpleStatus, args []string) { if !filepath.IsAbs(path) { path = filepath.Join(ts.cd, arg) } - err := os.Chmod(path, os.FileMode(perm)) + err := os.Chmod(path, fs.FileMode(perm)) ts.check(err) } } @@ -595,7 +596,7 @@ func (ts *testScript) cmdCp(want simpleStatus, args []string) { var ( src string data []byte - mode os.FileMode + mode fs.FileMode ) switch arg { case "stdout": diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go index d9c3aab9c49..d1b6467c5d1 100644 --- a/src/cmd/go/testdata/addmod.go +++ b/src/cmd/go/testdata/addmod.go @@ -22,6 +22,7 @@ import ( "bytes" "flag" "fmt" + "io/fs" "io/ioutil" "log" "os" @@ -121,7 +122,7 @@ func main() { {Name: ".info", Data: info}, } dir = filepath.Clean(dir) - err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { if !info.Mode().IsRegular() { return nil } diff --git a/src/cmd/go/testdata/savedir.go b/src/cmd/go/testdata/savedir.go index 48a63188607..04902df61ef 100644 --- a/src/cmd/go/testdata/savedir.go +++ b/src/cmd/go/testdata/savedir.go @@ -17,6 +17,7 @@ package main import ( "flag" "fmt" + "io/fs" "io/ioutil" "log" "os" @@ -48,7 +49,7 @@ func main() { a := new(txtar.Archive) dir = filepath.Clean(dir) - filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { if path == dir { return nil } diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index 8c56af75596..48b6ad6f539 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -14,6 +14,7 @@ import ( "go/scanner" "go/token" "io" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -73,7 +74,7 @@ func initParserMode() { } } -func isGoFile(f os.FileInfo) bool { +func isGoFile(f fs.FileInfo) bool { // ignore non-Go files name := f.Name() return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") @@ -81,7 +82,7 @@ func isGoFile(f os.FileInfo) bool { // If in == nil, the source is the contents of the file with the given filename. func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error { - var perm os.FileMode = 0644 + var perm fs.FileMode = 0644 if in == nil { f, err := os.Open(filename) if err != nil { @@ -163,7 +164,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error return err } -func visitFile(path string, f os.FileInfo, err error) error { +func visitFile(path string, f fs.FileInfo, err error) error { if err == nil && isGoFile(f) { err = processFile(path, nil, os.Stdout, false) } @@ -275,7 +276,7 @@ const chmodSupported = runtime.GOOS != "windows" // backupFile writes data to a new file named filename with permissions perm, // with 0 && name[0] != '.' && // ignore .files @@ -86,7 +86,7 @@ func test(t *testing.T, mode Mode) { if err != nil { t.Fatal(err) } - filter = func(fi os.FileInfo) bool { + filter = func(fi fs.FileInfo) bool { return isGoFile(fi) && rx.MatchString(fi.Name()) } } diff --git a/src/go/doc/headscan.go b/src/go/doc/headscan.go index 3f782cc1b4b..8ea462366e0 100644 --- a/src/go/doc/headscan.go +++ b/src/go/doc/headscan.go @@ -23,6 +23,7 @@ import ( "go/parser" "go/token" "internal/lazyregexp" + "io/fs" "os" "path/filepath" "runtime" @@ -39,7 +40,7 @@ var html_h = lazyregexp.New(`

`) const html_endh = "

\n" -func isGoFile(fi os.FileInfo) bool { +func isGoFile(fi fs.FileInfo) bool { return strings.HasSuffix(fi.Name(), ".go") && !strings.HasSuffix(fi.Name(), "_test.go") } @@ -68,7 +69,7 @@ func main() { flag.Parse() fset := token.NewFileSet() nheadings := 0 - err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error { + err := filepath.Walk(*root, func(path string, fi fs.FileInfo, err error) error { if !fi.IsDir() { return nil } diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index 54f9d7b80ac..b2d834fdecf 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -12,8 +12,8 @@ import ( "go/ast" "go/token" "io" + "io/fs" "io/ioutil" - "os" "path/filepath" "strings" ) @@ -123,7 +123,7 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) // directory specified by path and returns a map of package name -> package // AST with all the packages found. // -// If filter != nil, only the files with os.FileInfo entries passing through +// If filter != nil, only the files with fs.FileInfo entries passing through // the filter (and ending in ".go") are considered. The mode bits are passed // to ParseFile unchanged. Position information is recorded in fset, which // must not be nil. @@ -132,7 +132,7 @@ func ParseFile(fset *token.FileSet, filename string, src interface{}, mode Mode) // returned. If a parse error occurred, a non-nil but incomplete map and the // first error encountered are returned. // -func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) { +func ParseDir(fset *token.FileSet, path string, filter func(fs.FileInfo) bool, mode Mode) (pkgs map[string]*ast.Package, first error) { list, err := ioutil.ReadDir(path) if err != nil { return nil, err diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go index 25a374eeefc..7193a329fe9 100644 --- a/src/go/parser/parser_test.go +++ b/src/go/parser/parser_test.go @@ -9,7 +9,7 @@ import ( "fmt" "go/ast" "go/token" - "os" + "io/fs" "strings" "testing" ) @@ -40,7 +40,7 @@ func nameFilter(filename string) bool { return false } -func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) } +func dirFilter(f fs.FileInfo) bool { return nameFilter(f.Name()) } func TestParseFile(t *testing.T) { src := "package p\nvar _=s[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]+\ns[::]" diff --git a/src/index/suffixarray/suffixarray_test.go b/src/index/suffixarray/suffixarray_test.go index 28090de9aa2..b6a81123b74 100644 --- a/src/index/suffixarray/suffixarray_test.go +++ b/src/index/suffixarray/suffixarray_test.go @@ -7,9 +7,9 @@ package suffixarray import ( "bytes" "fmt" + "io/fs" "io/ioutil" "math/rand" - "os" "path/filepath" "regexp" "sort" @@ -503,7 +503,7 @@ func makeText(name string) ([]byte, error) { return nil, err } case "go": - err := filepath.Walk("../..", func(path string, info os.FileInfo, err error) error { + err := filepath.Walk("../..", func(path string, info fs.FileInfo, err error) error { if err == nil && strings.HasSuffix(path, ".go") && !info.IsDir() { file, err := ioutil.ReadFile(path) if err != nil { diff --git a/src/internal/poll/error_test.go b/src/internal/poll/error_test.go index 06b96f635a5..abc8b1684f5 100644 --- a/src/internal/poll/error_test.go +++ b/src/internal/poll/error_test.go @@ -6,6 +6,7 @@ package poll_test import ( "fmt" + "io/fs" "net" "os" "testing" @@ -37,7 +38,7 @@ func parseReadError(nestedErr error, verify func(error) (string, bool)) error { if nerr, ok := err.(*net.OpError); ok { err = nerr.Err } - if nerr, ok := err.(*os.PathError); ok { + if nerr, ok := err.(*fs.PathError); ok { err = nerr.Err } if nerr, ok := err.(*os.SyscallError); ok { diff --git a/src/internal/reflectlite/reflect_mirror_test.go b/src/internal/reflectlite/reflect_mirror_test.go index fbb6fb397ef..9b28b13550e 100644 --- a/src/internal/reflectlite/reflect_mirror_test.go +++ b/src/internal/reflectlite/reflect_mirror_test.go @@ -9,6 +9,7 @@ import ( "go/ast" "go/parser" "go/token" + "io/fs" "os" "path/filepath" "runtime" @@ -71,7 +72,7 @@ func (v visitor) Visit(n ast.Node) ast.Visitor { func loadTypes(path, pkgName string, v visitor) { fset := token.NewFileSet() - filter := func(fi os.FileInfo) bool { + filter := func(fi fs.FileInfo) bool { return strings.HasSuffix(fi.Name(), ".go") } pkgs, err := parser.ParseDir(fset, path, filter, 0) diff --git a/src/io/ioutil/ioutil.go b/src/io/ioutil/ioutil.go index acc6ec3a40a..cae41f00183 100644 --- a/src/io/ioutil/ioutil.go +++ b/src/io/ioutil/ioutil.go @@ -8,6 +8,7 @@ package ioutil import ( "bytes" "io" + "io/fs" "os" "sort" "sync" @@ -76,7 +77,7 @@ func ReadFile(filename string) ([]byte, error) { // WriteFile writes data to a file named by filename. // If the file does not exist, WriteFile creates it with permissions perm // (before umask); otherwise WriteFile truncates it before writing, without changing permissions. -func WriteFile(filename string, data []byte, perm os.FileMode) error { +func WriteFile(filename string, data []byte, perm fs.FileMode) error { f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) if err != nil { return err @@ -90,7 +91,7 @@ func WriteFile(filename string, data []byte, perm os.FileMode) error { // ReadDir reads the directory named by dirname and returns // a list of directory entries sorted by filename. -func ReadDir(dirname string) ([]os.FileInfo, error) { +func ReadDir(dirname string) ([]fs.FileInfo, error) { f, err := os.Open(dirname) if err != nil { return nil, err diff --git a/src/io/ioutil/tempfile_test.go b/src/io/ioutil/tempfile_test.go index fcc5101fcc8..440c7cffc67 100644 --- a/src/io/ioutil/tempfile_test.go +++ b/src/io/ioutil/tempfile_test.go @@ -5,6 +5,7 @@ package ioutil_test import ( + "io/fs" . "io/ioutil" "os" "path/filepath" @@ -151,7 +152,7 @@ func TestTempDir_BadDir(t *testing.T) { badDir := filepath.Join(dir, "not-exist") _, err = TempDir(badDir, "foo") - if pe, ok := err.(*os.PathError); !ok || !os.IsNotExist(err) || pe.Path != badDir { + if pe, ok := err.(*fs.PathError); !ok || !os.IsNotExist(err) || pe.Path != badDir { t.Errorf("TempDir error = %#v; want PathError for path %q satisifying os.IsNotExist", err, badDir) } } diff --git a/src/net/conf_test.go b/src/net/conf_test.go index 3c7403eccc2..4c21d56ba0a 100644 --- a/src/net/conf_test.go +++ b/src/net/conf_test.go @@ -7,7 +7,7 @@ package net import ( - "os" + "io/fs" "strings" "testing" ) @@ -26,7 +26,7 @@ var defaultResolvConf = &dnsConfig{ ndots: 1, timeout: 5, attempts: 2, - err: os.ErrNotExist, + err: fs.ErrNotExist, } func TestConfHostLookupOrder(t *testing.T) { @@ -106,7 +106,7 @@ func TestConfHostLookupOrder(t *testing.T) { name: "solaris_no_nsswitch", c: &conf{ goos: "solaris", - nss: &nssConf{err: os.ErrNotExist}, + nss: &nssConf{err: fs.ErrNotExist}, resolv: defaultResolvConf, }, hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, @@ -176,7 +176,7 @@ func TestConfHostLookupOrder(t *testing.T) { name: "linux_no_nsswitch.conf", c: &conf{ goos: "linux", - nss: &nssConf{err: os.ErrNotExist}, + nss: &nssConf{err: fs.ErrNotExist}, resolv: defaultResolvConf, }, hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}}, diff --git a/src/net/dnsconfig_unix_test.go b/src/net/dnsconfig_unix_test.go index 42880123c52..0d7897a813c 100644 --- a/src/net/dnsconfig_unix_test.go +++ b/src/net/dnsconfig_unix_test.go @@ -8,6 +8,7 @@ package net import ( "errors" + "io/fs" "os" "reflect" "strings" @@ -183,7 +184,7 @@ func TestDNSReadMissingFile(t *testing.T) { conf := dnsReadConfig("a-nonexistent-file") if !os.IsNotExist(conf.err) { - t.Errorf("missing resolv.conf:\ngot: %v\nwant: %v", conf.err, os.ErrNotExist) + t.Errorf("missing resolv.conf:\ngot: %v\nwant: %v", conf.err, fs.ErrNotExist) } conf.err = nil want := &dnsConfig{ diff --git a/src/net/error_test.go b/src/net/error_test.go index 62dfb9c15d3..7823fdf9d82 100644 --- a/src/net/error_test.go +++ b/src/net/error_test.go @@ -12,6 +12,7 @@ import ( "fmt" "internal/poll" "io" + "io/fs" "io/ioutil" "net/internal/socktest" "os" @@ -97,7 +98,7 @@ second: case *os.SyscallError: nestedErr = err.Err goto third - case *os.PathError: // for Plan 9 + case *fs.PathError: // for Plan 9 nestedErr = err.Err goto third } @@ -531,7 +532,7 @@ second: case *os.SyscallError: nestedErr = err.Err goto third - case *os.PathError: // for Plan 9 + case *fs.PathError: // for Plan 9 nestedErr = err.Err goto third } @@ -546,7 +547,7 @@ third: return nil } switch nestedErr { - case os.ErrClosed: // for Plan 9 + case fs.ErrClosed: // for Plan 9 return nil } return fmt.Errorf("unexpected type on 3rd nested level: %T", nestedErr) @@ -627,7 +628,7 @@ second: case *os.SyscallError: nestedErr = err.Err goto third - case *os.PathError: // for Plan 9 + case *fs.PathError: // for Plan 9 nestedErr = err.Err goto third } @@ -706,7 +707,7 @@ second: case *os.LinkError: nestedErr = err.Err goto third - case *os.PathError: + case *fs.PathError: nestedErr = err.Err goto third } @@ -799,7 +800,7 @@ func parseLookupPortError(nestedErr error) error { switch nestedErr.(type) { case *AddrError, *DNSError: return nil - case *os.PathError: // for Plan 9 + case *fs.PathError: // for Plan 9 return nil } return fmt.Errorf("unexpected type on 1st nested level: %T", nestedErr) diff --git a/src/net/http/example_filesystem_test.go b/src/net/http/example_filesystem_test.go index e1fd42d0494..0e81458a071 100644 --- a/src/net/http/example_filesystem_test.go +++ b/src/net/http/example_filesystem_test.go @@ -5,9 +5,9 @@ package http_test import ( + "io/fs" "log" "net/http" - "os" "strings" ) @@ -33,7 +33,7 @@ type dotFileHidingFile struct { // Readdir is a wrapper around the Readdir method of the embedded File // that filters out all files that start with a period in their name. -func (f dotFileHidingFile) Readdir(n int) (fis []os.FileInfo, err error) { +func (f dotFileHidingFile) Readdir(n int) (fis []fs.FileInfo, err error) { files, err := f.File.Readdir(n) for _, file := range files { // Filters out the dot files if !strings.HasPrefix(file.Name(), ".") { @@ -52,12 +52,12 @@ type dotFileHidingFileSystem struct { // Open is a wrapper around the Open method of the embedded FileSystem // that serves a 403 permission error when name has a file or directory // with whose name starts with a period in its path. -func (fs dotFileHidingFileSystem) Open(name string) (http.File, error) { +func (fsys dotFileHidingFileSystem) Open(name string) (http.File, error) { if containsDotFile(name) { // If dot file, return 403 response - return nil, os.ErrPermission + return nil, fs.ErrPermission } - file, err := fs.FileSystem.Open(name) + file, err := fsys.FileSystem.Open(name) if err != nil { return nil, err } @@ -65,7 +65,7 @@ func (fs dotFileHidingFileSystem) Open(name string) (http.File, error) { } func ExampleFileServer_dotFileHiding() { - fs := dotFileHidingFileSystem{http.Dir(".")} - http.Handle("/", http.FileServer(fs)) + fsys := dotFileHidingFileSystem{http.Dir(".")} + http.Handle("/", http.FileServer(fsys)) log.Fatal(http.ListenAndServe(":8080", nil)) } diff --git a/src/net/http/fs.go b/src/net/http/fs.go index d718fffba06..0743b5b621c 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "io" + "io/fs" "mime" "mime/multipart" "net/textproto" @@ -43,7 +44,7 @@ type Dir string // mapDirOpenError maps the provided non-nil error from opening name // to a possibly better non-nil error. In particular, it turns OS-specific errors -// about opening files in non-directories into os.ErrNotExist. See Issue 18984. +// about opening files in non-directories into fs.ErrNotExist. See Issue 18984. func mapDirOpenError(originalErr error, name string) error { if os.IsNotExist(originalErr) || os.IsPermission(originalErr) { return originalErr @@ -59,7 +60,7 @@ func mapDirOpenError(originalErr error, name string) error { return originalErr } if !fi.IsDir() { - return os.ErrNotExist + return fs.ErrNotExist } } return originalErr @@ -98,8 +99,8 @@ type File interface { io.Closer io.Reader io.Seeker - Readdir(count int) ([]os.FileInfo, error) - Stat() (os.FileInfo, error) + Readdir(count int) ([]fs.FileInfo, error) + Stat() (fs.FileInfo, error) } func dirList(w ResponseWriter, r *Request, f File) { diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go index 4ac73b728fb..de793b331e6 100644 --- a/src/net/http/fs_test.go +++ b/src/net/http/fs_test.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "io" + "io/fs" "io/ioutil" "mime" "mime/multipart" @@ -629,9 +630,9 @@ func (f *fakeFileInfo) Sys() interface{} { return nil } func (f *fakeFileInfo) ModTime() time.Time { return f.modtime } func (f *fakeFileInfo) IsDir() bool { return f.dir } func (f *fakeFileInfo) Size() int64 { return int64(len(f.contents)) } -func (f *fakeFileInfo) Mode() os.FileMode { +func (f *fakeFileInfo) Mode() fs.FileMode { if f.dir { - return 0755 | os.ModeDir + return 0755 | fs.ModeDir } return 0644 } @@ -644,12 +645,12 @@ type fakeFile struct { } func (f *fakeFile) Close() error { return nil } -func (f *fakeFile) Stat() (os.FileInfo, error) { return f.fi, nil } -func (f *fakeFile) Readdir(count int) ([]os.FileInfo, error) { +func (f *fakeFile) Stat() (fs.FileInfo, error) { return f.fi, nil } +func (f *fakeFile) Readdir(count int) ([]fs.FileInfo, error) { if !f.fi.dir { - return nil, os.ErrInvalid + return nil, fs.ErrInvalid } - var fis []os.FileInfo + var fis []fs.FileInfo limit := f.entpos + count if count <= 0 || limit > len(f.fi.ents) { @@ -668,11 +669,11 @@ func (f *fakeFile) Readdir(count int) ([]os.FileInfo, error) { type fakeFS map[string]*fakeFileInfo -func (fs fakeFS) Open(name string) (File, error) { +func (fsys fakeFS) Open(name string) (File, error) { name = path.Clean(name) - f, ok := fs[name] + f, ok := fsys[name] if !ok { - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } if f.err != nil { return nil, f.err @@ -747,7 +748,7 @@ func TestDirectoryIfNotModified(t *testing.T) { res.Body.Close() } -func mustStat(t *testing.T, fileName string) os.FileInfo { +func mustStat(t *testing.T, fileName string) fs.FileInfo { fi, err := os.Stat(fileName) if err != nil { t.Fatal(err) @@ -1081,7 +1082,7 @@ func (issue12991FS) Open(string) (File, error) { return issue12991File{}, nil } type issue12991File struct{ File } -func (issue12991File) Stat() (os.FileInfo, error) { return nil, os.ErrPermission } +func (issue12991File) Stat() (fs.FileInfo, error) { return nil, fs.ErrPermission } func (issue12991File) Close() error { return nil } func TestServeContentErrorMessages(t *testing.T) { @@ -1091,7 +1092,7 @@ func TestServeContentErrorMessages(t *testing.T) { err: errors.New("random error"), }, "/403": &fakeFileInfo{ - err: &os.PathError{Err: os.ErrPermission}, + err: &fs.PathError{Err: fs.ErrPermission}, }, } ts := httptest.NewServer(FileServer(fs)) @@ -1289,7 +1290,7 @@ func (d fileServerCleanPathDir) Open(path string) (File, error) { // Just return back something that's a directory. return Dir(".").Open(".") } - return nil, os.ErrNotExist + return nil, fs.ErrNotExist } type panicOnSeek struct{ io.ReadSeeker } diff --git a/src/net/ipsock_plan9.go b/src/net/ipsock_plan9.go index 23082366aac..7a4b7a6041c 100644 --- a/src/net/ipsock_plan9.go +++ b/src/net/ipsock_plan9.go @@ -7,6 +7,7 @@ package net import ( "context" "internal/bytealg" + "io/fs" "os" "syscall" ) @@ -164,7 +165,7 @@ func fixErr(err error) { if nonNilInterface(oe.Addr) { oe.Addr = nil } - if pe, ok := oe.Err.(*os.PathError); ok { + if pe, ok := oe.Err.(*fs.PathError); ok { if _, ok = pe.Err.(syscall.ErrorString); ok { oe.Err = pe.Err } diff --git a/src/os/error_test.go b/src/os/error_test.go index 3d921578fd2..060cf59875a 100644 --- a/src/os/error_test.go +++ b/src/os/error_test.go @@ -7,6 +7,7 @@ package os_test import ( "errors" "fmt" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -27,7 +28,7 @@ func TestErrIsExist(t *testing.T) { t.Fatal("Open should have failed") return } - if s := checkErrorPredicate("os.IsExist", os.IsExist, err, os.ErrExist); s != "" { + if s := checkErrorPredicate("os.IsExist", os.IsExist, err, fs.ErrExist); s != "" { t.Fatal(s) return } @@ -39,7 +40,7 @@ func testErrNotExist(name string) string { f.Close() return "Open should have failed" } - if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err, os.ErrNotExist); s != "" { + if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err, fs.ErrNotExist); s != "" { return s } @@ -47,7 +48,7 @@ func testErrNotExist(name string) string { if err == nil { return "Chdir should have failed" } - if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err, os.ErrNotExist); s != "" { + if s := checkErrorPredicate("os.IsNotExist", os.IsNotExist, err, fs.ErrNotExist); s != "" { return s } return "" @@ -91,18 +92,18 @@ type isExistTest struct { } var isExistTests = []isExistTest{ - {&os.PathError{Err: os.ErrInvalid}, false, false}, - {&os.PathError{Err: os.ErrPermission}, false, false}, - {&os.PathError{Err: os.ErrExist}, true, false}, - {&os.PathError{Err: os.ErrNotExist}, false, true}, - {&os.PathError{Err: os.ErrClosed}, false, false}, - {&os.LinkError{Err: os.ErrInvalid}, false, false}, - {&os.LinkError{Err: os.ErrPermission}, false, false}, - {&os.LinkError{Err: os.ErrExist}, true, false}, - {&os.LinkError{Err: os.ErrNotExist}, false, true}, - {&os.LinkError{Err: os.ErrClosed}, false, false}, - {&os.SyscallError{Err: os.ErrNotExist}, false, true}, - {&os.SyscallError{Err: os.ErrExist}, true, false}, + {&fs.PathError{Err: fs.ErrInvalid}, false, false}, + {&fs.PathError{Err: fs.ErrPermission}, false, false}, + {&fs.PathError{Err: fs.ErrExist}, true, false}, + {&fs.PathError{Err: fs.ErrNotExist}, false, true}, + {&fs.PathError{Err: fs.ErrClosed}, false, false}, + {&os.LinkError{Err: fs.ErrInvalid}, false, false}, + {&os.LinkError{Err: fs.ErrPermission}, false, false}, + {&os.LinkError{Err: fs.ErrExist}, true, false}, + {&os.LinkError{Err: fs.ErrNotExist}, false, true}, + {&os.LinkError{Err: fs.ErrClosed}, false, false}, + {&os.SyscallError{Err: fs.ErrNotExist}, false, true}, + {&os.SyscallError{Err: fs.ErrExist}, true, false}, {nil, false, false}, } @@ -111,14 +112,14 @@ func TestIsExist(t *testing.T) { if is := os.IsExist(tt.err); is != tt.is { t.Errorf("os.IsExist(%T %v) = %v, want %v", tt.err, tt.err, is, tt.is) } - if is := errors.Is(tt.err, os.ErrExist); is != tt.is { - t.Errorf("errors.Is(%T %v, os.ErrExist) = %v, want %v", tt.err, tt.err, is, tt.is) + if is := errors.Is(tt.err, fs.ErrExist); is != tt.is { + t.Errorf("errors.Is(%T %v, fs.ErrExist) = %v, want %v", tt.err, tt.err, is, tt.is) } if isnot := os.IsNotExist(tt.err); isnot != tt.isnot { t.Errorf("os.IsNotExist(%T %v) = %v, want %v", tt.err, tt.err, isnot, tt.isnot) } - if isnot := errors.Is(tt.err, os.ErrNotExist); isnot != tt.isnot { - t.Errorf("errors.Is(%T %v, os.ErrNotExist) = %v, want %v", tt.err, tt.err, isnot, tt.isnot) + if isnot := errors.Is(tt.err, fs.ErrNotExist); isnot != tt.isnot { + t.Errorf("errors.Is(%T %v, fs.ErrNotExist) = %v, want %v", tt.err, tt.err, isnot, tt.isnot) } } } @@ -130,8 +131,8 @@ type isPermissionTest struct { var isPermissionTests = []isPermissionTest{ {nil, false}, - {&os.PathError{Err: os.ErrPermission}, true}, - {&os.SyscallError{Err: os.ErrPermission}, true}, + {&fs.PathError{Err: fs.ErrPermission}, true}, + {&os.SyscallError{Err: fs.ErrPermission}, true}, } func TestIsPermission(t *testing.T) { @@ -139,8 +140,8 @@ func TestIsPermission(t *testing.T) { if got := os.IsPermission(tt.err); got != tt.want { t.Errorf("os.IsPermission(%#v) = %v; want %v", tt.err, got, tt.want) } - if got := errors.Is(tt.err, os.ErrPermission); got != tt.want { - t.Errorf("errors.Is(%#v, os.ErrPermission) = %v; want %v", tt.err, got, tt.want) + if got := errors.Is(tt.err, fs.ErrPermission); got != tt.want { + t.Errorf("errors.Is(%#v, fs.ErrPermission) = %v; want %v", tt.err, got, tt.want) } } } @@ -170,8 +171,8 @@ func TestErrPathNUL(t *testing.T) { } func TestPathErrorUnwrap(t *testing.T) { - pe := &os.PathError{Err: os.ErrInvalid} - if !errors.Is(pe, os.ErrInvalid) { + pe := &fs.PathError{Err: fs.ErrInvalid} + if !errors.Is(pe, fs.ErrInvalid) { t.Error("errors.Is failed, wanted success") } } @@ -181,7 +182,7 @@ type myErrorIs struct{ error } func (e myErrorIs) Is(target error) bool { return target == e.error } func TestErrorIsMethods(t *testing.T) { - if os.IsPermission(myErrorIs{os.ErrPermission}) { - t.Error("os.IsPermission(err) = true when err.Is(os.ErrPermission), wanted false") + if os.IsPermission(myErrorIs{fs.ErrPermission}) { + t.Error("os.IsPermission(err) = true when err.Is(fs.ErrPermission), wanted false") } } diff --git a/src/os/error_unix_test.go b/src/os/error_unix_test.go index bfc83c98673..18bcf3f4e44 100644 --- a/src/os/error_unix_test.go +++ b/src/os/error_unix_test.go @@ -7,14 +7,15 @@ package os_test import ( + "io/fs" "os" "syscall" ) func init() { isExistTests = append(isExistTests, - isExistTest{err: &os.PathError{Err: syscall.EEXIST}, is: true, isnot: false}, - isExistTest{err: &os.PathError{Err: syscall.ENOTEMPTY}, is: true, isnot: false}, + isExistTest{err: &fs.PathError{Err: syscall.EEXIST}, is: true, isnot: false}, + isExistTest{err: &fs.PathError{Err: syscall.ENOTEMPTY}, is: true, isnot: false}, isExistTest{err: &os.LinkError{Err: syscall.EEXIST}, is: true, isnot: false}, isExistTest{err: &os.LinkError{Err: syscall.ENOTEMPTY}, is: true, isnot: false}, @@ -23,9 +24,9 @@ func init() { isExistTest{err: &os.SyscallError{Err: syscall.ENOTEMPTY}, is: true, isnot: false}, ) isPermissionTests = append(isPermissionTests, - isPermissionTest{err: &os.PathError{Err: syscall.EACCES}, want: true}, - isPermissionTest{err: &os.PathError{Err: syscall.EPERM}, want: true}, - isPermissionTest{err: &os.PathError{Err: syscall.EEXIST}, want: false}, + isPermissionTest{err: &fs.PathError{Err: syscall.EACCES}, want: true}, + isPermissionTest{err: &fs.PathError{Err: syscall.EPERM}, want: true}, + isPermissionTest{err: &fs.PathError{Err: syscall.EEXIST}, want: false}, isPermissionTest{err: &os.LinkError{Err: syscall.EACCES}, want: true}, isPermissionTest{err: &os.LinkError{Err: syscall.EPERM}, want: true}, diff --git a/src/os/error_windows_test.go b/src/os/error_windows_test.go index 1635c1088e6..b8191c5ebc8 100644 --- a/src/os/error_windows_test.go +++ b/src/os/error_windows_test.go @@ -7,6 +7,7 @@ package os_test import ( + "io/fs" "os" "syscall" ) @@ -15,24 +16,24 @@ func init() { const _ERROR_BAD_NETPATH = syscall.Errno(53) isExistTests = append(isExistTests, - isExistTest{err: &os.PathError{Err: syscall.ERROR_FILE_NOT_FOUND}, is: false, isnot: true}, + isExistTest{err: &fs.PathError{Err: syscall.ERROR_FILE_NOT_FOUND}, is: false, isnot: true}, isExistTest{err: &os.LinkError{Err: syscall.ERROR_FILE_NOT_FOUND}, is: false, isnot: true}, isExistTest{err: &os.SyscallError{Err: syscall.ERROR_FILE_NOT_FOUND}, is: false, isnot: true}, - isExistTest{err: &os.PathError{Err: _ERROR_BAD_NETPATH}, is: false, isnot: true}, + isExistTest{err: &fs.PathError{Err: _ERROR_BAD_NETPATH}, is: false, isnot: true}, isExistTest{err: &os.LinkError{Err: _ERROR_BAD_NETPATH}, is: false, isnot: true}, isExistTest{err: &os.SyscallError{Err: _ERROR_BAD_NETPATH}, is: false, isnot: true}, - isExistTest{err: &os.PathError{Err: syscall.ERROR_PATH_NOT_FOUND}, is: false, isnot: true}, + isExistTest{err: &fs.PathError{Err: syscall.ERROR_PATH_NOT_FOUND}, is: false, isnot: true}, isExistTest{err: &os.LinkError{Err: syscall.ERROR_PATH_NOT_FOUND}, is: false, isnot: true}, isExistTest{err: &os.SyscallError{Err: syscall.ERROR_PATH_NOT_FOUND}, is: false, isnot: true}, - isExistTest{err: &os.PathError{Err: syscall.ERROR_DIR_NOT_EMPTY}, is: true, isnot: false}, + isExistTest{err: &fs.PathError{Err: syscall.ERROR_DIR_NOT_EMPTY}, is: true, isnot: false}, isExistTest{err: &os.LinkError{Err: syscall.ERROR_DIR_NOT_EMPTY}, is: true, isnot: false}, isExistTest{err: &os.SyscallError{Err: syscall.ERROR_DIR_NOT_EMPTY}, is: true, isnot: false}, ) isPermissionTests = append(isPermissionTests, - isPermissionTest{err: &os.PathError{Err: syscall.ERROR_ACCESS_DENIED}, want: true}, + isPermissionTest{err: &fs.PathError{Err: syscall.ERROR_ACCESS_DENIED}, want: true}, isPermissionTest{err: &os.LinkError{Err: syscall.ERROR_ACCESS_DENIED}, want: true}, isPermissionTest{err: &os.SyscallError{Err: syscall.ERROR_ACCESS_DENIED}, want: true}, ) diff --git a/src/os/example_test.go b/src/os/example_test.go index 822886f70c6..fbb277b6f1a 100644 --- a/src/os/example_test.go +++ b/src/os/example_test.go @@ -6,6 +6,7 @@ package os_test import ( "fmt" + "io/fs" "log" "os" "time" @@ -62,9 +63,9 @@ func ExampleFileMode() { fmt.Println("regular file") case mode.IsDir(): fmt.Println("directory") - case mode&os.ModeSymlink != 0: + case mode&fs.ModeSymlink != 0: fmt.Println("symbolic link") - case mode&os.ModeNamedPipe != 0: + case mode&fs.ModeNamedPipe != 0: fmt.Println("named pipe") } } diff --git a/src/os/exec/exec_plan9.go b/src/os/exec/exec_plan9.go index d90bd043991..21ac7b765f1 100644 --- a/src/os/exec/exec_plan9.go +++ b/src/os/exec/exec_plan9.go @@ -4,14 +4,14 @@ package exec -import "os" +import "io/fs" func init() { skipStdinCopyError = func(err error) bool { // Ignore hungup errors copying to stdin if the program // completed successfully otherwise. // See Issue 35753. - pe, ok := err.(*os.PathError) + pe, ok := err.(*fs.PathError) return ok && pe.Op == "write" && pe.Path == "|1" && pe.Err.Error() == "i/o on hungup channel" diff --git a/src/os/exec/exec_unix.go b/src/os/exec/exec_unix.go index 9c3e17d23ab..51c52427c2b 100644 --- a/src/os/exec/exec_unix.go +++ b/src/os/exec/exec_unix.go @@ -7,7 +7,7 @@ package exec import ( - "os" + "io/fs" "syscall" ) @@ -16,7 +16,7 @@ func init() { // Ignore EPIPE errors copying to stdin if the program // completed successfully otherwise. // See Issue 9173. - pe, ok := err.(*os.PathError) + pe, ok := err.(*fs.PathError) return ok && pe.Op == "write" && pe.Path == "|1" && pe.Err == syscall.EPIPE diff --git a/src/os/exec/exec_windows.go b/src/os/exec/exec_windows.go index af8cd97218e..bb937f8aed7 100644 --- a/src/os/exec/exec_windows.go +++ b/src/os/exec/exec_windows.go @@ -5,7 +5,7 @@ package exec import ( - "os" + "io/fs" "syscall" ) @@ -15,7 +15,7 @@ func init() { // to stdin if the program completed successfully otherwise. // See Issue 20445. const _ERROR_NO_DATA = syscall.Errno(0xe8) - pe, ok := err.(*os.PathError) + pe, ok := err.(*fs.PathError) return ok && pe.Op == "write" && pe.Path == "|1" && (pe.Err == syscall.ERROR_BROKEN_PIPE || pe.Err == _ERROR_NO_DATA) diff --git a/src/os/exec/lp_plan9.go b/src/os/exec/lp_plan9.go index 5860cbca4d3..e8826a5083b 100644 --- a/src/os/exec/lp_plan9.go +++ b/src/os/exec/lp_plan9.go @@ -6,6 +6,7 @@ package exec import ( "errors" + "io/fs" "os" "path/filepath" "strings" @@ -22,7 +23,7 @@ func findExecutable(file string) error { if m := d.Mode(); !m.IsDir() && m&0111 != 0 { return nil } - return os.ErrPermission + return fs.ErrPermission } // LookPath searches for an executable named file in the diff --git a/src/os/exec/lp_unix.go b/src/os/exec/lp_unix.go index 93793e0eee6..66c1df76fb9 100644 --- a/src/os/exec/lp_unix.go +++ b/src/os/exec/lp_unix.go @@ -8,6 +8,7 @@ package exec import ( "errors" + "io/fs" "os" "path/filepath" "strings" @@ -24,7 +25,7 @@ func findExecutable(file string) error { if m := d.Mode(); !m.IsDir() && m&0111 != 0 { return nil } - return os.ErrPermission + return fs.ErrPermission } // LookPath searches for an executable named file in the diff --git a/src/os/exec/lp_windows.go b/src/os/exec/lp_windows.go index 9ea3d765757..e7a2cdf142a 100644 --- a/src/os/exec/lp_windows.go +++ b/src/os/exec/lp_windows.go @@ -6,6 +6,7 @@ package exec import ( "errors" + "io/fs" "os" "path/filepath" "strings" @@ -20,7 +21,7 @@ func chkStat(file string) error { return err } if d.IsDir() { - return os.ErrPermission + return fs.ErrPermission } return nil } @@ -47,7 +48,7 @@ func findExecutable(file string, exts []string) (string, error) { return f, nil } } - return "", os.ErrNotExist + return "", fs.ErrNotExist } // LookPath searches for an executable named file in the diff --git a/src/os/os_test.go b/src/os/os_test.go index c692ba099f9..8f14263401d 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -2526,7 +2526,7 @@ func testDoubleCloseError(t *testing.T, path string) { if err := file.Close(); err == nil { t.Error("second Close did not fail") } else if pe, ok := err.(*PathError); !ok { - t.Errorf("second Close returned unexpected error type %T; expected os.PathError", pe) + t.Errorf("second Close returned unexpected error type %T; expected fs.PathError", pe) } else if pe.Err != ErrClosed { t.Errorf("second Close returned %q, wanted %q", err, ErrClosed) } else { diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go index f03ec750d02..e0027748449 100644 --- a/src/os/os_windows_test.go +++ b/src/os/os_windows_test.go @@ -12,6 +12,7 @@ import ( "internal/syscall/windows/registry" "internal/testenv" "io" + "io/fs" "io/ioutil" "os" osexec "os/exec" @@ -164,11 +165,11 @@ func testDirLinks(t *testing.T, tests []dirLinkTest) { t.Errorf("failed to lstat link %v: %v", link, err) continue } - if m := fi2.Mode(); m&os.ModeSymlink == 0 { + if m := fi2.Mode(); m&fs.ModeSymlink == 0 { t.Errorf("%q should be a link, but is not (mode=0x%x)", link, uint32(m)) continue } - if m := fi2.Mode(); m&os.ModeDir != 0 { + if m := fi2.Mode(); m&fs.ModeDir != 0 { t.Errorf("%q should be a link, not a directory (mode=0x%x)", link, uint32(m)) continue } @@ -681,7 +682,7 @@ func TestStatSymlinkLoop(t *testing.T) { defer os.Remove("x") _, err = os.Stat("x") - if _, ok := err.(*os.PathError); !ok { + if _, ok := err.(*fs.PathError); !ok { t.Errorf("expected *PathError, got %T: %v\n", err, err) } } @@ -1291,9 +1292,9 @@ func TestWindowsReadlink(t *testing.T) { // os.Mkdir(os.DevNull) fails. func TestMkdirDevNull(t *testing.T) { err := os.Mkdir(os.DevNull, 777) - oserr, ok := err.(*os.PathError) + oserr, ok := err.(*fs.PathError) if !ok { - t.Fatalf("error (%T) is not *os.PathError", err) + t.Fatalf("error (%T) is not *fs.PathError", err) } errno, ok := oserr.Err.(syscall.Errno) if !ok { diff --git a/src/os/pipe_test.go b/src/os/pipe_test.go index 429bd813c20..0593efec75b 100644 --- a/src/os/pipe_test.go +++ b/src/os/pipe_test.go @@ -13,6 +13,7 @@ import ( "fmt" "internal/testenv" "io" + "io/fs" "io/ioutil" "os" osexec "os/exec" @@ -46,7 +47,7 @@ func TestEPIPE(t *testing.T) { if err == nil { t.Fatal("unexpected success of Write to broken pipe") } - if pe, ok := err.(*os.PathError); ok { + if pe, ok := err.(*fs.PathError); ok { err = pe.Err } if se, ok := err.(*os.SyscallError); ok { @@ -202,10 +203,10 @@ func testClosedPipeRace(t *testing.T, read bool) { } if err == nil { t.Error("I/O on closed pipe unexpectedly succeeded") - } else if pe, ok := err.(*os.PathError); !ok { - t.Errorf("I/O on closed pipe returned unexpected error type %T; expected os.PathError", pe) - } else if pe.Err != os.ErrClosed { - t.Errorf("got error %q but expected %q", pe.Err, os.ErrClosed) + } else if pe, ok := err.(*fs.PathError); !ok { + t.Errorf("I/O on closed pipe returned unexpected error type %T; expected fs.PathError", pe) + } else if pe.Err != fs.ErrClosed { + t.Errorf("got error %q but expected %q", pe.Err, fs.ErrClosed) } else { t.Logf("I/O returned expected error %q", err) } @@ -233,7 +234,7 @@ func TestReadNonblockingFd(t *testing.T) { defer syscall.SetNonblock(fd, false) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { - if perr, ok := err.(*os.PathError); !ok || perr.Err != syscall.EAGAIN { + if perr, ok := err.(*fs.PathError); !ok || perr.Err != syscall.EAGAIN { t.Fatalf("read on nonblocking stdin got %q, should have gotten EAGAIN", err) } } @@ -308,10 +309,10 @@ func testCloseWithBlockingRead(t *testing.T, r, w *os.File) { if err == nil { t.Error("I/O on closed pipe unexpectedly succeeded") } - if pe, ok := err.(*os.PathError); ok { + if pe, ok := err.(*fs.PathError); ok { err = pe.Err } - if err != io.EOF && err != os.ErrClosed { + if err != io.EOF && err != fs.ErrClosed { t.Errorf("got %v, expected EOF or closed", err) } }(c2) diff --git a/src/os/removeall_test.go b/src/os/removeall_test.go index 1e5c650fe1a..bc9c468ce3e 100644 --- a/src/os/removeall_test.go +++ b/src/os/removeall_test.go @@ -359,7 +359,7 @@ func TestRemoveAllButReadOnlyAndPathError(t *testing.T) { t.Errorf("got %q, expected pathErr.path %q", g, w) } } else { - t.Errorf("got %T, expected *os.PathError", err) + t.Errorf("got %T, expected *fs.PathError", err) } for _, dir := range dirs { diff --git a/src/os/signal/signal_cgo_test.go b/src/os/signal/signal_cgo_test.go index a117221400d..a8a485613f5 100644 --- a/src/os/signal/signal_cgo_test.go +++ b/src/os/signal/signal_cgo_test.go @@ -17,6 +17,7 @@ import ( "context" "fmt" "io" + "io/fs" "os" "os/exec" ptypkg "os/signal/internal/pty" @@ -127,7 +128,7 @@ func TestTerminalSignal(t *testing.T) { if len(line) > 0 || len(handled) > 0 { t.Logf("%q", append(handled, line...)) } - if perr, ok := err.(*os.PathError); ok { + if perr, ok := err.(*fs.PathError); ok { err = perr.Err } // EOF means pty is closed. diff --git a/src/os/stat_test.go b/src/os/stat_test.go index 60f3b4c587d..88b789080ec 100644 --- a/src/os/stat_test.go +++ b/src/os/stat_test.go @@ -6,6 +6,7 @@ package os_test import ( "internal/testenv" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -14,7 +15,7 @@ import ( ) // testStatAndLstat verifies that all os.Stat, os.Lstat os.File.Stat and os.Readdir work. -func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCheck func(*testing.T, string, os.FileInfo)) { +func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCheck func(*testing.T, string, fs.FileInfo)) { // test os.Stat sfi, err := os.Stat(path) if err != nil { @@ -70,7 +71,7 @@ func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCh } } - // test os.FileInfo returned by os.Readdir + // test fs.FileInfo returned by os.Readdir if len(path) > 0 && os.IsPathSeparator(path[len(path)-1]) { // skip os.Readdir test of directories with slash at the end return @@ -88,7 +89,7 @@ func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCh t.Error(err) return } - var lsfi2 os.FileInfo + var lsfi2 fs.FileInfo base := filepath.Base(path) for _, fi2 := range fis { if fi2.Name() == base { @@ -108,34 +109,34 @@ func testStatAndLstat(t *testing.T, path string, isLink bool, statCheck, lstatCh } // testIsDir verifies that fi refers to directory. -func testIsDir(t *testing.T, path string, fi os.FileInfo) { +func testIsDir(t *testing.T, path string, fi fs.FileInfo) { t.Helper() if !fi.IsDir() { t.Errorf("%q should be a directory", path) } - if fi.Mode()&os.ModeSymlink != 0 { + if fi.Mode()&fs.ModeSymlink != 0 { t.Errorf("%q should not be a symlink", path) } } // testIsSymlink verifies that fi refers to symlink. -func testIsSymlink(t *testing.T, path string, fi os.FileInfo) { +func testIsSymlink(t *testing.T, path string, fi fs.FileInfo) { t.Helper() if fi.IsDir() { t.Errorf("%q should not be a directory", path) } - if fi.Mode()&os.ModeSymlink == 0 { + if fi.Mode()&fs.ModeSymlink == 0 { t.Errorf("%q should be a symlink", path) } } // testIsFile verifies that fi refers to file. -func testIsFile(t *testing.T, path string, fi os.FileInfo) { +func testIsFile(t *testing.T, path string, fi fs.FileInfo) { t.Helper() if fi.IsDir() { t.Errorf("%q should not be a directory", path) } - if fi.Mode()&os.ModeSymlink != 0 { + if fi.Mode()&fs.ModeSymlink != 0 { t.Errorf("%q should not be a symlink", path) } } diff --git a/src/path/filepath/example_unix_walk_test.go b/src/path/filepath/example_unix_walk_test.go index fa8b8e393b0..66dc7f6b534 100644 --- a/src/path/filepath/example_unix_walk_test.go +++ b/src/path/filepath/example_unix_walk_test.go @@ -8,6 +8,7 @@ package filepath_test import ( "fmt" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -40,7 +41,7 @@ func ExampleWalk() { subDirToSkip := "skip" fmt.Println("On Unix:") - err = filepath.Walk(".", func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(".", func(path string, info fs.FileInfo, err error) error { if err != nil { fmt.Printf("prevent panic by handling failure accessing a path %q: %v\n", path, err) return err diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go index 26f18331892..dffd27db146 100644 --- a/src/path/filepath/path.go +++ b/src/path/filepath/path.go @@ -13,6 +13,7 @@ package filepath import ( "errors" + "io/fs" "os" "sort" "strings" @@ -339,7 +340,7 @@ var SkipDir = errors.New("skip this directory") // visited by Walk. The path argument contains the argument to Walk as a // prefix; that is, if Walk is called with "dir", which is a directory // containing the file "a", the walk function will be called with argument -// "dir/a". The info argument is the os.FileInfo for the named path. +// "dir/a". The info argument is the fs.FileInfo for the named path. // // If there was a problem walking to the file or directory named by path, the // incoming error will describe the problem and the function can decide how @@ -350,12 +351,12 @@ var SkipDir = errors.New("skip this directory") // Walk skips the directory's contents entirely. If the function returns SkipDir // when invoked on a non-directory file, Walk skips the remaining files in the // containing directory. -type WalkFunc func(path string, info os.FileInfo, err error) error +type WalkFunc func(path string, info fs.FileInfo, err error) error var lstat = os.Lstat // for testing // walk recursively descends path, calling walkFn. -func walk(path string, info os.FileInfo, walkFn WalkFunc) error { +func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { if !info.IsDir() { return walkFn(path, info, nil) } diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index 6a8700e4135..7dc8b60c28c 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "internal/testenv" + "io/fs" "io/ioutil" "os" "path/filepath" @@ -393,7 +394,7 @@ func checkMarks(t *testing.T, report bool) { // Assumes that each node name is unique. Good enough for a test. // If clear is true, any incoming error is cleared before return. The errors // are always accumulated, though. -func mark(info os.FileInfo, err error, errors *[]error, clear bool) error { +func mark(info fs.FileInfo, err error, errors *[]error, clear bool) error { name := info.Name() walkTree(tree, tree.name, func(path string, n *Node) { if n.name == name { @@ -454,7 +455,7 @@ func TestWalk(t *testing.T) { makeTree(t) errors := make([]error, 0, 10) clear := true - markFn := func(path string, info os.FileInfo, err error) error { + markFn := func(path string, info fs.FileInfo, err error) error { return mark(info, err, &errors, clear) } // Expect no errors. @@ -543,7 +544,7 @@ func TestWalkSkipDirOnFile(t *testing.T) { touch(t, filepath.Join(td, "dir/foo2")) sawFoo2 := false - walker := func(path string, info os.FileInfo, err error) error { + walker := func(path string, info fs.FileInfo, err error) error { if strings.HasSuffix(path, "foo2") { sawFoo2 = true } @@ -589,14 +590,14 @@ func TestWalkFileError(t *testing.T) { *filepath.LstatP = os.Lstat }() statErr := errors.New("some stat error") - *filepath.LstatP = func(path string) (os.FileInfo, error) { + *filepath.LstatP = func(path string) (fs.FileInfo, error) { if strings.HasSuffix(path, "stat-error") { return nil, statErr } return os.Lstat(path) } got := map[string]error{} - err = filepath.Walk(td, func(path string, fi os.FileInfo, err error) error { + err = filepath.Walk(td, func(path string, fi fs.FileInfo, err error) error { rel, _ := filepath.Rel(td, path) got[filepath.ToSlash(rel)] = err return nil @@ -1289,7 +1290,7 @@ func TestBug3486(t *testing.T) { // https://golang.org/issue/3486 ken := filepath.Join(root, "ken") seenBugs := false seenKen := false - err = filepath.Walk(root, func(pth string, info os.FileInfo, err error) error { + err = filepath.Walk(root, func(pth string, info fs.FileInfo, err error) error { if err != nil { t.Fatal(err) } @@ -1338,7 +1339,7 @@ func testWalkSymlink(t *testing.T, mklink func(target, link string) error) { } var visited []string - err = filepath.Walk(tmpdir, func(path string, info os.FileInfo, err error) error { + err = filepath.Walk(tmpdir, func(path string, info fs.FileInfo, err error) error { if err != nil { t.Fatal(err) } diff --git a/src/path/filepath/path_windows_test.go b/src/path/filepath/path_windows_test.go index f7c454bf65f..990f18614d7 100644 --- a/src/path/filepath/path_windows_test.go +++ b/src/path/filepath/path_windows_test.go @@ -8,6 +8,7 @@ import ( "flag" "fmt" "internal/testenv" + "io/fs" "io/ioutil" "os" "os/exec" @@ -34,7 +35,7 @@ func testWinSplitListTestIsValid(t *testing.T, ti int, tt SplitListTest, const ( cmdfile = `printdir.cmd` - perm os.FileMode = 0700 + perm fs.FileMode = 0700 ) tmp, err := ioutil.TempDir("", "testWinSplitListTestIsValid") diff --git a/src/path/filepath/symlink.go b/src/path/filepath/symlink.go index 335b315a202..6fefd15977e 100644 --- a/src/path/filepath/symlink.go +++ b/src/path/filepath/symlink.go @@ -6,6 +6,7 @@ package filepath import ( "errors" + "io/fs" "os" "runtime" "syscall" @@ -85,7 +86,7 @@ func walkSymlinks(path string) (string, error) { return "", err } - if fi.Mode()&os.ModeSymlink == 0 { + if fi.Mode()&fs.ModeSymlink == 0 { if !fi.Mode().IsDir() && end < len(path) { return "", syscall.ENOTDIR } diff --git a/src/runtime/testdata/testprogcgo/exec.go b/src/runtime/testdata/testprogcgo/exec.go index 94da5dc526b..15723c73695 100644 --- a/src/runtime/testdata/testprogcgo/exec.go +++ b/src/runtime/testdata/testprogcgo/exec.go @@ -31,6 +31,7 @@ import "C" import ( "fmt" + "io/fs" "os" "os/exec" "os/signal" @@ -98,7 +99,7 @@ func CgoExecSignalMask() { // isEAGAIN reports whether err is an EAGAIN error from a process execution. func isEAGAIN(err error) bool { - if p, ok := err.(*os.PathError); ok { + if p, ok := err.(*fs.PathError); ok { err = p.Err } return err == syscall.EAGAIN diff --git a/src/syscall/syscall_js.go b/src/syscall/syscall_js.go index dfb4a275e30..0ab8c3fba4c 100644 --- a/src/syscall/syscall_js.go +++ b/src/syscall/syscall_js.go @@ -49,7 +49,7 @@ const PathMax = 256 // using errors.Is. For example: // // _, _, err := syscall.Syscall(...) -// if errors.Is(err, os.ErrNotExist) ... +// if errors.Is(err, fs.ErrNotExist) ... type Errno uintptr func (e Errno) Error() string { diff --git a/src/syscall/syscall_linux_test.go b/src/syscall/syscall_linux_test.go index c5008f29132..93a4d236d82 100644 --- a/src/syscall/syscall_linux_test.go +++ b/src/syscall/syscall_linux_test.go @@ -8,6 +8,7 @@ import ( "bufio" "fmt" "io" + "io/fs" "io/ioutil" "os" "os/exec" @@ -353,7 +354,7 @@ func TestSyscallNoError(t *testing.T) { t.Fatalf("failed to chown test binary %q, %v", tmpBinary, err) } - err = os.Chmod(tmpBinary, 0755|os.ModeSetuid) + err = os.Chmod(tmpBinary, 0755|fs.ModeSetuid) if err != nil { t.Fatalf("failed to set setuid bit on test binary %q, %v", tmpBinary, err) } diff --git a/src/syscall/syscall_plan9.go b/src/syscall/syscall_plan9.go index 1648e409b09..d16cad45d85 100644 --- a/src/syscall/syscall_plan9.go +++ b/src/syscall/syscall_plan9.go @@ -25,7 +25,7 @@ const bitSize16 = 2 // using errors.Is. For example: // // _, _, err := syscall.Syscall(...) -// if errors.Is(err, os.ErrNotExist) ... +// if errors.Is(err, fs.ErrNotExist) ... type ErrorString string func (e ErrorString) Error() string { return string(e) } diff --git a/src/syscall/syscall_unix.go b/src/syscall/syscall_unix.go index 91c939e0ea7..786ad34170d 100644 --- a/src/syscall/syscall_unix.go +++ b/src/syscall/syscall_unix.go @@ -110,7 +110,7 @@ func (m *mmapper) Munmap(data []byte) (err error) { // using errors.Is. For example: // // _, _, err := syscall.Syscall(...) -// if errors.Is(err, os.ErrNotExist) ... +// if errors.Is(err, fs.ErrNotExist) ... type Errno uintptr func (e Errno) Error() string { diff --git a/src/syscall/syscall_windows.go b/src/syscall/syscall_windows.go index f62c00d72fe..40c43de84c8 100644 --- a/src/syscall/syscall_windows.go +++ b/src/syscall/syscall_windows.go @@ -106,7 +106,7 @@ func UTF16PtrFromString(s string) (*uint16, error) { // using errors.Is. For example: // // _, _, err := syscall.Syscall(...) -// if errors.Is(err, os.ErrNotExist) ... +// if errors.Is(err, fs.ErrNotExist) ... type Errno uintptr func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) } From 9ad090c5fea60c9925b7eb30155ce01961c3537f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sat, 18 Jul 2020 22:26:00 -0400 Subject: [PATCH 022/403] testing/iotest: add TestReader to test readers There are many reader behaviors that are subtle and worth testing, and it's nice to have one complete tester instead of many incomplete ones. For #41190, which will use this as part of a larger file system implementation tester. Change-Id: Ib4cc7fae94b0d9b45dfacadc52baa77ad3761322 Reviewed-on: https://go-review.googlesource.com/c/go/+/243909 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike Reviewed-by: Emmanuel Odeke --- src/testing/iotest/reader.go | 175 +++++++++++++++++++++++++++++- src/testing/iotest/reader_test.go | 10 ++ 2 files changed, 181 insertions(+), 4 deletions(-) diff --git a/src/testing/iotest/reader.go b/src/testing/iotest/reader.go index bc2f72a911d..33b782dcb60 100644 --- a/src/testing/iotest/reader.go +++ b/src/testing/iotest/reader.go @@ -6,8 +6,11 @@ package iotest import ( + "bytes" "errors" + "fmt" "io" + "io/ioutil" ) // OneByteReader returns a Reader that implements @@ -90,13 +93,177 @@ func (r *timeoutReader) Read(p []byte) (int, error) { // ErrReader returns an io.Reader that returns 0, err from all Read calls. func ErrReader(err error) io.Reader { - return &alwaysErrReader{err: err} + return &errReader{err: err} } -type alwaysErrReader struct { +type errReader struct { err error } -func (aer *alwaysErrReader) Read(p []byte) (int, error) { - return 0, aer.err +func (r *errReader) Read(p []byte) (int, error) { + return 0, r.err +} + +type smallByteReader struct { + r io.Reader + off int + n int +} + +func (r *smallByteReader) Read(p []byte) (int, error) { + if len(p) == 0 { + return 0, nil + } + r.n = r.n%3 + 1 + n := r.n + if n > len(p) { + n = len(p) + } + n, err := r.r.Read(p[0:n]) + if err != nil && err != io.EOF { + err = fmt.Errorf("Read(%d bytes at offset %d): %v", n, r.off, err) + } + r.off += n + return n, err +} + +// TestReader tests that reading from r returns the expected file content. +// It does reads of different sizes, until EOF. +// If r implements io.ReaderAt or io.Seeker, TestReader also checks +// that those operations behave as they should. +// +// If TestReader finds any misbehaviors, it returns an error reporting them. +// The error text may span multiple lines. +func TestReader(r io.Reader, content []byte) error { + if len(content) > 0 { + n, err := r.Read(nil) + if n != 0 || err != nil { + return fmt.Errorf("Read(0) = %d, %v, want 0, nil", n, err) + } + } + + data, err := ioutil.ReadAll(&smallByteReader{r: r}) + if err != nil { + return err + } + if !bytes.Equal(data, content) { + return fmt.Errorf("ReadAll(small amounts) = %q\n\twant %q", data, content) + } + n, err := r.Read(make([]byte, 10)) + if n != 0 || err != io.EOF { + return fmt.Errorf("Read(10) at EOF = %v, %v, want 0, EOF", n, err) + } + + if r, ok := r.(io.ReadSeeker); ok { + // Seek(0, 1) should report the current file position (EOF). + if off, err := r.Seek(0, 1); off != int64(len(content)) || err != nil { + return fmt.Errorf("Seek(0, 1) from EOF = %d, %v, want %d, nil", off, err, len(content)) + } + + // Seek backward partway through file, in two steps. + // If middle == 0, len(content) == 0, can't use the -1 and +1 seeks. + middle := len(content) - len(content)/3 + if middle > 0 { + if off, err := r.Seek(-1, 1); off != int64(len(content)-1) || err != nil { + return fmt.Errorf("Seek(-1, 1) from EOF = %d, %v, want %d, nil", -off, err, len(content)-1) + } + if off, err := r.Seek(int64(-len(content)/3), 1); off != int64(middle-1) || err != nil { + return fmt.Errorf("Seek(%d, 1) from %d = %d, %v, want %d, nil", -len(content)/3, len(content)-1, off, err, middle-1) + } + if off, err := r.Seek(+1, 1); off != int64(middle) || err != nil { + return fmt.Errorf("Seek(+1, 1) from %d = %d, %v, want %d, nil", middle-1, off, err, middle) + } + } + + // Seek(0, 1) should report the current file position (middle). + if off, err := r.Seek(0, 1); off != int64(middle) || err != nil { + return fmt.Errorf("Seek(0, 1) from %d = %d, %v, want %d, nil", middle, off, err, middle) + } + + // Reading forward should return the last part of the file. + data, err := ioutil.ReadAll(&smallByteReader{r: r}) + if err != nil { + return fmt.Errorf("ReadAll from offset %d: %v", middle, err) + } + if !bytes.Equal(data, content[middle:]) { + return fmt.Errorf("ReadAll from offset %d = %q\n\twant %q", middle, data, content[middle:]) + } + + // Seek relative to end of file, but start elsewhere. + if off, err := r.Seek(int64(middle/2), 0); off != int64(middle/2) || err != nil { + return fmt.Errorf("Seek(%d, 0) from EOF = %d, %v, want %d, nil", middle/2, off, err, middle/2) + } + if off, err := r.Seek(int64(-len(content)/3), 2); off != int64(middle) || err != nil { + return fmt.Errorf("Seek(%d, 2) from %d = %d, %v, want %d, nil", -len(content)/3, middle/2, off, err, middle) + } + + // Reading forward should return the last part of the file (again). + data, err = ioutil.ReadAll(&smallByteReader{r: r}) + if err != nil { + return fmt.Errorf("ReadAll from offset %d: %v", middle, err) + } + if !bytes.Equal(data, content[middle:]) { + return fmt.Errorf("ReadAll from offset %d = %q\n\twant %q", middle, data, content[middle:]) + } + + // Absolute seek & read forward. + if off, err := r.Seek(int64(middle/2), 0); off != int64(middle/2) || err != nil { + return fmt.Errorf("Seek(%d, 0) from EOF = %d, %v, want %d, nil", middle/2, off, err, middle/2) + } + data, err = ioutil.ReadAll(r) + if err != nil { + return fmt.Errorf("ReadAll from offset %d: %v", middle/2, err) + } + if !bytes.Equal(data, content[middle/2:]) { + return fmt.Errorf("ReadAll from offset %d = %q\n\twant %q", middle/2, data, content[middle/2:]) + } + } + + if r, ok := r.(io.ReaderAt); ok { + data := make([]byte, len(content), len(content)+1) + for i := range data { + data[i] = 0xfe + } + n, err := r.ReadAt(data, 0) + if n != len(data) || err != nil && err != io.EOF { + return fmt.Errorf("ReadAt(%d, 0) = %v, %v, want %d, nil or EOF", len(data), n, err, len(data)) + } + if !bytes.Equal(data, content) { + return fmt.Errorf("ReadAt(%d, 0) = %q\n\twant %q", len(data), data, content) + } + + n, err = r.ReadAt(data[:1], int64(len(data))) + if n != 0 || err != io.EOF { + return fmt.Errorf("ReadAt(1, %d) = %v, %v, want 0, EOF", len(data), n, err) + } + + for i := range data { + data[i] = 0xfe + } + n, err = r.ReadAt(data[:cap(data)], 0) + if n != len(data) || err != io.EOF { + return fmt.Errorf("ReadAt(%d, 0) = %v, %v, want %d, EOF", cap(data), n, err, len(data)) + } + if !bytes.Equal(data, content) { + return fmt.Errorf("ReadAt(%d, 0) = %q\n\twant %q", len(data), data, content) + } + + for i := range data { + data[i] = 0xfe + } + for i := range data { + n, err = r.ReadAt(data[i:i+1], int64(i)) + if n != 1 || err != nil && (i != len(data)-1 || err != io.EOF) { + want := "nil" + if i == len(data)-1 { + want = "nil or EOF" + } + return fmt.Errorf("ReadAt(1, %d) = %v, %v, want 1, %s", i, n, err, want) + } + if data[i] != content[i] { + return fmt.Errorf("ReadAt(1, %d) = %q want %q", i, data[i:i+1], content[i:i+1]) + } + } + } + return nil } diff --git a/src/testing/iotest/reader_test.go b/src/testing/iotest/reader_test.go index 6004e841e5e..f149e74c74d 100644 --- a/src/testing/iotest/reader_test.go +++ b/src/testing/iotest/reader_test.go @@ -8,6 +8,7 @@ import ( "bytes" "errors" "io" + "strings" "testing" ) @@ -249,3 +250,12 @@ func TestErrReader(t *testing.T) { }) } } + +func TestStringsReader(t *testing.T) { + const msg = "Now is the time for all good gophers." + + r := strings.NewReader(msg) + if err := TestReader(r, []byte(msg)); err != nil { + t.Fatal(err) + } +} From fcb9d6b5d0ba6f5606c2b5dfc09f75e2dc5fc1e5 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 09:56:43 -0400 Subject: [PATCH 023/403] io/fs: add FS, File, ReadDirFile; move DirEntry from os These are the core interfaces for the io/fs design. See #41190 and https://golang.org/s/draft-iofs-design for details. DirEntry was left behind in the previous move from os but is needed for ReadDirFile, so it moves in this commit. Also apply a couple comment changes suggested in the review of CL 261540. For #41190. Change-Id: I087741545139ed30b9ba5db728a0bad71129500b Reviewed-on: https://go-review.googlesource.com/c/go/+/243908 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Emmanuel Odeke Reviewed-by: Rob Pike TryBot-Result: Go Bot --- src/io/fs/fs.go | 112 +++++++++++++++++++++++++++++++++++++++++++ src/io/fs/fs_test.go | 48 +++++++++++++++++++ src/os/dir.go | 24 ++-------- 3 files changed, 163 insertions(+), 21 deletions(-) create mode 100644 src/io/fs/fs_test.go diff --git a/src/io/fs/fs.go b/src/io/fs/fs.go index de5c465d9d3..d9f89fc6ee5 100644 --- a/src/io/fs/fs.go +++ b/src/io/fs/fs.go @@ -12,6 +12,118 @@ import ( "time" ) +// An FS provides access to a hierarchical file system. +// +// The FS interface is the minimum implementation required of the file system. +// A file system may implement additional interfaces, +// such as fsutil.ReadFileFS, to provide additional or optimized functionality. +// See io/fsutil for details. +type FS interface { + // Open opens the named file. + // + // When Open returns an error, it should be of type *PathError + // with the Op field set to "open", the Path field set to name, + // and the Err field describing the problem. + // + // Open should reject attempts to open names that do not satisfy + // ValidPath(name), returning a *PathError with Err set to + // ErrInvalid or ErrNotExist. + Open(name string) (File, error) +} + +// ValidPath reports whether the given path name +// is valid for use in a call to Open. +// Path names passed to open are unrooted, slash-separated +// sequences of path elements, like “x/y/z”. +// Path names must not contain a “.” or “..” or empty element, +// except for the special case that the root directory is named “.”. +// +// Paths are slash-separated on all systems, even Windows. +// Backslashes must not appear in path names. +func ValidPath(name string) bool { + if name == "." { + // special case + return true + } + + // Iterate over elements in name, checking each. + for { + i := 0 + for i < len(name) && name[i] != '/' { + if name[i] == '\\' { + return false + } + i++ + } + elem := name[:i] + if elem == "" || elem == "." || elem == ".." { + return false + } + if i == len(name) { + return true // reached clean ending + } + name = name[i+1:] + } +} + +// A File provides access to a single file. +// The File interface is the minimum implementation required of the file. +// A file may implement additional interfaces, such as +// ReadDirFile, ReaderAt, or Seeker, to provide additional or optimized functionality. +type File interface { + Stat() (FileInfo, error) + Read([]byte) (int, error) + Close() error +} + +// A DirEntry is an entry read from a directory +// (using the ReadDir function or a ReadDirFile's ReadDir method). +type DirEntry interface { + // Name returns the name of the file (or subdirectory) described by the entry. + // This name is only the final element of the path (the base name), not the entire path. + // For example, Name would return "hello.go" not "/home/gopher/hello.go". + Name() string + + // IsDir reports whether the entry describes a directory. + IsDir() bool + + // Type returns the type bits for the entry. + // The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method. + Type() FileMode + + // Info returns the FileInfo for the file or subdirectory described by the entry. + // The returned FileInfo may be from the time of the original directory read + // or from the time of the call to Info. If the file has been removed or renamed + // since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist). + // If the entry denotes a symbolic link, Info reports the information about the link itself, + // not the link's target. + Info() (FileInfo, error) +} + +// A ReadDirFile is a directory file whose entries can be read with the ReadDir method. +// Every directory file should implement this interface. +// (It is permissible for any file to implement this interface, +// but if so ReadDir should return an error for non-directories.) +type ReadDirFile interface { + File + + // ReadDir reads the contents of the directory and returns + // a slice of up to n DirEntry values in directory order. + // Subsequent calls on the same file will yield further DirEntry values. + // + // If n > 0, ReadDir returns at most n DirEntry structures. + // In this case, if ReadDir returns an empty slice, it will return + // a non-nil error explaining why. + // At the end of a directory, the error is io.EOF. + // + // If n <= 0, ReadDir returns all the DirEntry values from the directory + // in a single slice. In this case, if ReadDir succeeds (reads all the way + // to the end of the directory), it returns the slice and a nil error. + // If it encounters an error before the end of the directory, + // ReadDir returns the DirEntry list read until that point and a non-nil error. + ReadDir(n int) ([]DirEntry, error) +} + // Generic file system errors. // Errors returned by file systems can be tested against these errors // using errors.Is. diff --git a/src/io/fs/fs_test.go b/src/io/fs/fs_test.go new file mode 100644 index 00000000000..8d395fc0db1 --- /dev/null +++ b/src/io/fs/fs_test.go @@ -0,0 +1,48 @@ +// Copyright 2020 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 fs_test + +import ( + . "io/fs" + "testing" +) + +var isValidPathTests = []struct { + name string + ok bool +}{ + {".", true}, + {"x", true}, + {"x/y", true}, + + {"", false}, + {"..", false}, + {"/", false}, + {"x/", false}, + {"/x", false}, + {"x/y/", false}, + {"/x/y", false}, + {"./", false}, + {"./x", false}, + {"x/.", false}, + {"x/./y", false}, + {"../", false}, + {"../x", false}, + {"x/..", false}, + {"x/../y", false}, + {"x//y", false}, + {`x\`, false}, + {`x\y`, false}, + {`\x`, false}, +} + +func TestValidPath(t *testing.T) { + for _, tt := range isValidPathTests { + ok := ValidPath(tt.name) + if ok != tt.ok { + t.Errorf("ValidPath(%q) = %v, want %v", tt.name, ok, tt.ok) + } + } +} diff --git a/src/os/dir.go b/src/os/dir.go index a3120017043..b56d9984592 100644 --- a/src/os/dir.go +++ b/src/os/dir.go @@ -4,6 +4,8 @@ package os +import "io/fs" + type readdirMode int const ( @@ -62,27 +64,7 @@ func (f *File) Readdirnames(n int) (names []string, err error) { // A DirEntry is an entry read from a directory // (using the ReadDir function or a File's ReadDir method). -type DirEntry interface { - // Name returns the name of the file (or subdirectory) described by the entry. - // This name is only the final element of the path, not the entire path. - // For example, Name would return "hello.go" not "/home/gopher/hello.go". - Name() string - - // IsDir reports whether the entry describes a subdirectory. - IsDir() bool - - // Type returns the type bits for the entry. - // The type bits are a subset of the usual FileMode bits, those returned by the FileMode.Type method. - Type() FileMode - - // Info returns the FileInfo for the file or subdirectory described by the entry. - // The returned FileInfo may be from the time of the original directory read - // or from the time of the call to Info. If the file has been removed or renamed - // since the directory read, Info may return an error satisfying errors.Is(err, ErrNotExist). - // If the entry denotes a symbolic link, Info reports the information about the link itself, - // not the link's target. - Info() (FileInfo, error) -} +type DirEntry = fs.DirEntry // ReadDir reads the contents of the directory associated with the file f // and returns a slice of DirEntry values in directory order. From 310984bf54a52b15085e195a402873ab558d34d4 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 19 Oct 2020 12:01:23 +0200 Subject: [PATCH 024/403] syscall, cmd/go/internal/modload: add and use Access on aix Implement Access using Faccessat on aix following golang.org/x/sys/unix CL 262897 and switch cmd/go/internal/modload to use it to implement hasWritePerm. Change-Id: I682e44737ac2bac5a203ac1c9ddd277810454426 Reviewed-on: https://go-review.googlesource.com/c/go/+/263540 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modload/stat_openfile.go | 2 +- src/cmd/go/internal/modload/stat_unix.go | 2 +- src/syscall/syscall_aix.go | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/modload/stat_openfile.go b/src/cmd/go/internal/modload/stat_openfile.go index 7cdeaf47a2f..5842b858f0b 100644 --- a/src/cmd/go/internal/modload/stat_openfile.go +++ b/src/cmd/go/internal/modload/stat_openfile.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. -// +build aix js,wasm plan9 +// +build js,wasm plan9 // On plan9, per http://9p.io/magic/man2html/2/access: “Since file permissions // are checked by the server and group information is not known to the client, diff --git a/src/cmd/go/internal/modload/stat_unix.go b/src/cmd/go/internal/modload/stat_unix.go index 65068444d06..f49278ec3a8 100644 --- a/src/cmd/go/internal/modload/stat_unix.go +++ b/src/cmd/go/internal/modload/stat_unix.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. -// +build darwin dragonfly freebsd linux netbsd openbsd solaris +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris package modload diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go index 8837dd5a7f3..9c6afba442e 100644 --- a/src/syscall/syscall_aix.go +++ b/src/syscall/syscall_aix.go @@ -45,6 +45,10 @@ func (ts *StTimespec_t) Nano() int64 { * Wrapped */ +func Access(path string, mode uint32) (err error) { + return Faccessat(_AT_FDCWD, path, mode, 0) +} + // fcntl must never be called with cmd=F_DUP2FD because it doesn't work on AIX // There is no way to create a custom fcntl and to keep //sys fcntl easily, // because we need fcntl name for its libc symbol. This is linked with the script. From 55b2d479d774d9887a6ec32b34e2c413f7c84f78 Mon Sep 17 00:00:00 2001 From: Nikhil Benesch Date: Sun, 18 Oct 2020 21:55:55 -0400 Subject: [PATCH 025/403] net/http/cgi: preserve LD_LIBRARY_PATH on NetBSD, too This makes the behavior of the cgi package on NetBSD consistent with its behavior on the other BSDs. It is also necessary for the test suite to pass on NetBSD with gccgo (see CL 261137). Change-Id: I531a6e0954f895a921204dcc61e3f3e90860a23d Reviewed-on: https://go-review.googlesource.com/c/go/+/263577 Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Benny Siegert Reviewed-by: Tobias Klauser Trust: Benny Siegert --- src/net/http/cgi/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go index 624044aa092..cd42f4d9218 100644 --- a/src/net/http/cgi/host.go +++ b/src/net/http/cgi/host.go @@ -39,7 +39,7 @@ var osDefaultInheritEnv = func() []string { switch runtime.GOOS { case "darwin", "ios": return []string{"DYLD_LIBRARY_PATH"} - case "linux", "freebsd", "openbsd": + case "linux", "freebsd", "netbsd", "openbsd": return []string{"LD_LIBRARY_PATH"} case "hpux": return []string{"LD_LIBRARY_PATH", "SHLIB_PATH"} From de932da453f68b8fc04e9c2ab25136748173c806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Tue, 13 Oct 2020 22:30:23 +0200 Subject: [PATCH 026/403] internal/cpu: consolidate arm64 feature detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move code to detect and mask arm64 CPU features from runtime to internal/cpu. Change-Id: Ib784e2ff056e8def125d68827b852f07a3eff0db Reviewed-on: https://go-review.googlesource.com/c/go/+/261878 Trust: Martin Möhrmann Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Tobias Klauser Reviewed-by: Benny Siegert --- src/internal/cpu/cpu_android.go | 7 ++ src/internal/cpu/cpu_arm64.go | 73 +++++++++++++--- src/internal/cpu/cpu_arm64.s | 12 +++ src/internal/cpu/cpu_freebsd.go | 7 ++ src/internal/cpu/cpu_linux.go | 9 ++ src/internal/cpu/cpu_other.go | 11 +++ src/runtime/auxv_none.go | 1 - src/runtime/os_freebsd_arm64.go | 143 ------------------------------- src/runtime/os_freebsd_noauxv.go | 2 +- src/runtime/os_linux_arm64.go | 14 +-- src/runtime/os_netbsd.go | 1 - src/runtime/os_netbsd_386.go | 3 - src/runtime/os_netbsd_amd64.go | 3 - src/runtime/os_netbsd_arm.go | 3 - src/runtime/os_netbsd_arm64.go | 12 +-- src/runtime/os_openbsd_arm64.go | 11 --- src/runtime/sys_freebsd_arm64.s | 21 ----- 17 files changed, 110 insertions(+), 223 deletions(-) create mode 100644 src/internal/cpu/cpu_android.go create mode 100644 src/internal/cpu/cpu_arm64.s create mode 100644 src/internal/cpu/cpu_freebsd.go create mode 100644 src/internal/cpu/cpu_linux.go create mode 100644 src/internal/cpu/cpu_other.go diff --git a/src/internal/cpu/cpu_android.go b/src/internal/cpu/cpu_android.go new file mode 100644 index 00000000000..d995e8d5a74 --- /dev/null +++ b/src/internal/cpu/cpu_android.go @@ -0,0 +1,7 @@ +// Copyright 2020 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 cpu + +const GOOS = "android" diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index d9e0c98ca6b..533bea24700 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -6,13 +6,11 @@ package cpu const CacheLinePadSize = 64 -// arm64 doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2. -// These are initialized by archauxv and should not be changed after they are -// initialized. +// HWCap may be initialized by archauxv and +// should not be changed after it was initialized. var HWCap uint -var HWCap2 uint -// HWCAP/HWCAP2 bits. These are exposed by Linux. +// HWCAP bits. These are exposed by Linux. const ( hwcap_AES = 1 << 3 hwcap_PMULL = 1 << 4 @@ -32,15 +30,66 @@ func doinit() { {Name: "atomics", Feature: &ARM64.HasATOMICS}, } - // HWCAP feature bits - ARM64.HasAES = isSet(HWCap, hwcap_AES) - ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) - ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) - ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) - ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) - ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) + switch GOOS { + case "linux", "android": + // HWCap was populated by the runtime from the auxillary vector. + // Use HWCap information since reading aarch64 system registers + // is not supported in user space on older linux kernels. + ARM64.HasAES = isSet(HWCap, hwcap_AES) + ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) + ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) + ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) + ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) + + // The Samsung S9+ kernel reports support for atomics, but not all cores + // actually support them, resulting in SIGILL. See issue #28431. + // TODO(elias.naur): Only disable the optimization on bad chipsets on android. + ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && GOOS != "android" + + case "freebsd": + // Retrieve info from system register ID_AA64ISAR0_EL1. + isar0 := getisar0() + + // ID_AA64ISAR0_EL1 + switch extractBits(isar0, 4, 7) { + case 1: + ARM64.HasAES = true + case 2: + ARM64.HasAES = true + ARM64.HasPMULL = true + } + + switch extractBits(isar0, 8, 11) { + case 1: + ARM64.HasSHA1 = true + } + + switch extractBits(isar0, 12, 15) { + case 1, 2: + ARM64.HasSHA2 = true + } + + switch extractBits(isar0, 16, 19) { + case 1: + ARM64.HasCRC32 = true + } + + switch extractBits(isar0, 20, 23) { + case 2: + ARM64.HasATOMICS = true + } + default: + // Other operating systems do not support reading HWCap from auxillary vector + // or reading privileged aarch64 system registers in user space. + } +} + +func extractBits(data uint64, start, end uint) uint { + return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) } func isSet(hwc uint, value uint) bool { return hwc&value != 0 } + +func getisar0() uint64 diff --git a/src/internal/cpu/cpu_arm64.s b/src/internal/cpu/cpu_arm64.s new file mode 100644 index 00000000000..d85914973f9 --- /dev/null +++ b/src/internal/cpu/cpu_arm64.s @@ -0,0 +1,12 @@ +// Copyright 2020 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. + +#include "textflag.h" + +// func getisar0() uint64 +TEXT ·getisar0(SB),NOSPLIT,$0 + // get Instruction Set Attributes 0 into R0 + MRS ID_AA64ISAR0_EL1, R0 + MOVD R0, ret+0(FP) + RET diff --git a/src/internal/cpu/cpu_freebsd.go b/src/internal/cpu/cpu_freebsd.go new file mode 100644 index 00000000000..dc37173dacf --- /dev/null +++ b/src/internal/cpu/cpu_freebsd.go @@ -0,0 +1,7 @@ +// Copyright 2020 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 cpu + +const GOOS = "freebsd" diff --git a/src/internal/cpu/cpu_linux.go b/src/internal/cpu/cpu_linux.go new file mode 100644 index 00000000000..ec0b84c510f --- /dev/null +++ b/src/internal/cpu/cpu_linux.go @@ -0,0 +1,9 @@ +// Copyright 2020 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. + +// +build !android + +package cpu + +const GOOS = "linux" diff --git a/src/internal/cpu/cpu_other.go b/src/internal/cpu/cpu_other.go new file mode 100644 index 00000000000..8a15fbe79d8 --- /dev/null +++ b/src/internal/cpu/cpu_other.go @@ -0,0 +1,11 @@ +// Copyright 2020 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. + +// +build !linux +// +build !freebsd +// +build !android + +package cpu + +const GOOS = "other" diff --git a/src/runtime/auxv_none.go b/src/runtime/auxv_none.go index 3a560a17937..3ca617b21eb 100644 --- a/src/runtime/auxv_none.go +++ b/src/runtime/auxv_none.go @@ -7,7 +7,6 @@ // +build !dragonfly // +build !freebsd // +build !netbsd -// +build !openbsd !arm64 // +build !solaris package runtime diff --git a/src/runtime/os_freebsd_arm64.go b/src/runtime/os_freebsd_arm64.go index 51ebf9d4784..b5b25f0dc5f 100644 --- a/src/runtime/os_freebsd_arm64.go +++ b/src/runtime/os_freebsd_arm64.go @@ -4,149 +4,6 @@ package runtime -import "internal/cpu" - -const ( - hwcap_FP = 1 << 0 - hwcap_ASIMD = 1 << 1 - hwcap_EVTSTRM = 1 << 2 - hwcap_AES = 1 << 3 - hwcap_PMULL = 1 << 4 - hwcap_SHA1 = 1 << 5 - hwcap_SHA2 = 1 << 6 - hwcap_CRC32 = 1 << 7 - hwcap_ATOMICS = 1 << 8 - hwcap_FPHP = 1 << 9 - hwcap_ASIMDHP = 1 << 10 - hwcap_CPUID = 1 << 11 - hwcap_ASIMDRDM = 1 << 12 - hwcap_JSCVT = 1 << 13 - hwcap_FCMA = 1 << 14 - hwcap_LRCPC = 1 << 15 - hwcap_DCPOP = 1 << 16 - hwcap_SHA3 = 1 << 17 - hwcap_SM3 = 1 << 18 - hwcap_SM4 = 1 << 19 - hwcap_ASIMDDP = 1 << 20 - hwcap_SHA512 = 1 << 21 - hwcap_SVE = 1 << 22 - hwcap_ASIMDFHM = 1 << 23 -) - -func getisar0() uint64 -func getisar1() uint64 -func getpfr0() uint64 - -// no hwcap support on FreeBSD aarch64, we need to retrieve the info from -// ID_AA64ISAR0_EL1, ID_AA64ISAR1_EL1 and ID_AA64PFR0_EL1 -func archauxv(tag, val uintptr) { - var isar0, isar1, pfr0 uint64 - - isar0 = getisar0() - isar1 = getisar1() - pfr0 = getpfr0() - - // ID_AA64ISAR0_EL1 - switch extractBits(isar0, 4, 7) { - case 1: - cpu.HWCap |= hwcap_AES - case 2: - cpu.HWCap |= hwcap_PMULL | hwcap_AES - } - - switch extractBits(isar0, 8, 11) { - case 1: - cpu.HWCap |= hwcap_SHA1 - } - - switch extractBits(isar0, 12, 15) { - case 1: - cpu.HWCap |= hwcap_SHA2 - case 2: - cpu.HWCap |= hwcap_SHA2 | hwcap_SHA512 - } - - switch extractBits(isar0, 16, 19) { - case 1: - cpu.HWCap |= hwcap_CRC32 - } - - switch extractBits(isar0, 20, 23) { - case 2: - cpu.HWCap |= hwcap_ATOMICS - } - - switch extractBits(isar0, 28, 31) { - case 1: - cpu.HWCap |= hwcap_ASIMDRDM - } - - switch extractBits(isar0, 32, 35) { - case 1: - cpu.HWCap |= hwcap_SHA3 - } - - switch extractBits(isar0, 36, 39) { - case 1: - cpu.HWCap |= hwcap_SM3 - } - - switch extractBits(isar0, 40, 43) { - case 1: - cpu.HWCap |= hwcap_SM4 - } - - switch extractBits(isar0, 44, 47) { - case 1: - cpu.HWCap |= hwcap_ASIMDDP - } - - // ID_AA64ISAR1_EL1 - switch extractBits(isar1, 0, 3) { - case 1: - cpu.HWCap |= hwcap_DCPOP - } - - switch extractBits(isar1, 12, 15) { - case 1: - cpu.HWCap |= hwcap_JSCVT - } - - switch extractBits(isar1, 16, 19) { - case 1: - cpu.HWCap |= hwcap_FCMA - } - - switch extractBits(isar1, 20, 23) { - case 1: - cpu.HWCap |= hwcap_LRCPC - } - - // ID_AA64PFR0_EL1 - switch extractBits(pfr0, 16, 19) { - case 0: - cpu.HWCap |= hwcap_FP - case 1: - cpu.HWCap |= hwcap_FP | hwcap_FPHP - } - - switch extractBits(pfr0, 20, 23) { - case 0: - cpu.HWCap |= hwcap_ASIMD - case 1: - cpu.HWCap |= hwcap_ASIMD | hwcap_ASIMDHP - } - - switch extractBits(pfr0, 32, 35) { - case 1: - cpu.HWCap |= hwcap_SVE - } -} - -func extractBits(data uint64, start, end uint) uint { - return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) -} - //go:nosplit func cputicks() int64 { // Currently cputicks() is used in blocking profiler and to seed fastrand(). diff --git a/src/runtime/os_freebsd_noauxv.go b/src/runtime/os_freebsd_noauxv.go index c6a49927c8b..01efb9b7c9c 100644 --- a/src/runtime/os_freebsd_noauxv.go +++ b/src/runtime/os_freebsd_noauxv.go @@ -3,7 +3,7 @@ // license that can be found in the LICENSE file. // +build freebsd -// +build !arm,!arm64 +// +build !arm package runtime diff --git a/src/runtime/os_linux_arm64.go b/src/runtime/os_linux_arm64.go index 19968dc164b..c5fd7420488 100644 --- a/src/runtime/os_linux_arm64.go +++ b/src/runtime/os_linux_arm64.go @@ -11,19 +11,7 @@ import "internal/cpu" func archauxv(tag, val uintptr) { switch tag { case _AT_HWCAP: - // arm64 doesn't have a 'cpuid' instruction equivalent and relies on - // HWCAP/HWCAP2 bits for hardware capabilities. - hwcap := uint(val) - if GOOS == "android" { - // The Samsung S9+ kernel reports support for atomics, but not all cores - // actually support them, resulting in SIGILL. See issue #28431. - // TODO(elias.naur): Only disable the optimization on bad chipsets. - const hwcap_ATOMICS = 1 << 8 - hwcap &= ^uint(hwcap_ATOMICS) - } - cpu.HWCap = hwcap - case _AT_HWCAP2: - cpu.HWCap2 = uint(val) + cpu.HWCap = uint(val) } } diff --git a/src/runtime/os_netbsd.go b/src/runtime/os_netbsd.go index c4c3d8e2fe1..f7f90cedc1a 100644 --- a/src/runtime/os_netbsd.go +++ b/src/runtime/os_netbsd.go @@ -359,7 +359,6 @@ func sysargs(argc int32, argv **byte) { // now argv+n is auxv auxv := (*[1 << 28]uintptr)(add(unsafe.Pointer(argv), uintptr(n)*sys.PtrSize)) sysauxv(auxv[:]) - archauxv(auxv[:]) } const ( diff --git a/src/runtime/os_netbsd_386.go b/src/runtime/os_netbsd_386.go index c203af9cef5..037f7e36dc6 100644 --- a/src/runtime/os_netbsd_386.go +++ b/src/runtime/os_netbsd_386.go @@ -14,6 +14,3 @@ func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintp mc.__gregs[_REG_EDX] = uint32(uintptr(unsafe.Pointer(gp))) mc.__gregs[_REG_ESI] = uint32(fn) } - -func archauxv(auxv []uintptr) { -} diff --git a/src/runtime/os_netbsd_amd64.go b/src/runtime/os_netbsd_amd64.go index ea9d1254920..5118b0c4ffd 100644 --- a/src/runtime/os_netbsd_amd64.go +++ b/src/runtime/os_netbsd_amd64.go @@ -14,6 +14,3 @@ func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintp mc.__gregs[_REG_R9] = uint64(uintptr(unsafe.Pointer(gp))) mc.__gregs[_REG_R12] = uint64(fn) } - -func archauxv(auxv []uintptr) { -} diff --git a/src/runtime/os_netbsd_arm.go b/src/runtime/os_netbsd_arm.go index 646da9dc0b4..b5ec23e45b0 100644 --- a/src/runtime/os_netbsd_arm.go +++ b/src/runtime/os_netbsd_arm.go @@ -32,6 +32,3 @@ func cputicks() int64 { // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler. return nanotime() } - -func archauxv(auxv []uintptr) { -} diff --git a/src/runtime/os_netbsd_arm64.go b/src/runtime/os_netbsd_arm64.go index ae2638c778c..8d21b0a430f 100644 --- a/src/runtime/os_netbsd_arm64.go +++ b/src/runtime/os_netbsd_arm64.go @@ -4,10 +4,7 @@ package runtime -import ( - "internal/cpu" - "unsafe" -) +import "unsafe" func lwp_mcontext_init(mc *mcontextt, stk unsafe.Pointer, mp *m, gp *g, fn uintptr) { // Machine dependent mcontext initialisation for LWP. @@ -24,10 +21,3 @@ func cputicks() int64 { // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler. return nanotime() } - -func archauxv(auxv []uintptr) { - // NetBSD does not supply AT_HWCAP, however we still need to initialise cpu.HWCaps. - // For now specify the bare minimum until we add some form of capabilities - // detection. See issue https://golang.org/issue/30824#issuecomment-494901591 - cpu.HWCap = 1<<1 | 1<<0 // ASIMD, FP -} diff --git a/src/runtime/os_openbsd_arm64.go b/src/runtime/os_openbsd_arm64.go index d559a2a3e5a..d71de7d196f 100644 --- a/src/runtime/os_openbsd_arm64.go +++ b/src/runtime/os_openbsd_arm64.go @@ -4,20 +4,9 @@ package runtime -import ( - "internal/cpu" -) - //go:nosplit func cputicks() int64 { // Currently cputicks() is used in blocking profiler and to seed runtime·fastrand(). // runtime·nanotime() is a poor approximation of CPU ticks that is enough for the profiler. return nanotime() } - -func sysargs(argc int32, argv **byte) { - // OpenBSD does not have auxv, however we still need to initialise cpu.HWCaps. - // For now specify the bare minimum until we add some form of capabilities - // detection. See issue #31746. - cpu.HWCap = 1<<1 | 1<<0 // ASIMD, FP -} diff --git a/src/runtime/sys_freebsd_arm64.s b/src/runtime/sys_freebsd_arm64.s index 2330f2ffe2c..8a4f9b7fa14 100644 --- a/src/runtime/sys_freebsd_arm64.s +++ b/src/runtime/sys_freebsd_arm64.s @@ -515,24 +515,3 @@ TEXT runtime·getCntxct(SB),NOSPLIT,$0 MOVW R0, ret+8(FP) RET - -// func getisar0() uint64 -TEXT runtime·getisar0(SB),NOSPLIT,$0 - // get Instruction Set Attributes 0 into R0 - MRS ID_AA64ISAR0_EL1, R0 - MOVD R0, ret+0(FP) - RET - -// func getisar1() uint64 -TEXT runtime·getisar1(SB),NOSPLIT,$0 - // get Instruction Set Attributes 1 into R0 - MRS ID_AA64ISAR1_EL1, R0 - MOVD R0, ret+0(FP) - RET - -// func getpfr0() uint64 -TEXT runtime·getpfr0(SB),NOSPLIT,$0 - // get Processor Feature Register 0 into R0 - MRS ID_AA64PFR0_EL1, R0 - MOVD R0, ret+0(FP) - RET From feb984c96b10900daade4b47c4d308d7dd4ed5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Tue, 20 Oct 2020 11:06:02 +0200 Subject: [PATCH 027/403] internal/cpu: make architectures without initialization work explicit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When cpu_no_init.go was created most architectures did not have code in the doinit function. Currently only mips(le), riscv64 and wasm do not have empty doinit functions. Keeping cpu_no_init.go around does not reduce the work to satisfy the build process when adding support for new architectures. To support a new architecture a new file or build directive has to be added to an existing file at any rate to define the constant CacheLinePadSize. A new empty doinit can then be created in the new file or the existing doinit can be reused when adding the additional build directive. Change-Id: I58a97f8cdf1cf1be85c37f4550c40750358aa031 Reviewed-on: https://go-review.googlesource.com/c/go/+/263801 Trust: Martin Möhrmann Reviewed-by: Tobias Klauser --- src/internal/cpu/cpu_mips.go | 3 +++ src/internal/cpu/cpu_mipsle.go | 3 +++ src/internal/cpu/cpu_no_init.go | 18 ------------------ src/internal/cpu/cpu_riscv64.go | 3 +++ src/internal/cpu/cpu_wasm.go | 3 +++ 5 files changed, 12 insertions(+), 18 deletions(-) delete mode 100644 src/internal/cpu/cpu_no_init.go diff --git a/src/internal/cpu/cpu_mips.go b/src/internal/cpu/cpu_mips.go index 0f821e44e77..14a9c975eae 100644 --- a/src/internal/cpu/cpu_mips.go +++ b/src/internal/cpu/cpu_mips.go @@ -5,3 +5,6 @@ package cpu const CacheLinePadSize = 32 + +func doinit() { +} diff --git a/src/internal/cpu/cpu_mipsle.go b/src/internal/cpu/cpu_mipsle.go index 0f821e44e77..14a9c975eae 100644 --- a/src/internal/cpu/cpu_mipsle.go +++ b/src/internal/cpu/cpu_mipsle.go @@ -5,3 +5,6 @@ package cpu const CacheLinePadSize = 32 + +func doinit() { +} diff --git a/src/internal/cpu/cpu_no_init.go b/src/internal/cpu/cpu_no_init.go deleted file mode 100644 index fb381e1ce2d..00000000000 --- a/src/internal/cpu/cpu_no_init.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018 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. - -// +build !386 -// +build !amd64 -// +build !arm -// +build !arm64 -// +build !ppc64 -// +build !ppc64le -// +build !s390x -// +build !mips64 -// +build !mips64le - -package cpu - -func doinit() { -} diff --git a/src/internal/cpu/cpu_riscv64.go b/src/internal/cpu/cpu_riscv64.go index c49cab79fdc..54b8c3378b4 100644 --- a/src/internal/cpu/cpu_riscv64.go +++ b/src/internal/cpu/cpu_riscv64.go @@ -5,3 +5,6 @@ package cpu const CacheLinePadSize = 32 + +func doinit() { +} diff --git a/src/internal/cpu/cpu_wasm.go b/src/internal/cpu/cpu_wasm.go index b4597387705..2310ad6a481 100644 --- a/src/internal/cpu/cpu_wasm.go +++ b/src/internal/cpu/cpu_wasm.go @@ -5,3 +5,6 @@ package cpu const CacheLinePadSize = 64 + +func doinit() { +} From 0709e58bee0b268ee2a11629f44e352c41339443 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 20 Oct 2020 13:36:57 +0200 Subject: [PATCH 028/403] net/http/cgi: preserve env vars on illumos Preserve the same environment variables as on solaris. Spotted while reviewing CL 263577. Change-Id: Id479dcf83d6231e9ef1fd2404b400d10082e1d0b Reviewed-on: https://go-review.googlesource.com/c/go/+/263802 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Emmanuel Odeke --- src/net/http/cgi/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go index cd42f4d9218..eff67caf4e6 100644 --- a/src/net/http/cgi/host.go +++ b/src/net/http/cgi/host.go @@ -45,7 +45,7 @@ var osDefaultInheritEnv = func() []string { return []string{"LD_LIBRARY_PATH", "SHLIB_PATH"} case "irix": return []string{"LD_LIBRARY_PATH", "LD_LIBRARYN32_PATH", "LD_LIBRARY64_PATH"} - case "solaris": + case "illumos", "solaris": return []string{"LD_LIBRARY_PATH", "LD_LIBRARY_PATH_32", "LD_LIBRARY_PATH_64"} case "windows": return []string{"SystemRoot", "COMSPEC", "PATHEXT", "WINDIR"} From 0bf507efe9f995076e3a65bcf61baf3e905b58c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Mon, 19 Oct 2020 15:06:02 +0100 Subject: [PATCH 029/403] cmd/go: add BuildID to list -json -export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is, the following two pieces of shell code are now equivalent: $ go tool buildid $(go list -export -f {{.Export}} strings) v_0VqA6yzwuMg2dn4u57/PXcIR2Pb8Mi9yRdcdkwe $ go list -export -f {{.BuildID}} strings v_0VqA6yzwuMg2dn4u57/PXcIR2Pb8Mi9yRdcdkwe This does not expose any information that wasn't available before, but makes this workflow simpler and faster. In the first example, we have to execute two programs, and 'go tool buildid' has to re-open the export data file to read the build ID. With the new mechanism, 'go list -export' already has the build ID ready, so we can simply print it out. Moreover, when listing lots of related packages like './...', we can now obtain all their build IDs at once. Fixes #37281. Change-Id: I8e2f65a08391b3df1a628c6e06e708b8c8cb7865 Reviewed-on: https://go-review.googlesource.com/c/go/+/263542 Trust: Daniel Martí Trust: Bryan C. Mills Run-TryBot: Daniel Martí TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 1 + src/cmd/go/go_test.go | 12 ++++++++++++ src/cmd/go/internal/list/list.go | 1 + src/cmd/go/internal/load/pkg.go | 1 + src/cmd/go/internal/work/buildid.go | 1 + src/cmd/go/internal/work/exec.go | 1 + 6 files changed, 17 insertions(+) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index ebd786d4e2f..0827f0c609b 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -796,6 +796,7 @@ // BinaryOnly bool // binary-only package (no longer supported) // ForTest string // package is only for use in named test // Export string // file containing export data (when using -export) +// BuildID string // build ID of the export data (when using -export) // Module *Module // info about package's containing module, if any (can be nil) // Match []string // command-line patterns matching this package // DepOnly bool // package is only a dependency, not explicitly listed diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 2c11d169596..e9c26d161a9 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -1237,6 +1237,18 @@ func TestGoListExport(t *testing.T) { if _, err := os.Stat(file); err != nil { t.Fatalf("cannot find .Export result %s: %v", file, err) } + + tg.run("list", "-export", "-f", "{{.BuildID}}", "strings") + buildID := strings.TrimSpace(tg.stdout.String()) + if buildID == "" { + t.Fatalf(".BuildID with -export was empty") + } + + tg.run("tool", "buildid", file) + toolBuildID := strings.TrimSpace(tg.stdout.String()) + if buildID != toolBuildID { + t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID) + } } // Issue 4096. Validate the output of unsuccessful go install foo/quxx. diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 732cebc8cb9..9fd9d7446df 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -66,6 +66,7 @@ to -f '{{.ImportPath}}'. The struct being passed to the template is: BinaryOnly bool // binary-only package (no longer supported) ForTest string // package is only for use in named test Export string // file containing export data (when using -export) + BuildID string // build ID of the export data (when using -export) Module *Module // info about package's containing module, if any (can be nil) Match []string // command-line patterns matching this package DepOnly bool // package is only a dependency, not explicitly listed diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 066ff6c9815..913b3b94d76 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -60,6 +60,7 @@ type PackagePublic struct { ConflictDir string `json:",omitempty"` // Dir is hidden by this other directory ForTest string `json:",omitempty"` // package is only for use in named test Export string `json:",omitempty"` // file containing export data (set by go list -export) + BuildID string `json:",omitempty"` // build ID of the export data (set by go list -export) Module *modinfo.ModulePublic `json:",omitempty"` // info about package's module, if any Match []string `json:",omitempty"` // command-line patterns matching this package Goroot bool `json:",omitempty"` // is this package found in the Go root? diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index a3c9b1a2c1c..5cd3124e54a 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -713,6 +713,7 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error { return err } a.Package.Export = c.OutputFile(outputID) + a.Package.BuildID = a.buildID } } } diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 717b0cc3afe..3ffdca57182 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -433,6 +433,7 @@ func (b *Builder) build(ctx context.Context, a *Action) (err error) { need &^= needBuild if b.NeedExport { p.Export = a.built + p.BuildID = a.buildID } if need&needCompiledGoFiles != 0 { if err := b.loadCachedSrcFiles(a); err == nil { From 05f5ae74bc95b0d77a512029bc1a6739c5d0f181 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Tue, 20 Oct 2020 12:57:14 +0000 Subject: [PATCH 030/403] runtime: fix scavenging tests for pallocChunkBytes huge pages and larger Currently the scavenging tests implicitly assume that the system huge page size is always strictly less than 4 MiB, or pallocChunkBytes. This leads to failures on systems with huge pages of this size, and larger. Filter out those tests on such platforms and add a test for the 4 MiB case. The scavenger is already equipped to handle this case. Huge page sizes > 4 MiB are effectively ignored, so also add a test case to ensure that happens. Unfortunately we can't actually run these tests in our CI because they require the platform to provide the right huge page size, but we really should just parameterize this value so we can test it (there's a TODO about this already). Fixes #42053. Change-Id: Ia576cbf67e178a14a178a893967efbed27d6eb17 Reviewed-on: https://go-review.googlesource.com/c/go/+/263837 Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Michael Knyszek --- src/runtime/mgcscavenge_test.go | 53 ++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/src/runtime/mgcscavenge_test.go b/src/runtime/mgcscavenge_test.go index 7f619b1e7db..250343077ff 100644 --- a/src/runtime/mgcscavenge_test.go +++ b/src/runtime/mgcscavenge_test.go @@ -235,26 +235,43 @@ func TestPallocDataFindScavengeCandidate(t *testing.T) { if PhysHugePageSize > uintptr(PageSize) { // Check hugepage preserving behavior. bits := uint(PhysHugePageSize / uintptr(PageSize)) - tests["PreserveHugePageBottom"] = test{ - alloc: []BitRange{{bits + 2, PallocChunkPages - (bits + 2)}}, - min: 1, - max: 3, // Make it so that max would have us try to break the huge page. - want: BitRange{0, bits + 2}, - } - if 3*bits < PallocChunkPages { - // We need at least 3 huge pages in a chunk for this test to make sense. - tests["PreserveHugePageMiddle"] = test{ - alloc: []BitRange{{0, bits - 10}, {2*bits + 10, PallocChunkPages - (2*bits + 10)}}, + if bits < PallocChunkPages { + tests["PreserveHugePageBottom"] = test{ + alloc: []BitRange{{bits + 2, PallocChunkPages - (bits + 2)}}, min: 1, - max: 12, // Make it so that max would have us try to break the huge page. - want: BitRange{bits, bits + 10}, + max: 3, // Make it so that max would have us try to break the huge page. + want: BitRange{0, bits + 2}, + } + if 3*bits < PallocChunkPages { + // We need at least 3 huge pages in a chunk for this test to make sense. + tests["PreserveHugePageMiddle"] = test{ + alloc: []BitRange{{0, bits - 10}, {2*bits + 10, PallocChunkPages - (2*bits + 10)}}, + min: 1, + max: 12, // Make it so that max would have us try to break the huge page. + want: BitRange{bits, bits + 10}, + } + } + tests["PreserveHugePageTop"] = test{ + alloc: []BitRange{{0, PallocChunkPages - bits}}, + min: 1, + max: 1, // Even one page would break a huge page in this case. + want: BitRange{PallocChunkPages - bits, bits}, + } + } else if bits == PallocChunkPages { + tests["PreserveHugePageAll"] = test{ + min: 1, + max: 1, // Even one page would break a huge page in this case. + want: BitRange{0, PallocChunkPages}, + } + } else { + // The huge page size is greater than pallocChunkPages, so it should + // be effectively disabled. There's no way we can possible scavenge + // a huge page out of this bitmap chunk. + tests["PreserveHugePageNone"] = test{ + min: 1, + max: 1, + want: BitRange{PallocChunkPages - 1, 1}, } - } - tests["PreserveHugePageTop"] = test{ - alloc: []BitRange{{0, PallocChunkPages - bits}}, - min: 1, - max: 1, // Even one page would break a huge page in this case. - want: BitRange{PallocChunkPages - bits, bits}, } } for name, v := range tests { From f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 19 Oct 2020 20:45:01 -0400 Subject: [PATCH 031/403] cmd/go/internal/renameio: include ios in the darwin test-flake mitigation Because the "ios" build constraint implies "darwin", it is already included in the general "darwin" flakiness workaround in cmd/go/internal/robustio. We just need to relax the renameio test to avoid false-positives there. I do not expect this change to drive the rate of false-positives down to zero, but it should at least reduce noise on the build dashboard. For #42066 Change-Id: Ia33dbd33295fce5b3261b4831f2807ce29b82e65 Reviewed-on: https://go-review.googlesource.com/c/go/+/263777 Trust: Bryan C. Mills Reviewed-by: Cherry Zhang Reviewed-by: Dmitri Shuralyov --- src/cmd/go/internal/renameio/renameio_test.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/internal/renameio/renameio_test.go b/src/cmd/go/internal/renameio/renameio_test.go index df8ddabdb82..e6d2025a0e2 100644 --- a/src/cmd/go/internal/renameio/renameio_test.go +++ b/src/cmd/go/internal/renameio/renameio_test.go @@ -144,10 +144,12 @@ func TestConcurrentReadsAndWrites(t *testing.T) { // As long as those are the only errors and *some* of the reads succeed, we're happy. minReadSuccesses = attempts / 4 - case "darwin": - // The filesystem on macOS 10.14 occasionally fails with "no such file or - // directory" errors. See https://golang.org/issue/33041. The flake rate is - // fairly low, so ensure that at least 75% of attempts succeed. + case "darwin", "ios": + // The filesystem on certain versions of macOS (10.14) and iOS (affected + // versions TBD) occasionally fail with "no such file or directory" errors. + // See https://golang.org/issue/33041 and https://golang.org/issue/42066. + // The flake rate is fairly low, so ensure that at least 75% of attempts + // succeed. minReadSuccesses = attempts - (attempts / 4) } From d595712540f00d980b1276ed25495ee7e05c1bfa Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Tue, 20 Oct 2020 09:06:42 -0400 Subject: [PATCH 032/403] cmd/asm: rename "compiling runtime" flag Rename the assembler "-compilingRuntime" flag to "-compiling-runtime", to be more consistent with the flag style of other Go commands. Change-Id: I8cc5cbf0b9b34d1dd4e9fa499d3fec8c1ef10b6e Reviewed-on: https://go-review.googlesource.com/c/go/+/263857 Trust: Than McIntosh Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Austin Clements Reviewed-by: Cherry Zhang --- src/cmd/asm/internal/flags/flags.go | 2 +- src/cmd/dist/build.go | 2 +- src/cmd/go/internal/work/gc.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/asm/internal/flags/flags.go b/src/cmd/asm/internal/flags/flags.go index 07654399591..426e0156aa5 100644 --- a/src/cmd/asm/internal/flags/flags.go +++ b/src/cmd/asm/internal/flags/flags.go @@ -24,7 +24,7 @@ var ( SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble") Importpath = flag.String("p", "", "set expected package import to path") Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)") - CompilingRuntime = flag.Bool("compilingRuntime", false, "source to be compiled is part of the Go runtime") + CompilingRuntime = flag.Bool("compiling-runtime", false, "source to be compiled is part of the Go runtime") ) var ( diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index 11da38ebdf8..d902addb0c1 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -833,7 +833,7 @@ func runInstall(pkg string, ch chan struct{}) { } goasmh := pathf("%s/go_asm.h", workdir) if IsRuntimePackagePath(pkg) { - asmArgs = append(asmArgs, "-compilingRuntime") + asmArgs = append(asmArgs, "-compiling-runtime") if os.Getenv("GOEXPERIMENT") == "regabi" { // In order to make it easier to port runtime assembly // to the register ABI, we introduce a macro diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 2df4a52ba59..e93031431c8 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -293,7 +293,7 @@ func asmArgs(a *Action, p *load.Package) []interface{} { } } if objabi.IsRuntimePackagePath(pkgpath) { - args = append(args, "-compilingRuntime") + args = append(args, "-compiling-runtime") if objabi.Regabi_enabled != 0 { // In order to make it easier to port runtime assembly // to the register ABI, we introduce a macro From 90c924ff88a8b5ab65538ccc16d160922b1b4003 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 10:58:05 -0400 Subject: [PATCH 033/403] testing/fstest: new package for testing file system code This change adds basic test helpers for file system code. The type MapFS is a simple map-based file system for use when exercising general file system code. The func TestFS tests a file system implementation. For #41190. Change-Id: I5a2036f57e733915ad508651ad7317749794423c Reviewed-on: https://go-review.googlesource.com/c/go/+/243910 Trust: Russ Cox Reviewed-by: Rob Pike --- src/go/build/deps_test.go | 3 +- src/testing/fstest/mapfs.go | 204 +++++++++++++++++ src/testing/fstest/mapfs_test.go | 19 ++ src/testing/fstest/testfs.go | 364 +++++++++++++++++++++++++++++++ 4 files changed, 589 insertions(+), 1 deletion(-) create mode 100644 src/testing/fstest/mapfs.go create mode 100644 src/testing/fstest/mapfs_test.go create mode 100644 src/testing/fstest/testfs.go diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 9e72c8f234f..4867a5031ac 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -468,7 +468,8 @@ var depsRules = ` # Test-only log - < testing/iotest; + < testing/iotest + < testing/fstest; FMT, flag, math/rand < testing/quick; diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go new file mode 100644 index 00000000000..84a943f4090 --- /dev/null +++ b/src/testing/fstest/mapfs.go @@ -0,0 +1,204 @@ +// Copyright 2020 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 fstest + +import ( + "io" + "io/fs" + "path" + "sort" + "strings" + "time" +) + +// A MapFS is a simple in-memory file system for use in tests, +// represented as a map from path names (arguments to Open) +// to information about the files or directories they represent. +// +// The map need not include parent directories for files contained +// in the map; those will be synthesized if needed. +// But a directory can still be included by setting the MapFile.Mode's ModeDir bit; +// this may be necessary for detailed control over the directory's FileInfo +// or to create an empty directory. +// +// File system operations read directly from the map, +// so that the file system can be changed by editing the map as needed. +// An implication is that file system operations must not run concurrently +// with changes to the map, which would be a race. +// Another implication is that opening or reading a directory requires +// iterating over the entire map, so a MapFS should typically be used with not more +// than a few hundred entries or directory reads. +type MapFS map[string]*MapFile + +// A MapFile describes a single file in a MapFS. +type MapFile struct { + Data []byte // file content + Mode fs.FileMode // FileInfo.Mode + ModTime time.Time // FileInfo.ModTime + Sys interface{} // FileInfo.Sys +} + +var _ fs.FS = MapFS(nil) +var _ fs.File = (*openMapFile)(nil) + +// Open opens the named file. +func (fsys MapFS) Open(name string) (fs.File, error) { + if !fs.ValidPath(name) { + return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist} + } + file := fsys[name] + if file != nil && file.Mode&fs.ModeDir == 0 { + // Ordinary file + return &openMapFile{name, mapFileInfo{path.Base(name), file}, 0}, nil + } + + // Directory, possibly synthesized. + // Note that file can be nil here: the map need not contain explicit parent directories for all its files. + // But file can also be non-nil, in case the user wants to set metadata for the directory explicitly. + // Either way, we need to construct the list of children of this directory. + var list []mapFileInfo + var elem string + var need = make(map[string]bool) + if name == "." { + elem = "." + for fname, f := range fsys { + i := strings.Index(fname, "/") + if i < 0 { + list = append(list, mapFileInfo{fname, f}) + } else { + need[fname[:i]] = true + } + } + } else { + elem = name[strings.LastIndex(name, "/")+1:] + prefix := name + "/" + for fname, f := range fsys { + if strings.HasPrefix(fname, prefix) { + felem := fname[len(prefix):] + i := strings.Index(felem, "/") + if i < 0 { + list = append(list, mapFileInfo{felem, f}) + } else { + need[fname[len(prefix):len(prefix)+i]] = true + } + } + } + // If the directory name is not in the map, + // and there are no children of the name in the map, + // then the directory is treated as not existing. + if file == nil && list == nil && len(need) == 0 { + return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist} + } + } + for _, fi := range list { + delete(need, fi.name) + } + for name := range need { + list = append(list, mapFileInfo{name, &MapFile{Mode: fs.ModeDir}}) + } + sort.Slice(list, func(i, j int) bool { + return list[i].name < list[j].name + }) + + if file == nil { + file = &MapFile{Mode: fs.ModeDir} + } + return &mapDir{name, mapFileInfo{elem, file}, list, 0}, nil +} + +// A mapFileInfo implements fs.FileInfo and fs.DirEntry for a given map file. +type mapFileInfo struct { + name string + f *MapFile +} + +func (i *mapFileInfo) Name() string { return i.name } +func (i *mapFileInfo) Size() int64 { return int64(len(i.f.Data)) } +func (i *mapFileInfo) Mode() fs.FileMode { return i.f.Mode } +func (i *mapFileInfo) Type() fs.FileMode { return i.f.Mode.Type() } +func (i *mapFileInfo) ModTime() time.Time { return i.f.ModTime } +func (i *mapFileInfo) IsDir() bool { return i.f.Mode&fs.ModeDir != 0 } +func (i *mapFileInfo) Sys() interface{} { return i.f.Sys } +func (i *mapFileInfo) Info() (fs.FileInfo, error) { return i, nil } + +// An openMapFile is a regular (non-directory) fs.File open for reading. +type openMapFile struct { + path string + mapFileInfo + offset int64 +} + +func (f *openMapFile) Stat() (fs.FileInfo, error) { return &f.mapFileInfo, nil } + +func (f *openMapFile) Close() error { return nil } + +func (f *openMapFile) Read(b []byte) (int, error) { + if f.offset >= int64(len(f.f.Data)) { + return 0, io.EOF + } + if f.offset < 0 { + return 0, &fs.PathError{Op: "read", Path: f.path, Err: fs.ErrInvalid} + } + n := copy(b, f.f.Data[f.offset:]) + f.offset += int64(n) + return n, nil +} + +func (f *openMapFile) Seek(offset int64, whence int) (int64, error) { + switch whence { + case 0: + // offset += 0 + case 1: + offset += f.offset + case 2: + offset += int64(len(f.f.Data)) + } + if offset < 0 || offset > int64(len(f.f.Data)) { + return 0, &fs.PathError{Op: "seek", Path: f.path, Err: fs.ErrInvalid} + } + f.offset = offset + return offset, nil +} + +func (f *openMapFile) ReadAt(b []byte, offset int64) (int, error) { + if offset < 0 || offset > int64(len(f.f.Data)) { + return 0, &fs.PathError{Op: "read", Path: f.path, Err: fs.ErrInvalid} + } + n := copy(b, f.f.Data[offset:]) + if n < len(b) { + return n, io.EOF + } + return n, nil +} + +// A mapDir is a directory fs.File (so also an fs.ReadDirFile) open for reading. +type mapDir struct { + path string + mapFileInfo + entry []mapFileInfo + offset int +} + +func (d *mapDir) Stat() (fs.FileInfo, error) { return &d.mapFileInfo, nil } +func (d *mapDir) Close() error { return nil } +func (d *mapDir) Read(b []byte) (int, error) { + return 0, &fs.PathError{Op: "read", Path: d.path, Err: fs.ErrInvalid} +} + +func (d *mapDir) ReadDir(count int) ([]fs.DirEntry, error) { + n := len(d.entry) - d.offset + if count > 0 && n > count { + n = count + } + if n == 0 && count > 0 { + return nil, io.EOF + } + list := make([]fs.DirEntry, n) + for i := range list { + list[i] = &d.entry[d.offset+i] + } + d.offset += n + return list, nil +} diff --git a/src/testing/fstest/mapfs_test.go b/src/testing/fstest/mapfs_test.go new file mode 100644 index 00000000000..2abedd67351 --- /dev/null +++ b/src/testing/fstest/mapfs_test.go @@ -0,0 +1,19 @@ +// Copyright 2020 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 fstest + +import ( + "testing" +) + +func TestMapFS(t *testing.T) { + m := MapFS{ + "hello": {Data: []byte("hello, world\n")}, + "fortune/k/ken.txt": {Data: []byte("If a program is too slow, it must have a loop.\n")}, + } + if err := TestFS(m, "hello", "fortune/k/ken.txt"); err != nil { + t.Fatal(err) + } +} diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go new file mode 100644 index 00000000000..2bb2120c195 --- /dev/null +++ b/src/testing/fstest/testfs.go @@ -0,0 +1,364 @@ +// Copyright 2020 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 fstest implements support for testing implementations and users of file systems. +package fstest + +import ( + "errors" + "fmt" + "io" + "io/fs" + "io/ioutil" + "sort" + "strings" + "testing/iotest" +) + +// TestFS tests a file system implementation. +// It walks the entire tree of files in fsys, +// opening and checking that each file behaves correctly. +// It also checks that the file system contains at least the expected files. +// +// If TestFS finds any misbehaviors, it returns an error reporting all of them. +// The error text spans multiple lines, one per detected misbehavior. +// +// Typical usage inside a test is: +// +// if err := fstest.TestFS(myFS, "file/that/should/be/present"); err != nil { +// t.Fatal(err) +// } +// +func TestFS(fsys fs.FS, expected ...string) error { + t := fsTester{fsys: fsys} + t.checkDir(".") + t.checkOpen(".") + found := make(map[string]bool) + for _, dir := range t.dirs { + found[dir] = true + } + for _, file := range t.files { + found[file] = true + } + for _, name := range expected { + if !found[name] { + t.errorf("expected but not found: %s", name) + } + } + if len(t.errText) == 0 { + return nil + } + return errors.New("TestFS found errors:\n" + string(t.errText)) +} + +// An fsTester holds state for running the test. +type fsTester struct { + fsys fs.FS + errText []byte + dirs []string + files []string +} + +// errorf adds an error line to errText. +func (t *fsTester) errorf(format string, args ...interface{}) { + if len(t.errText) > 0 { + t.errText = append(t.errText, '\n') + } + t.errText = append(t.errText, fmt.Sprintf(format, args...)...) +} + +func (t *fsTester) openDir(dir string) fs.ReadDirFile { + f, err := t.fsys.Open(dir) + if err != nil { + t.errorf("%s: Open: %v", dir, err) + return nil + } + d, ok := f.(fs.ReadDirFile) + if !ok { + f.Close() + t.errorf("%s: Open returned File type %T, not a io.ReadDirFile", dir, f) + return nil + } + return d +} + +// checkDir checks the directory dir, which is expected to exist +// (it is either the root or was found in a directory listing with IsDir true). +func (t *fsTester) checkDir(dir string) { + // Read entire directory. + t.dirs = append(t.dirs, dir) + d := t.openDir(dir) + if d == nil { + return + } + list, err := d.ReadDir(-1) + if err != nil { + d.Close() + t.errorf("%s: ReadDir(-1): %v", dir, err) + return + } + + // Check all children. + var prefix string + if dir == "." { + prefix = "" + } else { + prefix = dir + "/" + } + for _, info := range list { + name := info.Name() + switch { + case name == ".", name == "..", name == "": + t.errorf("%s: ReadDir: child has invalid name: %#q", dir, name) + continue + case strings.Contains(name, "/"): + t.errorf("%s: ReadDir: child name contains slash: %#q", dir, name) + continue + case strings.Contains(name, `\`): + t.errorf("%s: ReadDir: child name contains backslash: %#q", dir, name) + continue + } + path := prefix + name + t.checkStat(path, info) + t.checkOpen(path) + if info.IsDir() { + t.checkDir(path) + } else { + t.checkFile(path) + } + } + + // Check ReadDir(-1) at EOF. + list2, err := d.ReadDir(-1) + if len(list2) > 0 || err != nil { + d.Close() + t.errorf("%s: ReadDir(-1) at EOF = %d entries, %v, wanted 0 entries, nil", dir, len(list2), err) + return + } + + // Check ReadDir(1) at EOF (different results). + list2, err = d.ReadDir(1) + if len(list2) > 0 || err != io.EOF { + d.Close() + t.errorf("%s: ReadDir(1) at EOF = %d entries, %v, wanted 0 entries, EOF", dir, len(list2), err) + return + } + + // Check that close does not report an error. + if err := d.Close(); err != nil { + t.errorf("%s: Close: %v", dir, err) + } + + // Check that closing twice doesn't crash. + // The return value doesn't matter. + d.Close() + + // Reopen directory, read a second time, make sure contents match. + if d = t.openDir(dir); d == nil { + return + } + defer d.Close() + list2, err = d.ReadDir(-1) + if err != nil { + t.errorf("%s: second Open+ReadDir(-1): %v", dir, err) + return + } + t.checkDirList(dir, "first Open+ReadDir(-1) vs second Open+ReadDir(-1)", list, list2) + + // Reopen directory, read a third time in pieces, make sure contents match. + if d = t.openDir(dir); d == nil { + return + } + defer d.Close() + list2 = nil + for { + n := 1 + if len(list2) > 0 { + n = 2 + } + frag, err := d.ReadDir(n) + if len(frag) > n { + t.errorf("%s: third Open: ReadDir(%d) after %d: %d entries (too many)", dir, n, len(list2), len(frag)) + return + } + list2 = append(list2, frag...) + if err == io.EOF { + break + } + if err != nil { + t.errorf("%s: third Open: ReadDir(%d) after %d: %v", dir, n, len(list2), err) + return + } + if n == 0 { + t.errorf("%s: third Open: ReadDir(%d) after %d: 0 entries but nil error", dir, n, len(list2)) + return + } + } + t.checkDirList(dir, "first Open+ReadDir(-1) vs third Open+ReadDir(1,2) loop", list, list2) +} + +// formatEntry formats an fs.DirEntry into a string for error messages and comparison. +func formatEntry(entry fs.DirEntry) string { + return fmt.Sprintf("%s IsDir=%v Type=%v", entry.Name(), entry.IsDir(), entry.Type()) +} + +// formatInfoEntry formats an fs.FileInfo into a string like the result of formatEntry, for error messages and comparison. +func formatInfoEntry(info fs.FileInfo) string { + return fmt.Sprintf("%s IsDir=%v Type=%v", info.Name(), info.IsDir(), info.Mode().Type()) +} + +// formatInfo formats an fs.FileInfo into a string for error messages and comparison. +func formatInfo(info fs.FileInfo) string { + return fmt.Sprintf("%s IsDir=%v Mode=%v Size=%d ModTime=%v", info.Name(), info.IsDir(), info.Mode(), info.Size(), info.ModTime()) +} + +// checkStat checks that a direct stat of path matches entry, +// which was found in the parent's directory listing. +func (t *fsTester) checkStat(path string, entry fs.DirEntry) { + file, err := t.fsys.Open(path) + if err != nil { + t.errorf("%s: Open: %v", path, err) + return + } + info, err := file.Stat() + file.Close() + if err != nil { + t.errorf("%s: Stat: %v", path, err) + return + } + fentry := formatEntry(entry) + finfo := formatInfoEntry(info) + if fentry != finfo { + t.errorf("%s: mismatch:\n\tentry = %v\n\tfile.Stat() = %v", path, fentry, finfo) + } +} + +// checkDirList checks that two directory lists contain the same files and file info. +// The order of the lists need not match. +func (t *fsTester) checkDirList(dir, desc string, list1, list2 []fs.DirEntry) { + old := make(map[string]fs.DirEntry) + checkMode := func(entry fs.DirEntry) { + if entry.IsDir() != (entry.Type()&fs.ModeDir != 0) { + if entry.IsDir() { + t.errorf("%s: ReadDir returned %s with IsDir() = true, Type() & ModeDir = 0", dir, entry.Name()) + } else { + t.errorf("%s: ReadDir returned %s with IsDir() = false, Type() & ModeDir = ModeDir", dir, entry.Name()) + } + } + } + + for _, entry1 := range list1 { + old[entry1.Name()] = entry1 + checkMode(entry1) + } + + var diffs []string + for _, entry2 := range list2 { + entry1 := old[entry2.Name()] + if entry1 == nil { + checkMode(entry2) + diffs = append(diffs, "+ "+formatEntry(entry2)) + continue + } + if formatEntry(entry1) != formatEntry(entry2) { + diffs = append(diffs, "- "+formatEntry(entry1), "+ "+formatEntry(entry2)) + } + delete(old, entry2.Name()) + } + for _, entry1 := range old { + diffs = append(diffs, "- "+formatEntry(entry1)) + } + + if len(diffs) == 0 { + return + } + + sort.Slice(diffs, func(i, j int) bool { + fi := strings.Fields(diffs[i]) + fj := strings.Fields(diffs[j]) + // sort by name (i < j) and then +/- (j < i, because + < -) + return fi[1]+" "+fj[0] < fj[1]+" "+fi[0] + }) + + t.errorf("%s: diff %s:\n\t%s", dir, desc, strings.Join(diffs, "\n\t")) +} + +// checkFile checks that basic file reading works correctly. +func (t *fsTester) checkFile(file string) { + t.files = append(t.files, file) + + // Read entire file. + f, err := t.fsys.Open(file) + if err != nil { + t.errorf("%s: Open: %v", file, err) + return + } + + data, err := ioutil.ReadAll(f) + if err != nil { + f.Close() + t.errorf("%s: Open+ReadAll: %v", file, err) + return + } + + if err := f.Close(); err != nil { + t.errorf("%s: Close: %v", file, err) + } + + // Check that closing twice doesn't crash. + // The return value doesn't matter. + f.Close() + + // Use iotest.TestReader to check small reads, Seek, ReadAt. + f, err = t.fsys.Open(file) + if err != nil { + t.errorf("%s: second Open: %v", file, err) + return + } + defer f.Close() + if err := iotest.TestReader(f, data); err != nil { + t.errorf("%s: failed TestReader:\n\t%s", file, strings.ReplaceAll(err.Error(), "\n", "\n\t")) + } +} + +func (t *fsTester) checkFileRead(file, desc string, data1, data2 []byte) { + if string(data1) != string(data2) { + t.errorf("%s: %s: different data returned\n\t%q\n\t%q", file, desc, data1, data2) + return + } +} + +// checkOpen checks that various invalid forms of file's name cannot be opened. +func (t *fsTester) checkOpen(file string) { + bad := []string{ + "/" + file, + file + "/.", + } + if file == "." { + bad = append(bad, "/") + } + if i := strings.Index(file, "/"); i >= 0 { + bad = append(bad, + file[:i]+"//"+file[i+1:], + file[:i]+"/./"+file[i+1:], + file[:i]+`\`+file[i+1:], + file[:i]+"/../"+file, + ) + } + if i := strings.LastIndex(file, "/"); i >= 0 { + bad = append(bad, + file[:i]+"//"+file[i+1:], + file[:i]+"/./"+file[i+1:], + file[:i]+`\`+file[i+1:], + file+"/../"+file[i+1:], + ) + } + + for _, b := range bad { + if f, err := t.fsys.Open(b); err == nil { + f.Close() + t.errorf("%s: Open(%s) succeeded, want error", file, b) + } + } +} From b1f76f7a220a806d74bf55da374ea89467753e1f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 11:27:38 -0400 Subject: [PATCH 034/403] os: add DirFS It will inevitably be important to be able to pass an operating system directory to code written to expect an fs.FS. os.DirFS provides the conversion. For #41190. Change-Id: Id1a8fcbe4c7a30de2c47dea0504e9481a88b1b39 Reviewed-on: https://go-review.googlesource.com/c/go/+/243911 Trust: Russ Cox Reviewed-by: Rob Pike --- src/os/file.go | 19 +++++++++++++++++++ src/os/os_test.go | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/src/os/file.go b/src/os/file.go index 5f16fc28eea..835d44ab8c4 100644 --- a/src/os/file.go +++ b/src/os/file.go @@ -45,6 +45,7 @@ import ( "internal/poll" "internal/testlog" "io" + "io/fs" "runtime" "syscall" "time" @@ -608,3 +609,21 @@ func isWindowsNulName(name string) bool { } return true } + +// DirFS returns a file system (an fs.FS) for the tree of files rooted at the directory dir. +func DirFS(dir string) fs.FS { + return dirFS(dir) +} + +type dirFS string + +func (dir dirFS) Open(name string) (fs.File, error) { + if !fs.ValidPath(name) { + return nil, &PathError{Op: "open", Path: name, Err: ErrInvalid} + } + f, err := Open(string(dir) + "/" + name) + if err != nil { + return nil, err // nil fs.File + } + return f, nil +} diff --git a/src/os/os_test.go b/src/os/os_test.go index 8f14263401d..378ddf58dd4 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -23,6 +23,7 @@ import ( "sync" "syscall" "testing" + "testing/fstest" "time" ) @@ -2671,3 +2672,9 @@ func TestOpenFileKeepsPermissions(t *testing.T) { t.Errorf("Stat after OpenFile is %v, should be writable", fi.Mode()) } } + +func TestDirFS(t *testing.T) { + if err := fstest.TestFS(DirFS("./signal"), "signal.go", "internal/pty/pty.go"); err != nil { + t.Fatal(err) + } +} From f098ccf04a33e2e4d2dffa2e90fe77ca8a0fcbb4 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 11:26:26 -0400 Subject: [PATCH 035/403] io/fs: add ReadFile and ReadFileFS Add ReadFile helper function, ReadFileFS interface, and test. Add ReadFile method to fstest.MapFS. Add testing of ReadFile method to fstest.TestFS. For #41190. Change-Id: I5b6a41e2e582824e570463b698b635abaa436c32 Reviewed-on: https://go-review.googlesource.com/c/go/+/243912 Trust: Russ Cox Reviewed-by: Rob Pike --- src/go/build/deps_test.go | 4 ++- src/io/fs/readfile.go | 63 ++++++++++++++++++++++++++++++++++++ src/io/fs/readfile_test.go | 43 ++++++++++++++++++++++++ src/testing/fstest/mapfs.go | 12 +++++++ src/testing/fstest/testfs.go | 39 +++++++++++++++++++--- 5 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 src/io/fs/readfile.go create mode 100644 src/io/fs/readfile_test.go diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 4867a5031ac..ccee5390864 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -165,7 +165,9 @@ var depsRules = ` os/signal, STR < path/filepath - < io/ioutil, os/exec + < io/ioutil, os/exec; + + io/ioutil, os/exec, os/signal < OS; reflect !< OS; diff --git a/src/io/fs/readfile.go b/src/io/fs/readfile.go new file mode 100644 index 00000000000..7ee9eadac4d --- /dev/null +++ b/src/io/fs/readfile.go @@ -0,0 +1,63 @@ +// Copyright 2020 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 fs + +import "io" + +// ReadFileFS is the interface implemented by a file system +// that provides an optimized implementation of ReadFile. +type ReadFileFS interface { + FS + + // ReadFile reads the named file and returns its contents. + // A successful call returns a nil error, not io.EOF. + // (Because ReadFile reads the whole file, the expected EOF + // from the final Read is not treated as an error to be reported.) + ReadFile(name string) ([]byte, error) +} + +// ReadFile reads the named file from the file system fs and returns its contents. +// A successful call returns a nil error, not io.EOF. +// (Because ReadFile reads the whole file, the expected EOF +// from the final Read is not treated as an error to be reported.) +// +// If fs implements ReadFileFS, ReadFile calls fs.ReadFile. +// Otherwise ReadFile calls fs.Open and uses Read and Close +// on the returned file. +func ReadFile(fsys FS, name string) ([]byte, error) { + if fsys, ok := fsys.(ReadFileFS); ok { + return fsys.ReadFile(name) + } + + file, err := fsys.Open(name) + if err != nil { + return nil, err + } + defer file.Close() + + var size int + if info, err := file.Stat(); err == nil { + size64 := info.Size() + if int64(int(size64)) == size64 { + size = int(size64) + } + } + + data := make([]byte, 0, size+1) + for { + if len(data) >= cap(data) { + d := append(data[:cap(data)], 0) + data = d[:len(data)] + } + n, err := file.Read(data[len(data):cap(data)]) + data = data[:len(data)+n] + if err != nil { + if err == io.EOF { + err = nil + } + return data, err + } + } +} diff --git a/src/io/fs/readfile_test.go b/src/io/fs/readfile_test.go new file mode 100644 index 00000000000..0afa334acea --- /dev/null +++ b/src/io/fs/readfile_test.go @@ -0,0 +1,43 @@ +// Copyright 2020 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 fs_test + +import ( + . "io/fs" + "testing" + "testing/fstest" + "time" +) + +var testFsys = fstest.MapFS{ + "hello.txt": { + Data: []byte("hello, world"), + Mode: 0456, + ModTime: time.Now(), + Sys: &sysValue, + }, +} + +var sysValue int + +type readFileOnly struct{ ReadFileFS } + +func (readFileOnly) Open(name string) (File, error) { return nil, ErrNotExist } + +type openOnly struct{ FS } + +func TestReadFile(t *testing.T) { + // Test that ReadFile uses the method when present. + data, err := ReadFile(readFileOnly{testFsys}, "hello.txt") + if string(data) != "hello, world" || err != nil { + t.Fatalf(`ReadFile(readFileOnly, "hello.txt") = %q, %v, want %q, nil`, data, err, "hello, world") + } + + // Test that ReadFile uses Open when the method is not present. + data, err = ReadFile(openOnly{testFsys}, "hello.txt") + if string(data) != "hello, world" || err != nil { + t.Fatalf(`ReadFile(openOnly, "hello.txt") = %q, %v, want %q, nil`, data, err, "hello, world") + } +} diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go index 84a943f4090..e969ac2bd14 100644 --- a/src/testing/fstest/mapfs.go +++ b/src/testing/fstest/mapfs.go @@ -108,6 +108,18 @@ func (fsys MapFS) Open(name string) (fs.File, error) { return &mapDir{name, mapFileInfo{elem, file}, list, 0}, nil } +// fsOnly is a wrapper that hides all but the fs.FS methods, +// to avoid an infinite recursion when implementing special +// methods in terms of helpers that would use them. +// (In general, implementing these methods using the package fs helpers +// is redundant and unnecessary, but having the methods may make +// MapFS exercise more code paths when used in tests.) +type fsOnly struct{ fs.FS } + +func (fsys MapFS) ReadFile(name string) ([]byte, error) { + return fs.ReadFile(fsOnly{fsys}, name) +} + // A mapFileInfo implements fs.FileInfo and fs.DirEntry for a given map file. type mapFileInfo struct { name string diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 2bb2120c195..66725ca2a43 100644 --- a/src/testing/fstest/testfs.go +++ b/src/testing/fstest/testfs.go @@ -310,6 +310,27 @@ func (t *fsTester) checkFile(file string) { // The return value doesn't matter. f.Close() + // Check that ReadFile works if present. + if fsys, ok := t.fsys.(fs.ReadFileFS); ok { + data2, err := fsys.ReadFile(file) + if err != nil { + t.errorf("%s: fsys.ReadFile: %v", file, err) + return + } + t.checkFileRead(file, "ReadAll vs fsys.ReadFile", data, data2) + + t.checkBadPath(file, "ReadFile", + func(name string) error { _, err := fsys.ReadFile(name); return err }) + } + + // Check that fs.ReadFile works with t.fsys. + data2, err := fs.ReadFile(t.fsys, file) + if err != nil { + t.errorf("%s: fs.ReadFile: %v", file, err) + return + } + t.checkFileRead(file, "ReadAll vs fs.ReadFile", data, data2) + // Use iotest.TestReader to check small reads, Seek, ReadAt. f, err = t.fsys.Open(file) if err != nil { @@ -329,8 +350,19 @@ func (t *fsTester) checkFileRead(file, desc string, data1, data2 []byte) { } } -// checkOpen checks that various invalid forms of file's name cannot be opened. +// checkBadPath checks that various invalid forms of file's name cannot be opened using t.fsys.Open. func (t *fsTester) checkOpen(file string) { + t.checkBadPath(file, "Open", func(file string) error { + f, err := t.fsys.Open(file) + if err == nil { + f.Close() + } + return err + }) +} + +// checkBadPath checks that various invalid forms of file's name cannot be opened using open. +func (t *fsTester) checkBadPath(file string, desc string, open func(string) error) { bad := []string{ "/" + file, file + "/.", @@ -356,9 +388,8 @@ func (t *fsTester) checkOpen(file string) { } for _, b := range bad { - if f, err := t.fsys.Open(b); err == nil { - f.Close() - t.errorf("%s: Open(%s) succeeded, want error", file, b) + if err := open(b); err == nil { + t.errorf("%s: %s(%s) succeeded, want error", file, desc, b) } } } From 10a1a1a37c007adef8425d273e6b276547982889 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 11:26:45 -0400 Subject: [PATCH 036/403] io/fs: add Stat and StatFS Add Stat helper function, StatFS interface, and test. Add Stat method to fstest.MapFS. Add testing of Stat method to fstest.TestFS. For #41190. Change-Id: Icf8b6eb1c3fa6f93a9be8405ec5a9468fb1da97b Reviewed-on: https://go-review.googlesource.com/c/go/+/243913 Trust: Russ Cox Reviewed-by: Rob Pike --- src/io/fs/stat.go | 31 +++++++++++++++++++++++++++++++ src/io/fs/stat_test.go | 36 ++++++++++++++++++++++++++++++++++++ src/testing/fstest/mapfs.go | 4 ++++ src/testing/fstest/testfs.go | 25 ++++++++++++++++++++++++- 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/io/fs/stat.go create mode 100644 src/io/fs/stat_test.go diff --git a/src/io/fs/stat.go b/src/io/fs/stat.go new file mode 100644 index 00000000000..735a6e3281c --- /dev/null +++ b/src/io/fs/stat.go @@ -0,0 +1,31 @@ +// Copyright 2020 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 fs + +// A StatFS is a file system with a Stat method. +type StatFS interface { + FS + + // Stat returns a FileInfo describing the file. + // If there is an error, it should be of type *PathError. + Stat(name string) (FileInfo, error) +} + +// Stat returns a FileInfo describing the named file from the file system. +// +// If fs implements StatFS, Stat calls fs.Stat. +// Otherwise, Stat opens the file to stat it. +func Stat(fsys FS, name string) (FileInfo, error) { + if fsys, ok := fsys.(StatFS); ok { + return fsys.Stat(name) + } + + file, err := fsys.Open(name) + if err != nil { + return nil, err + } + defer file.Close() + return file.Stat() +} diff --git a/src/io/fs/stat_test.go b/src/io/fs/stat_test.go new file mode 100644 index 00000000000..e312b6fbd91 --- /dev/null +++ b/src/io/fs/stat_test.go @@ -0,0 +1,36 @@ +// Copyright 2020 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 fs_test + +import ( + "fmt" + . "io/fs" + "testing" +) + +type statOnly struct{ StatFS } + +func (statOnly) Open(name string) (File, error) { return nil, ErrNotExist } + +func TestStat(t *testing.T) { + check := func(desc string, info FileInfo, err error) { + t.Helper() + if err != nil || info == nil || info.Mode() != 0456 { + infoStr := "" + if info != nil { + infoStr = fmt.Sprintf("FileInfo(Mode: %#o)", info.Mode()) + } + t.Fatalf("Stat(%s) = %v, %v, want Mode:0456, nil", desc, infoStr, err) + } + } + + // Test that Stat uses the method when present. + info, err := Stat(statOnly{testFsys}, "hello.txt") + check("statOnly", info, err) + + // Test that Stat uses Open when the method is not present. + info, err = Stat(openOnly{testFsys}, "hello.txt") + check("openOnly", info, err) +} diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go index e969ac2bd14..b01911e5894 100644 --- a/src/testing/fstest/mapfs.go +++ b/src/testing/fstest/mapfs.go @@ -120,6 +120,10 @@ func (fsys MapFS) ReadFile(name string) ([]byte, error) { return fs.ReadFile(fsOnly{fsys}, name) } +func (fsys MapFS) Stat(name string) (fs.FileInfo, error) { + return fs.Stat(fsOnly{fsys}, name) +} + // A mapFileInfo implements fs.FileInfo and fs.DirEntry for a given map file. type mapFileInfo struct { name string diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 66725ca2a43..290d2596cc3 100644 --- a/src/testing/fstest/testfs.go +++ b/src/testing/fstest/testfs.go @@ -230,7 +230,30 @@ func (t *fsTester) checkStat(path string, entry fs.DirEntry) { fentry := formatEntry(entry) finfo := formatInfoEntry(info) if fentry != finfo { - t.errorf("%s: mismatch:\n\tentry = %v\n\tfile.Stat() = %v", path, fentry, finfo) + t.errorf("%s: mismatch:\n\tentry = %s\n\tfile.Stat() = %s", path, fentry, finfo) + } + + info2, err := fs.Stat(t.fsys, path) + if err != nil { + t.errorf("%s: fs.Stat: %v", path, err) + return + } + finfo = formatInfo(info) + finfo2 := formatInfo(info2) + if finfo2 != finfo { + t.errorf("%s: fs.Stat(...) = %s\n\twant %s", path, finfo2, finfo) + } + + if fsys, ok := t.fsys.(fs.StatFS); ok { + info2, err := fsys.Stat(path) + if err != nil { + t.errorf("%s: fsys.Stat: %v", path, err) + return + } + finfo2 := formatInfo(info2) + if finfo2 != finfo { + t.errorf("%s: fsys.Stat(...) = %s\n\twant %s", path, finfo2, finfo) + } } } From 7a131acfd142f0fc7612365078b9f00e371fc0e2 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 11:26:56 -0400 Subject: [PATCH 037/403] io/fs: add ReadDir and ReadDirFS Add ReadDir helper function, ReadDirFS interface, and test. Add ReadDir method to fstest.MapFS. Add testing of ReadDir method to fstest.TestFS. For #41190. Change-Id: Ib860770ec7433ba77b29e626682b238f1b3bf54f Reviewed-on: https://go-review.googlesource.com/c/go/+/243914 Trust: Russ Cox Reviewed-by: Rob Pike --- src/io/fs/readdir.go | 47 ++++++++++++++++++++++++++++++++++++ src/io/fs/readdir_test.go | 35 +++++++++++++++++++++++++++ src/testing/fstest/mapfs.go | 4 +++ src/testing/fstest/testfs.go | 42 +++++++++++++++++++++++++++++++- 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/io/fs/readdir.go create mode 100644 src/io/fs/readdir_test.go diff --git a/src/io/fs/readdir.go b/src/io/fs/readdir.go new file mode 100644 index 00000000000..3a5aa6d86a6 --- /dev/null +++ b/src/io/fs/readdir.go @@ -0,0 +1,47 @@ +// Copyright 2020 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 fs + +import ( + "errors" + "sort" +) + +// ReadDirFS is the interface implemented by a file system +// that provides an optimized implementation of ReadDir. +type ReadDirFS interface { + FS + + // ReadDir reads the named directory + // and returns a list of directory entries sorted by filename. + ReadDir(name string) ([]DirEntry, error) +} + +// ReadDir reads the named directory +// and returns a list of directory entries sorted by filename. +// +// If fs implements ReadDirFS, ReadDir calls fs.ReadDir. +// Otherwise ReadDir calls fs.Open and uses ReadDir and Close +// on the returned file. +func ReadDir(fsys FS, name string) ([]DirEntry, error) { + if fsys, ok := fsys.(ReadDirFS); ok { + return fsys.ReadDir(name) + } + + file, err := fsys.Open(name) + if err != nil { + return nil, err + } + defer file.Close() + + dir, ok := file.(ReadDirFile) + if !ok { + return nil, &PathError{Op: "readdir", Path: name, Err: errors.New("not implemented")} + } + + list, err := dir.ReadDir(-1) + sort.Slice(list, func(i, j int) bool { return list[i].Name() < list[j].Name() }) + return list, err +} diff --git a/src/io/fs/readdir_test.go b/src/io/fs/readdir_test.go new file mode 100644 index 00000000000..46a4bc27889 --- /dev/null +++ b/src/io/fs/readdir_test.go @@ -0,0 +1,35 @@ +// Copyright 2020 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 fs_test + +import ( + . "io/fs" + "testing" +) + +type readDirOnly struct{ ReadDirFS } + +func (readDirOnly) Open(name string) (File, error) { return nil, ErrNotExist } + +func TestReadDir(t *testing.T) { + check := func(desc string, dirs []DirEntry, err error) { + t.Helper() + if err != nil || len(dirs) != 1 || dirs[0].Name() != "hello.txt" { + var names []string + for _, d := range dirs { + names = append(names, d.Name()) + } + t.Errorf("ReadDir(%s) = %v, %v, want %v, nil", desc, names, err, []string{"hello.txt"}) + } + } + + // Test that ReadDir uses the method when present. + dirs, err := ReadDir(readDirOnly{testFsys}, ".") + check("readDirOnly", dirs, err) + + // Test that ReadDir uses Open when the method is not present. + dirs, err = ReadDir(openOnly{testFsys}, ".") + check("openOnly", dirs, err) +} diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go index b01911e5894..1eaf8f0040f 100644 --- a/src/testing/fstest/mapfs.go +++ b/src/testing/fstest/mapfs.go @@ -124,6 +124,10 @@ func (fsys MapFS) Stat(name string) (fs.FileInfo, error) { return fs.Stat(fsOnly{fsys}, name) } +func (fsys MapFS) ReadDir(name string) ([]fs.DirEntry, error) { + return fs.ReadDir(fsOnly{fsys}, name) +} + // A mapFileInfo implements fs.FileInfo and fs.DirEntry for a given map file. type mapFileInfo struct { name string diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 290d2596cc3..4ea6ed60959 100644 --- a/src/testing/fstest/testfs.go +++ b/src/testing/fstest/testfs.go @@ -196,6 +196,36 @@ func (t *fsTester) checkDir(dir string) { } } t.checkDirList(dir, "first Open+ReadDir(-1) vs third Open+ReadDir(1,2) loop", list, list2) + + // If fsys has ReadDir, check that it matches and is sorted. + if fsys, ok := t.fsys.(fs.ReadDirFS); ok { + list2, err := fsys.ReadDir(dir) + if err != nil { + t.errorf("%s: fsys.ReadDir: %v", dir, err) + return + } + t.checkDirList(dir, "first Open+ReadDir(-1) vs fsys.ReadDir", list, list2) + + for i := 0; i+1 < len(list2); i++ { + if list2[i].Name() >= list2[i+1].Name() { + t.errorf("%s: fsys.ReadDir: list not sorted: %s before %s", dir, list2[i].Name(), list2[i+1].Name()) + } + } + } + + // Check fs.ReadDir as well. + list2, err = fs.ReadDir(t.fsys, dir) + if err != nil { + t.errorf("%s: fs.ReadDir: %v", dir, err) + return + } + t.checkDirList(dir, "first Open+ReadDir(-1) vs fs.ReadDir", list, list2) + + for i := 0; i+1 < len(list2); i++ { + if list2[i].Name() >= list2[i+1].Name() { + t.errorf("%s: fs.ReadDir: list not sorted: %s before %s", dir, list2[i].Name(), list2[i+1].Name()) + } + } } // formatEntry formats an fs.DirEntry into a string for error messages and comparison. @@ -233,12 +263,22 @@ func (t *fsTester) checkStat(path string, entry fs.DirEntry) { t.errorf("%s: mismatch:\n\tentry = %s\n\tfile.Stat() = %s", path, fentry, finfo) } + einfo, err := entry.Info() + if err != nil { + t.errorf("%s: entry.Info: %v", path, err) + return + } + fentry = formatInfo(einfo) + finfo = formatInfo(info) + if fentry != finfo { + t.errorf("%s: mismatch:\n\tentry.Info() = %s\n\tfile.Stat() = %s\n", path, fentry, finfo) + } + info2, err := fs.Stat(t.fsys, path) if err != nil { t.errorf("%s: fs.Stat: %v", path, err) return } - finfo = formatInfo(info) finfo2 := formatInfo(info2) if finfo2 != finfo { t.errorf("%s: fs.Stat(...) = %s\n\twant %s", path, finfo2, finfo) From b64202bc29b9c1cf0118878d1c0acc9cdb2308f6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 11:27:12 -0400 Subject: [PATCH 038/403] io/fs: add Glob and GlobFS Add Glob helper function, GlobFS interface, and test. Add Glob method to fstest.MapFS. Add testing of Glob method to fstest.TestFS. For #41190. Change-Id: If89dd7f63e310ba5ca2651340267a9ff39fcc0c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/243915 Trust: Russ Cox Reviewed-by: Rob Pike --- src/go/build/deps_test.go | 2 +- src/io/fs/glob.go | 116 +++++++++++++++++++++++++++++++++++ src/io/fs/glob_test.go | 82 +++++++++++++++++++++++++ src/testing/fstest/mapfs.go | 4 ++ src/testing/fstest/testfs.go | 96 +++++++++++++++++++++++++++++ 5 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 src/io/fs/glob.go create mode 100644 src/io/fs/glob_test.go diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index ccee5390864..16a67791cf1 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -123,7 +123,7 @@ var depsRules = ` < context < TIME; - TIME, io, sort + TIME, io, path, sort < io/fs; # MATH is RUNTIME plus the basic math packages. diff --git a/src/io/fs/glob.go b/src/io/fs/glob.go new file mode 100644 index 00000000000..77f6ebbaaf1 --- /dev/null +++ b/src/io/fs/glob.go @@ -0,0 +1,116 @@ +// Copyright 2010 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 fs + +import ( + "path" + "runtime" +) + +// A GlobFS is a file system with a Glob method. +type GlobFS interface { + FS + + // Glob returns the names of all files matching pattern, + // providing an implementation of the top-level + // Glob function. + Glob(pattern string) ([]string, error) +} + +// Glob returns the names of all files matching pattern or nil +// if there is no matching file. The syntax of patterns is the same +// as in path.Match. The pattern may describe hierarchical names such as +// /usr/*/bin/ed (assuming the Separator is '/'). +// +// Glob ignores file system errors such as I/O errors reading directories. +// The only possible returned error is path.ErrBadPattern, reporting that +// the pattern is malformed. +// +// If fs implements GlobFS, Glob calls fs.Glob. +// Otherwise, Glob uses ReadDir to traverse the directory tree +// and look for matches for the pattern. +func Glob(fsys FS, pattern string) (matches []string, err error) { + if fsys, ok := fsys.(GlobFS); ok { + return fsys.Glob(pattern) + } + + if !hasMeta(pattern) { + if _, err = Stat(fsys, pattern); err != nil { + return nil, nil + } + return []string{pattern}, nil + } + + dir, file := path.Split(pattern) + dir = cleanGlobPath(dir) + + if !hasMeta(dir) { + return glob(fsys, dir, file, nil) + } + + // Prevent infinite recursion. See issue 15879. + if dir == pattern { + return nil, path.ErrBadPattern + } + + var m []string + m, err = Glob(fsys, dir) + if err != nil { + return + } + for _, d := range m { + matches, err = glob(fsys, d, file, matches) + if err != nil { + return + } + } + return +} + +// cleanGlobPath prepares path for glob matching. +func cleanGlobPath(path string) string { + switch path { + case "": + return "." + default: + return path[0 : len(path)-1] // chop off trailing separator + } +} + +// glob searches for files matching pattern in the directory dir +// and appends them to matches, returning the updated slice. +// If the directory cannot be opened, glob returns the existing matches. +// New matches are added in lexicographical order. +func glob(fs FS, dir, pattern string, matches []string) (m []string, e error) { + m = matches + infos, err := ReadDir(fs, dir) + if err != nil { + return // ignore I/O error + } + + for _, info := range infos { + n := info.Name() + matched, err := path.Match(pattern, n) + if err != nil { + return m, err + } + if matched { + m = append(m, path.Join(dir, n)) + } + } + return +} + +// hasMeta reports whether path contains any of the magic characters +// recognized by path.Match. +func hasMeta(path string) bool { + for i := 0; i < len(path); i++ { + c := path[i] + if c == '*' || c == '?' || c == '[' || runtime.GOOS == "windows" && c == '\\' { + return true + } + } + return false +} diff --git a/src/io/fs/glob_test.go b/src/io/fs/glob_test.go new file mode 100644 index 00000000000..0183a49b6cf --- /dev/null +++ b/src/io/fs/glob_test.go @@ -0,0 +1,82 @@ +// Copyright 2009 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 fs_test + +import ( + . "io/fs" + "os" + "testing" +) + +var globTests = []struct { + fs FS + pattern, result string +}{ + {os.DirFS("."), "glob.go", "glob.go"}, + {os.DirFS("."), "gl?b.go", "glob.go"}, + {os.DirFS("."), "*", "glob.go"}, + {os.DirFS(".."), "*/glob.go", "fs/glob.go"}, +} + +func TestGlob(t *testing.T) { + for _, tt := range globTests { + matches, err := Glob(tt.fs, tt.pattern) + if err != nil { + t.Errorf("Glob error for %q: %s", tt.pattern, err) + continue + } + if !contains(matches, tt.result) { + t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result) + } + } + for _, pattern := range []string{"no_match", "../*/no_match"} { + matches, err := Glob(os.DirFS("."), pattern) + if err != nil { + t.Errorf("Glob error for %q: %s", pattern, err) + continue + } + if len(matches) != 0 { + t.Errorf("Glob(%#q) = %#v want []", pattern, matches) + } + } +} + +func TestGlobError(t *testing.T) { + _, err := Glob(os.DirFS("."), "[]") + if err == nil { + t.Error("expected error for bad pattern; got none") + } +} + +// contains reports whether vector contains the string s. +func contains(vector []string, s string) bool { + for _, elem := range vector { + if elem == s { + return true + } + } + return false +} + +type globOnly struct{ GlobFS } + +func (globOnly) Open(name string) (File, error) { return nil, ErrNotExist } + +func TestGlobMethod(t *testing.T) { + check := func(desc string, names []string, err error) { + t.Helper() + if err != nil || len(names) != 1 || names[0] != "hello.txt" { + t.Errorf("Glob(%s) = %v, %v, want %v, nil", desc, names, err, []string{"hello.txt"}) + } + } + + // Test that ReadDir uses the method when present. + names, err := Glob(globOnly{testFsys}, "*.txt") + check("readDirOnly", names, err) + + // Test that ReadDir uses Open when the method is not present. + names, err = Glob(openOnly{testFsys}, "*.txt") + check("openOnly", names, err) +} diff --git a/src/testing/fstest/mapfs.go b/src/testing/fstest/mapfs.go index 1eaf8f0040f..10e56f5b3c3 100644 --- a/src/testing/fstest/mapfs.go +++ b/src/testing/fstest/mapfs.go @@ -128,6 +128,10 @@ func (fsys MapFS) ReadDir(name string) ([]fs.DirEntry, error) { return fs.ReadDir(fsOnly{fsys}, name) } +func (fsys MapFS) Glob(pattern string) ([]string, error) { + return fs.Glob(fsOnly{fsys}, pattern) +} + // A mapFileInfo implements fs.FileInfo and fs.DirEntry for a given map file. type mapFileInfo struct { name string diff --git a/src/testing/fstest/testfs.go b/src/testing/fstest/testfs.go index 4ea6ed60959..21cd00e5b60 100644 --- a/src/testing/fstest/testfs.go +++ b/src/testing/fstest/testfs.go @@ -11,6 +11,8 @@ import ( "io" "io/fs" "io/ioutil" + "path" + "reflect" "sort" "strings" "testing/iotest" @@ -226,6 +228,8 @@ func (t *fsTester) checkDir(dir string) { t.errorf("%s: fs.ReadDir: list not sorted: %s before %s", dir, list2[i].Name(), list2[i+1].Name()) } } + + t.checkGlob(dir, list) } // formatEntry formats an fs.DirEntry into a string for error messages and comparison. @@ -243,6 +247,98 @@ func formatInfo(info fs.FileInfo) string { return fmt.Sprintf("%s IsDir=%v Mode=%v Size=%d ModTime=%v", info.Name(), info.IsDir(), info.Mode(), info.Size(), info.ModTime()) } +// checkGlob checks that various glob patterns work if the file system implements GlobFS. +func (t *fsTester) checkGlob(dir string, list []fs.DirEntry) { + if _, ok := t.fsys.(fs.GlobFS); !ok { + return + } + + // Make a complex glob pattern prefix that only matches dir. + var glob string + if dir != "." { + elem := strings.Split(dir, "/") + for i, e := range elem { + var pattern []rune + for j, r := range e { + if r == '*' || r == '?' || r == '\\' || r == '[' { + pattern = append(pattern, '\\', r) + continue + } + switch (i + j) % 5 { + case 0: + pattern = append(pattern, r) + case 1: + pattern = append(pattern, '[', r, ']') + case 2: + pattern = append(pattern, '[', r, '-', r, ']') + case 3: + pattern = append(pattern, '[', '\\', r, ']') + case 4: + pattern = append(pattern, '[', '\\', r, '-', '\\', r, ']') + } + } + elem[i] = string(pattern) + } + glob = strings.Join(elem, "/") + "/" + } + + // Try to find a letter that appears in only some of the final names. + c := rune('a') + for ; c <= 'z'; c++ { + have, haveNot := false, false + for _, d := range list { + if strings.ContainsRune(d.Name(), c) { + have = true + } else { + haveNot = true + } + } + if have && haveNot { + break + } + } + if c > 'z' { + c = 'a' + } + glob += "*" + string(c) + "*" + + var want []string + for _, d := range list { + if strings.ContainsRune(d.Name(), c) { + want = append(want, path.Join(dir, d.Name())) + } + } + + names, err := t.fsys.(fs.GlobFS).Glob(glob) + if err != nil { + t.errorf("%s: Glob(%#q): %v", dir, glob, err) + return + } + if reflect.DeepEqual(want, names) { + return + } + + if !sort.StringsAreSorted(names) { + t.errorf("%s: Glob(%#q): unsorted output:\n%s", dir, glob, strings.Join(names, "\n")) + sort.Strings(names) + } + + var problems []string + for len(want) > 0 || len(names) > 0 { + switch { + case len(want) > 0 && len(names) > 0 && want[0] == names[0]: + want, names = want[1:], names[1:] + case len(want) > 0 && (len(names) == 0 || want[0] < names[0]): + problems = append(problems, "missing: "+want[0]) + want = want[1:] + default: + problems = append(problems, "extra: "+names[0]) + names = names[1:] + } + } + t.errorf("%s: Glob(%#q): wrong output:\n%s", dir, glob, strings.Join(problems, "\n")) +} + // checkStat checks that a direct stat of path matches entry, // which was found in the parent's directory listing. func (t *fsTester) checkStat(path string, entry fs.DirEntry) { From 1296ee6b4f9058be75c799513ccb488d2f2dd085 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 11:56:19 -0400 Subject: [PATCH 039/403] archive/zip: make Reader implement fs.FS Now a zip.Reader (an open zip file) can be passed to code that accepts a file system, such as (soon) template parsing. For #41190. Change-Id: If51b12e39db3ccc27f643c2453d3300a38035360 Reviewed-on: https://go-review.googlesource.com/c/go/+/243937 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/archive/zip/reader.go | 189 +++++++++++++++++++++++++++++++++ src/archive/zip/reader_test.go | 11 ++ src/archive/zip/struct.go | 3 + 3 files changed, 203 insertions(+) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index 13ff9ddcf42..5c9f3dea281 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -11,7 +11,12 @@ import ( "hash" "hash/crc32" "io" + "io/fs" "os" + "path" + "sort" + "strings" + "sync" "time" ) @@ -21,18 +26,28 @@ var ( ErrChecksum = errors.New("zip: checksum error") ) +// A Reader serves content from a ZIP archive. type Reader struct { r io.ReaderAt File []*File Comment string decompressors map[uint16]Decompressor + + // fileList is a list of files sorted by ename, + // for use by the Open method. + fileListOnce sync.Once + fileList []fileListEntry } +// A ReadCloser is a Reader that must be closed when no longer needed. type ReadCloser struct { f *os.File Reader } +// A File is a single file in a ZIP archive. +// The file information is in the embedded FileHeader. +// The file content can be accessed by calling Open. type File struct { FileHeader zip *Reader @@ -187,6 +202,10 @@ type checksumReader struct { err error // sticky error } +func (r *checksumReader) Stat() (fs.FileInfo, error) { + return headerFileInfo{&r.f.FileHeader}, nil +} + func (r *checksumReader) Read(b []byte) (n int, err error) { if r.err != nil { return 0, r.err @@ -607,3 +626,173 @@ func (b *readBuf) sub(n int) readBuf { *b = (*b)[n:] return b2 } + +// A fileListEntry is a File and its ename. +// If file == nil, the fileListEntry describes a directory, without metadata. +type fileListEntry struct { + name string + file *File // nil for directories +} + +type fileInfoDirEntry interface { + fs.FileInfo + fs.DirEntry +} + +func (e *fileListEntry) stat() fileInfoDirEntry { + if e.file != nil { + return headerFileInfo{&e.file.FileHeader} + } + return e +} + +// Only used for directories. +func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem } +func (f *fileListEntry) Size() int64 { return 0 } +func (f *fileListEntry) ModTime() time.Time { return time.Time{} } +func (f *fileListEntry) Mode() fs.FileMode { return fs.ModeDir | 0555 } +func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir } +func (f *fileListEntry) IsDir() bool { return true } +func (f *fileListEntry) Sys() interface{} { return nil } + +func (f *fileListEntry) Info() (fs.FileInfo, error) { return f, nil } + +// toValidName coerces name to be a valid name for fs.FS.Open. +func toValidName(name string) string { + name = strings.ReplaceAll(name, `\`, `/`) + p := path.Clean(name) + if strings.HasPrefix(p, "/") { + p = p[len("/"):] + } + for strings.HasPrefix(name, "../") { + p = p[len("../"):] + } + return p +} + +func (r *Reader) initFileList() { + r.fileListOnce.Do(func() { + dirs := make(map[string]bool) + for _, file := range r.File { + name := toValidName(file.Name) + for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) { + dirs[dir] = true + } + r.fileList = append(r.fileList, fileListEntry{name, file}) + } + for dir := range dirs { + r.fileList = append(r.fileList, fileListEntry{dir + "/", nil}) + } + + sort.Slice(r.fileList, func(i, j int) bool { return fileEntryLess(r.fileList[i].name, r.fileList[j].name) }) + }) +} + +func fileEntryLess(x, y string) bool { + xdir, xelem, _ := split(x) + ydir, yelem, _ := split(y) + return xdir < ydir || xdir == ydir && xelem < yelem +} + +// Open opens the named file in the ZIP archive, +// using the semantics of io.FS.Open: +// paths are always slash separated, with no +// leading / or ../ elements. +func (r *Reader) Open(name string) (fs.File, error) { + r.initFileList() + + e := r.openLookup(name) + if e == nil || !fs.ValidPath(name) { + return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist} + } + if e.file == nil || strings.HasSuffix(e.file.Name, "/") { + return &openDir{e, r.openReadDir(name), 0}, nil + } + rc, err := e.file.Open() + if err != nil { + return nil, err + } + return rc.(fs.File), nil +} + +func split(name string) (dir, elem string, isDir bool) { + if name[len(name)-1] == '/' { + isDir = true + name = name[:len(name)-1] + } + i := len(name) - 1 + for i >= 0 && name[i] != '/' { + i-- + } + if i < 0 { + return ".", name, isDir + } + return name[:i], name[i+1:], isDir +} + +var dotFile = &fileListEntry{name: "./"} + +func (r *Reader) openLookup(name string) *fileListEntry { + if name == "." { + return dotFile + } + + dir, elem, _ := split(name) + files := r.fileList + i := sort.Search(len(files), func(i int) bool { + idir, ielem, _ := split(files[i].name) + return idir > dir || idir == dir && ielem >= elem + }) + if i < len(files) { + fname := files[i].name + if fname == name || len(fname) == len(name)+1 && fname[len(name)] == '/' && fname[:len(name)] == name { + return &files[i] + } + } + return nil +} + +func (r *Reader) openReadDir(dir string) []fileListEntry { + files := r.fileList + i := sort.Search(len(files), func(i int) bool { + idir, _, _ := split(files[i].name) + return idir >= dir + }) + j := sort.Search(len(files), func(j int) bool { + jdir, _, _ := split(files[j].name) + return jdir > dir + }) + return files[i:j] +} + +type openDir struct { + e *fileListEntry + files []fileListEntry + offset int +} + +func (d *openDir) Close() error { return nil } +func (d *openDir) Stat() (fs.FileInfo, error) { return d.e.stat(), nil } + +func (d *openDir) Read([]byte) (int, error) { + return 0, &fs.PathError{Op: "read", Path: d.e.name, Err: errors.New("is a directory")} +} + +func (d *openDir) ReadDir(count int) ([]fs.DirEntry, error) { + n := len(d.files) - d.offset + if count > 0 && n > count { + n = count + } + if n == 0 { + if count <= 0 { + return nil, nil + } + return nil, io.EOF + } + list := make([]fs.DirEntry, n) + for i := range list { + list[i] = d.files[d.offset+i].stat() + } + d.offset += n + return list, nil +} diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go index 8a32d9c7dc9..38ff7badd0e 100644 --- a/src/archive/zip/reader_test.go +++ b/src/archive/zip/reader_test.go @@ -17,6 +17,7 @@ import ( "regexp" "strings" "testing" + "testing/fstest" "time" ) @@ -1071,3 +1072,13 @@ func TestIssue12449(t *testing.T) { t.Errorf("Error reading the archive: %v", err) } } + +func TestFS(t *testing.T) { + z, err := OpenReader("testdata/unix.zip") + if err != nil { + t.Fatal(err) + } + if err := fstest.TestFS(z, "hello", "dir/bar", "dir/empty", "readonly"); err != nil { + t.Fatal(err) + } +} diff --git a/src/archive/zip/struct.go b/src/archive/zip/struct.go index 355c57051bf..4dd29f35fa6 100644 --- a/src/archive/zip/struct.go +++ b/src/archive/zip/struct.go @@ -162,8 +162,11 @@ func (fi headerFileInfo) ModTime() time.Time { return fi.fh.Modified.UTC() } func (fi headerFileInfo) Mode() fs.FileMode { return fi.fh.Mode() } +func (fi headerFileInfo) Type() fs.FileMode { return fi.fh.Mode().Type() } func (fi headerFileInfo) Sys() interface{} { return fi.fh } +func (fi headerFileInfo) Info() (fs.FileInfo, error) { return fi, nil } + // FileInfoHeader creates a partially-populated FileHeader from an // fs.FileInfo. // Because fs.FileInfo's Name method returns only the base name of From 2a9aa4dcac0c33f7fffefb94a1bc92a17fd7cfd3 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 6 Jul 2020 11:28:52 -0400 Subject: [PATCH 040/403] html/template, text/template: add ParseFS Now templates can be parsed not just from operating system files but from arbitrary file systems, including zip files. For #41190. Change-Id: I2172001388ddb1f13defa6c5e644e8ec8703ee80 Reviewed-on: https://go-review.googlesource.com/c/go/+/243938 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/html/template/multi_test.go | 43 ++++++++++++++++++++++ src/html/template/template.go | 58 ++++++++++++++++++++++++++--- src/html/template/testdata/fs.zip | Bin 0 -> 406 bytes src/text/template/helper.go | 59 +++++++++++++++++++++++++++--- src/text/template/multi_test.go | 30 +++++++++++++++ 5 files changed, 178 insertions(+), 12 deletions(-) create mode 100644 src/html/template/testdata/fs.zip diff --git a/src/html/template/multi_test.go b/src/html/template/multi_test.go index 50526c5b65f..6535ab6c043 100644 --- a/src/html/template/multi_test.go +++ b/src/html/template/multi_test.go @@ -7,7 +7,9 @@ package template import ( + "archive/zip" "bytes" + "os" "testing" "text/template/parse" ) @@ -82,6 +84,35 @@ func TestParseGlob(t *testing.T) { testExecute(multiExecTests, template, t) } +func TestParseFS(t *testing.T) { + fs := os.DirFS("testdata") + + { + _, err := ParseFS(fs, "DOES NOT EXIST") + if err == nil { + t.Error("expected error for non-existent file; got none") + } + } + + { + template := New("root") + _, err := template.ParseFS(fs, "file1.tmpl", "file2.tmpl") + if err != nil { + t.Fatalf("error parsing files: %v", err) + } + testExecute(multiExecTests, template, t) + } + + { + template := New("root") + _, err := template.ParseFS(fs, "file*.tmpl") + if err != nil { + t.Fatalf("error parsing files: %v", err) + } + testExecute(multiExecTests, template, t) + } +} + // In these tests, actual content (not just template definitions) comes from the parsed files. var templateFileExecTests = []execTest{ @@ -104,6 +135,18 @@ func TestParseGlobWithData(t *testing.T) { testExecute(templateFileExecTests, template, t) } +func TestParseZipFS(t *testing.T) { + z, err := zip.OpenReader("testdata/fs.zip") + if err != nil { + t.Fatalf("error parsing zip: %v", err) + } + template, err := New("root").ParseFS(z, "tmpl*.tmpl") + if err != nil { + t.Fatalf("error parsing files: %v", err) + } + testExecute(templateFileExecTests, template, t) +} + const ( cloneText1 = `{{define "a"}}{{template "b"}}{{template "c"}}{{end}}` cloneText2 = `{{define "b"}}b{{end}}` diff --git a/src/html/template/template.go b/src/html/template/template.go index 75437879e2e..bc960afe5f1 100644 --- a/src/html/template/template.go +++ b/src/html/template/template.go @@ -7,7 +7,9 @@ package template import ( "fmt" "io" + "io/fs" "io/ioutil" + "path" "path/filepath" "sync" "text/template" @@ -384,7 +386,7 @@ func Must(t *Template, err error) *Template { // For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template // named "foo", while "a/foo" is unavailable. func ParseFiles(filenames ...string) (*Template, error) { - return parseFiles(nil, filenames...) + return parseFiles(nil, readFileOS, filenames...) } // ParseFiles parses the named files and associates the resulting templates with @@ -396,12 +398,12 @@ func ParseFiles(filenames ...string) (*Template, error) { // // ParseFiles returns an error if t or any associated template has already been executed. func (t *Template) ParseFiles(filenames ...string) (*Template, error) { - return parseFiles(t, filenames...) + return parseFiles(t, readFileOS, filenames...) } // parseFiles is the helper for the method and function. If the argument // template is nil, it is created from the first file. -func parseFiles(t *Template, filenames ...string) (*Template, error) { +func parseFiles(t *Template, readFile func(string) (string, []byte, error), filenames ...string) (*Template, error) { if err := t.checkCanParse(); err != nil { return nil, err } @@ -411,12 +413,11 @@ func parseFiles(t *Template, filenames ...string) (*Template, error) { return nil, fmt.Errorf("html/template: no files named in call to ParseFiles") } for _, filename := range filenames { - b, err := ioutil.ReadFile(filename) + name, b, err := readFile(filename) if err != nil { return nil, err } s := string(b) - name := filepath.Base(filename) // First template becomes return value if not already defined, // and we use that one for subsequent New calls to associate // all the templates together. Also, if this file has the same name @@ -479,7 +480,7 @@ func parseGlob(t *Template, pattern string) (*Template, error) { if len(filenames) == 0 { return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern) } - return parseFiles(t, filenames...) + return parseFiles(t, readFileOS, filenames...) } // IsTrue reports whether the value is 'true', in the sense of not the zero of its type, @@ -488,3 +489,48 @@ func parseGlob(t *Template, pattern string) (*Template, error) { func IsTrue(val interface{}) (truth, ok bool) { return template.IsTrue(val) } + +// ParseFS is like ParseFiles or ParseGlob but reads from the file system fs +// instead of the host operating system's file system. +// It accepts a list of glob patterns. +// (Note that most file names serve as glob patterns matching only themselves.) +func ParseFS(fs fs.FS, patterns ...string) (*Template, error) { + return parseFS(nil, fs, patterns) +} + +// ParseFS is like ParseFiles or ParseGlob but reads from the file system fs +// instead of the host operating system's file system. +// It accepts a list of glob patterns. +// (Note that most file names serve as glob patterns matching only themselves.) +func (t *Template) ParseFS(fs fs.FS, patterns ...string) (*Template, error) { + return parseFS(t, fs, patterns) +} + +func parseFS(t *Template, fsys fs.FS, patterns []string) (*Template, error) { + var filenames []string + for _, pattern := range patterns { + list, err := fs.Glob(fsys, pattern) + if err != nil { + return nil, err + } + if len(list) == 0 { + return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern) + } + filenames = append(filenames, list...) + } + return parseFiles(t, readFileFS(fsys), filenames...) +} + +func readFileOS(file string) (name string, b []byte, err error) { + name = filepath.Base(file) + b, err = ioutil.ReadFile(file) + return +} + +func readFileFS(fsys fs.FS) func(string) (string, []byte, error) { + return func(file string) (name string, b []byte, err error) { + name = path.Base(file) + b, err = fs.ReadFile(fsys, file) + return + } +} diff --git a/src/html/template/testdata/fs.zip b/src/html/template/testdata/fs.zip new file mode 100644 index 0000000000000000000000000000000000000000..8581313ae36f2b3980e320f3a8f747db9727386a GIT binary patch literal 406 zcmWIWW@Zs#U|`^2;3#<;P@%SDw+@hJ1jJknG7KfT1v!R#ATl(BlYx2t3ZD4q!ou;T z72FJrEV`i#3@pL%j11bIXLV0_>Uf$yS+&m3)A#fl@6do%0jt)oU9ryZtoO>btX$I_ zrfO(}GO6xh2tct< Date: Tue, 7 Jul 2020 09:51:45 -0400 Subject: [PATCH 041/403] net/http: add FS to convert fs.FS to FileSystem Two different functions in the http API expect a FileSystem: http.FileSystem and http.NewFileTransport. Add a general converter http.FS to turn an fs.FS into an http.FileSystem for use with either of these functions. (The original plan was to add http.HandlerFS taking an fs.FS directly, but that doesn't help with NewFileTransport.) For #41190. Change-Id: I5f242eafe9b963f4387419a2615bdb487c358f16 Reviewed-on: https://go-review.googlesource.com/c/go/+/243939 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/net/http/fs.go | 133 +++++++++++++++++++++++++++++++++++++--- src/net/http/fs_test.go | 37 +++++++++++ 2 files changed, 162 insertions(+), 8 deletions(-) diff --git a/src/net/http/fs.go b/src/net/http/fs.go index 0743b5b621c..a28ae85958f 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -87,6 +87,10 @@ func (d Dir) Open(name string) (File, error) { // A FileSystem implements access to a collection of named files. // The elements in a file path are separated by slash ('/', U+002F) // characters, regardless of host operating system convention. +// See the FileServer function to convert a FileSystem to a Handler. +// +// This interface predates the fs.FS interface, which can be used instead: +// the FS adapter function converts an fs.FS to a FileSystem. type FileSystem interface { Open(name string) (File, error) } @@ -103,20 +107,52 @@ type File interface { Stat() (fs.FileInfo, error) } +type anyDirs interface { + len() int + name(i int) string + isDir(i int) bool +} + +type fileInfoDirs []fs.FileInfo + +func (d fileInfoDirs) len() int { return len(d) } +func (d fileInfoDirs) isDir(i int) bool { return d[i].IsDir() } +func (d fileInfoDirs) name(i int) string { return d[i].Name() } + +type dirEntryDirs []fs.DirEntry + +func (d dirEntryDirs) len() int { return len(d) } +func (d dirEntryDirs) isDir(i int) bool { return d[i].IsDir() } +func (d dirEntryDirs) name(i int) string { return d[i].Name() } + func dirList(w ResponseWriter, r *Request, f File) { - dirs, err := f.Readdir(-1) + // Prefer to use ReadDir instead of Readdir, + // because the former doesn't require calling + // Stat on every entry of a directory on Unix. + var dirs anyDirs + var err error + if d, ok := f.(fs.ReadDirFile); ok { + var list dirEntryDirs + list, err = d.ReadDir(-1) + dirs = list + } else { + var list fileInfoDirs + list, err = f.Readdir(-1) + dirs = list + } + if err != nil { logf(r, "http: error reading directory: %v", err) Error(w, "Error reading directory", StatusInternalServerError) return } - sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() }) + sort.Slice(dirs, func(i, j int) bool { return dirs.name(i) < dirs.name(j) }) w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprintf(w, "
\n")
-	for _, d := range dirs {
-		name := d.Name()
-		if d.IsDir() {
+	for i, n := 0, dirs.len(); i < n; i++ {
+		name := dirs.name(i)
+		if dirs.isDir(i) {
 			name += "/"
 		}
 		// name may contain '?' or '#', which must be escaped to remain
@@ -707,17 +743,98 @@ type fileHandler struct {
 	root FileSystem
 }
 
+type ioFS struct {
+	fsys fs.FS
+}
+
+type ioFile struct {
+	file fs.File
+}
+
+func (f ioFS) Open(name string) (File, error) {
+	if name == "/" {
+		name = "."
+	} else {
+		name = strings.TrimPrefix(name, "/")
+	}
+	file, err := f.fsys.Open(name)
+	if err != nil {
+		return nil, err
+	}
+	return ioFile{file}, nil
+}
+
+func (f ioFile) Close() error               { return f.file.Close() }
+func (f ioFile) Read(b []byte) (int, error) { return f.file.Read(b) }
+func (f ioFile) Stat() (fs.FileInfo, error) { return f.file.Stat() }
+
+var errMissingSeek = errors.New("io.File missing Seek method")
+var errMissingReadDir = errors.New("io.File directory missing ReadDir method")
+
+func (f ioFile) Seek(offset int64, whence int) (int64, error) {
+	s, ok := f.file.(io.Seeker)
+	if !ok {
+		return 0, errMissingSeek
+	}
+	return s.Seek(offset, whence)
+}
+
+func (f ioFile) ReadDir(count int) ([]fs.DirEntry, error) {
+	d, ok := f.file.(fs.ReadDirFile)
+	if !ok {
+		return nil, errMissingReadDir
+	}
+	return d.ReadDir(count)
+}
+
+func (f ioFile) Readdir(count int) ([]fs.FileInfo, error) {
+	d, ok := f.file.(fs.ReadDirFile)
+	if !ok {
+		return nil, errMissingReadDir
+	}
+	var list []fs.FileInfo
+	for {
+		dirs, err := d.ReadDir(count - len(list))
+		for _, dir := range dirs {
+			info, err := dir.Info()
+			if err != nil {
+				// Pretend it doesn't exist, like (*os.File).Readdir does.
+				continue
+			}
+			list = append(list, info)
+		}
+		if err != nil {
+			return list, err
+		}
+		if count < 0 || len(list) >= count {
+			break
+		}
+	}
+	return list, nil
+}
+
+// FS converts fsys to a FileSystem implementation,
+// for use with FileServer and NewFileTransport.
+func FS(fsys fs.FS) FileSystem {
+	return ioFS{fsys}
+}
+
 // FileServer returns a handler that serves HTTP requests
 // with the contents of the file system rooted at root.
 //
+// As a special case, the returned file server redirects any request
+// ending in "/index.html" to the same path, without the final
+// "index.html".
+//
 // To use the operating system's file system implementation,
 // use http.Dir:
 //
 //     http.Handle("/", http.FileServer(http.Dir("/tmp")))
 //
-// As a special case, the returned file server redirects any request
-// ending in "/index.html" to the same path, without the final
-// "index.html".
+// To use an fs.FS implementation, use http.FS to convert it:
+//
+//	http.Handle("/", http.FileServer(http.FS(fsys)))
+//
 func FileServer(root FileSystem) Handler {
 	return &fileHandler{root}
 }
diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go
index de793b331e6..c9f324cff6f 100644
--- a/src/net/http/fs_test.go
+++ b/src/net/http/fs_test.go
@@ -571,6 +571,43 @@ func testServeFileWithContentEncoding(t *testing.T, h2 bool) {
 
 func TestServeIndexHtml(t *testing.T) {
 	defer afterTest(t)
+
+	for i := 0; i < 2; i++ {
+		var h Handler
+		var name string
+		switch i {
+		case 0:
+			h = FileServer(Dir("."))
+			name = "Dir"
+		case 1:
+			h = FileServer(FS(os.DirFS(".")))
+			name = "DirFS"
+		}
+		t.Run(name, func(t *testing.T) {
+			const want = "index.html says hello\n"
+			ts := httptest.NewServer(h)
+			defer ts.Close()
+
+			for _, path := range []string{"/testdata/", "/testdata/index.html"} {
+				res, err := Get(ts.URL + path)
+				if err != nil {
+					t.Fatal(err)
+				}
+				b, err := ioutil.ReadAll(res.Body)
+				if err != nil {
+					t.Fatal("reading Body:", err)
+				}
+				if s := string(b); s != want {
+					t.Errorf("for path %q got %q, want %q", path, s, want)
+				}
+				res.Body.Close()
+			}
+		})
+	}
+}
+
+func TestServeIndexHtmlFS(t *testing.T) {
+	defer afterTest(t)
 	const want = "index.html says hello\n"
 	ts := httptest.NewServer(FileServer(Dir(".")))
 	defer ts.Close()

From cb0a0f52e67f128c6ad69027c9a8c7a5caf58446 Mon Sep 17 00:00:00 2001
From: Russ Cox 
Date: Fri, 16 Oct 2020 00:41:03 -0400
Subject: [PATCH 042/403] io: adopt Discard, NopCloser, ReadAll from io/ioutil

As proposed and approved in #40025, Discard, NopCloser, and ReadAll
do not really fit into io/ioutil, which exists mainly to hold things that
would cause an import cycle if implemented in io itself, which is to say
things that import "os".

These three do not import "os" - they are generic io helpers like
many of the things in io itself, so it makes sense for them to be there.

Fixes #40025.

Change-Id: I77f47e9b2a72839edf7446997936631980047b67
Reviewed-on: https://go-review.googlesource.com/c/go/+/263141
Trust: Russ Cox 
Run-TryBot: Russ Cox 
TryBot-Result: Go Bot 
Reviewed-by: Rob Pike 
---
 src/io/example_test.go  |  14 ++++++
 src/io/io.go            |  84 +++++++++++++++++++++++++++++--
 src/io/ioutil/ioutil.go | 107 ++++++++++++----------------------------
 3 files changed, 126 insertions(+), 79 deletions(-)

diff --git a/src/io/example_test.go b/src/io/example_test.go
index 465eed4d5e4..47060324298 100644
--- a/src/io/example_test.go
+++ b/src/io/example_test.go
@@ -241,3 +241,17 @@ func ExamplePipe() {
 	// Output:
 	// some io.Reader stream to be read
 }
+
+func ExampleReadAll() {
+	r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
+
+	b, err := ioutil.ReadAll(r)
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	fmt.Printf("%s", b)
+
+	// Output:
+	// Go is a general-purpose language designed with systems programming in mind.
+}
diff --git a/src/io/io.go b/src/io/io.go
index a34c39a32a4..269ebf6ed06 100644
--- a/src/io/io.go
+++ b/src/io/io.go
@@ -14,6 +14,7 @@ package io
 
 import (
 	"errors"
+	"sync"
 )
 
 // Seek whence values.
@@ -46,9 +47,9 @@ var EOF = errors.New("EOF")
 // middle of reading a fixed-size block or data structure.
 var ErrUnexpectedEOF = errors.New("unexpected EOF")
 
-// ErrNoProgress is returned by some clients of an io.Reader when
+// ErrNoProgress is returned by some clients of an Reader when
 // many calls to Read have failed to return any data or error,
-// usually the sign of a broken io.Reader implementation.
+// usually the sign of a broken Reader implementation.
 var ErrNoProgress = errors.New("multiple Read calls return no data or error")
 
 // Reader is the interface that wraps the basic Read method.
@@ -177,7 +178,7 @@ type ReadWriteSeeker interface {
 //
 // ReadFrom reads data from r until EOF or error.
 // The return value n is the number of bytes read.
-// Any error except io.EOF encountered during the read is also returned.
+// Any error except EOF encountered during the read is also returned.
 //
 // The Copy function uses ReaderFrom if available.
 type ReaderFrom interface {
@@ -390,7 +391,7 @@ func Copy(dst Writer, src Reader) (written int64, err error) {
 // buf will not be used to perform the copy.
 func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) {
 	if buf != nil && len(buf) == 0 {
-		panic("empty buffer in io.CopyBuffer")
+		panic("empty buffer in CopyBuffer")
 	}
 	return copyBuffer(dst, src, buf)
 }
@@ -564,3 +565,78 @@ func (t *teeReader) Read(p []byte) (n int, err error) {
 	}
 	return
 }
+
+// Discard is an Writer on which all Write calls succeed
+// without doing anything.
+var Discard Writer = discard{}
+
+type discard struct{}
+
+// discard implements ReaderFrom as an optimization so Copy to
+// ioutil.Discard can avoid doing unnecessary work.
+var _ ReaderFrom = discard{}
+
+func (discard) Write(p []byte) (int, error) {
+	return len(p), nil
+}
+
+func (discard) WriteString(s string) (int, error) {
+	return len(s), nil
+}
+
+var blackHolePool = sync.Pool{
+	New: func() interface{} {
+		b := make([]byte, 8192)
+		return &b
+	},
+}
+
+func (discard) ReadFrom(r Reader) (n int64, err error) {
+	bufp := blackHolePool.Get().(*[]byte)
+	readSize := 0
+	for {
+		readSize, err = r.Read(*bufp)
+		n += int64(readSize)
+		if err != nil {
+			blackHolePool.Put(bufp)
+			if err == EOF {
+				return n, nil
+			}
+			return
+		}
+	}
+}
+
+// NopCloser returns a ReadCloser with a no-op Close method wrapping
+// the provided Reader r.
+func NopCloser(r Reader) ReadCloser {
+	return nopCloser{r}
+}
+
+type nopCloser struct {
+	Reader
+}
+
+func (nopCloser) Close() error { return nil }
+
+// ReadAll reads from r until an error or EOF and returns the data it read.
+// A successful call returns err == nil, not err == EOF. Because ReadAll is
+// defined to read from src until EOF, it does not treat an EOF from Read
+// as an error to be reported.
+func ReadAll(r Reader) ([]byte, error) {
+	b := make([]byte, 0, 512)
+	for {
+		if len(b) == cap(b) {
+			// Add more capacity (let append pick how much).
+			b = append(b, 0)[:len(b)]
+		}
+		n, err := r.Read(b[len(b):cap(b)])
+		b = b[:len(b)+n]
+		if err != nil {
+			if err == EOF {
+				err = nil
+			}
+			return b, err
+		}
+	}
+}
diff --git a/src/io/ioutil/ioutil.go b/src/io/ioutil/ioutil.go
index cae41f00183..a001c86b2f2 100644
--- a/src/io/ioutil/ioutil.go
+++ b/src/io/ioutil/ioutil.go
@@ -6,44 +6,20 @@
 package ioutil
 
 import (
-	"bytes"
 	"io"
 	"io/fs"
 	"os"
 	"sort"
-	"sync"
 )
 
-// readAll reads from r until an error or EOF and returns the data it read
-// from the internal buffer allocated with a specified capacity.
-func readAll(r io.Reader, capacity int64) (b []byte, err error) {
-	var buf bytes.Buffer
-	// If the buffer overflows, we will get bytes.ErrTooLarge.
-	// Return that as an error. Any other panic remains.
-	defer func() {
-		e := recover()
-		if e == nil {
-			return
-		}
-		if panicErr, ok := e.(error); ok && panicErr == bytes.ErrTooLarge {
-			err = panicErr
-		} else {
-			panic(e)
-		}
-	}()
-	if int64(int(capacity)) == capacity {
-		buf.Grow(int(capacity))
-	}
-	_, err = buf.ReadFrom(r)
-	return buf.Bytes(), err
-}
-
 // ReadAll reads from r until an error or EOF and returns the data it read.
 // A successful call returns err == nil, not err == EOF. Because ReadAll is
 // defined to read from src until EOF, it does not treat an EOF from Read
 // as an error to be reported.
+//
+// As of Go 1.16, this function simply calls io.ReadAll.
 func ReadAll(r io.Reader) ([]byte, error) {
-	return readAll(r, bytes.MinRead)
+	return io.ReadAll(r)
 }
 
 // ReadFile reads the file named by filename and returns the contents.
@@ -58,7 +34,8 @@ func ReadFile(filename string) ([]byte, error) {
 	defer f.Close()
 	// It's a good but not certain bet that FileInfo will tell us exactly how much to
 	// read, so let's try it but be prepared for the answer to be wrong.
-	var n int64 = bytes.MinRead
+	const minRead = 512
+	var n int64 = minRead
 
 	if fi, err := f.Stat(); err == nil {
 		// As initial capacity for readAll, use Size + a little extra in case Size
@@ -67,11 +44,30 @@ func ReadFile(filename string) ([]byte, error) {
 		// cheaply. If the size was wrong, we'll either waste some space off the end
 		// or reallocate as needed, but in the overwhelmingly common case we'll get
 		// it just right.
-		if size := fi.Size() + bytes.MinRead; size > n {
+		if size := fi.Size() + minRead; size > n {
 			n = size
 		}
 	}
-	return readAll(f, n)
+
+	if int64(int(n)) != n {
+		n = minRead
+	}
+
+	b := make([]byte, 0, n)
+	for {
+		if len(b) == cap(b) {
+			// Add more capacity (let append pick how much).
+			b = append(b, 0)[:len(b)]
+		}
+		n, err := f.Read(b[len(b):cap(b)])
+		b = b[:len(b)+n]
+		if err != nil {
+			if err == io.EOF {
+				err = nil
+			}
+			return b, err
+		}
+	}
 }
 
 // WriteFile writes data to a file named by filename.
@@ -105,55 +101,16 @@ func ReadDir(dirname string) ([]fs.FileInfo, error) {
 	return list, nil
 }
 
-type nopCloser struct {
-	io.Reader
-}
-
-func (nopCloser) Close() error { return nil }
-
 // NopCloser returns a ReadCloser with a no-op Close method wrapping
 // the provided Reader r.
+//
+// As of Go 1.16, this function simply calls io.NopCloser.
 func NopCloser(r io.Reader) io.ReadCloser {
-	return nopCloser{r}
-}
-
-type devNull int
-
-// devNull implements ReaderFrom as an optimization so io.Copy to
-// ioutil.Discard can avoid doing unnecessary work.
-var _ io.ReaderFrom = devNull(0)
-
-func (devNull) Write(p []byte) (int, error) {
-	return len(p), nil
-}
-
-func (devNull) WriteString(s string) (int, error) {
-	return len(s), nil
-}
-
-var blackHolePool = sync.Pool{
-	New: func() interface{} {
-		b := make([]byte, 8192)
-		return &b
-	},
-}
-
-func (devNull) ReadFrom(r io.Reader) (n int64, err error) {
-	bufp := blackHolePool.Get().(*[]byte)
-	readSize := 0
-	for {
-		readSize, err = r.Read(*bufp)
-		n += int64(readSize)
-		if err != nil {
-			blackHolePool.Put(bufp)
-			if err == io.EOF {
-				return n, nil
-			}
-			return
-		}
-	}
+	return io.NopCloser(r)
 }
 
 // Discard is an io.Writer on which all Write calls succeed
 // without doing anything.
-var Discard io.Writer = devNull(0)
+//
+// As of Go 1.16, this value is simply io.Discard.
+var Discard io.Writer = io.Discard

From 1b09d430678d4a6f73b2443463d11f75851aba8a Mon Sep 17 00:00:00 2001
From: Russ Cox 
Date: Fri, 16 Oct 2020 00:49:02 -0400
Subject: [PATCH 043/403] all: update references to symbols moved from
 io/ioutil to io

The old ioutil references are still valid, but update our code
to reflect best practices and get used to the new locations.

Code compiled with the bootstrap toolchain
(cmd/asm, cmd/dist, cmd/compile, debug/elf)
must remain Go 1.4-compatible and is excluded.
Also excluded vendored code.

For #41190.

Change-Id: I6d86f2bf7bc37a9d904b6cee3fe0c7af6d94d5b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/263142
Trust: Russ Cox 
Run-TryBot: Russ Cox 
TryBot-Result: Go Bot 
Reviewed-by: Emmanuel Odeke 
---
 src/archive/tar/reader.go                     |   7 +-
 src/archive/tar/reader_test.go                |   2 +-
 src/archive/tar/tar_test.go                   |   8 +-
 src/archive/zip/reader_test.go                |   6 +-
 src/archive/zip/register.go                   |   3 +-
 src/archive/zip/writer_test.go                |   4 +-
 src/archive/zip/zip_test.go                   |   3 +-
 src/bufio/bufio_test.go                       |  19 ++-
 src/bytes/reader_test.go                      |   9 +-
 src/cmd/fix/main.go                           |   3 +-
 src/cmd/go/internal/clean/clean.go            |   3 +-
 src/cmd/go/internal/fsys/fsys_test.go         |   3 +-
 src/cmd/go/internal/imports/read.go           |   4 +-
 src/cmd/go/internal/lockedfile/lockedfile.go  |   5 +-
 src/cmd/go/internal/modfetch/codehost/git.go  |   5 +-
 .../go/internal/modfetch/codehost/git_test.go |   3 +-
 .../go/internal/modfetch/codehost/shell.go    |   3 +-
 src/cmd/go/internal/modfetch/coderepo.go      |   2 +-
 src/cmd/go/internal/modfetch/fetch.go         |   2 +-
 src/cmd/go/internal/modfetch/proxy.go         |   3 +-
 src/cmd/go/internal/modfetch/sumdb.go         |   4 +-
 src/cmd/go/internal/web/api.go                |   5 +-
 src/cmd/go/proxy_test.go                      |   4 +-
 .../go/testdata/script/test_cache_inputs.txt  |   2 +-
 src/cmd/gofmt/gofmt.go                        |   2 +-
 src/cmd/pprof/pprof.go                        |   4 +-
 src/cmd/trace/trace_test.go                   |  10 +-
 src/cmd/trace/trace_unix_test.go              |   4 +-
 src/compress/bzip2/bzip2_test.go              |   6 +-
 src/compress/flate/deflate_test.go            |  24 ++--
 src/compress/flate/flate_test.go              |   5 +-
 src/compress/flate/inflate_test.go            |   3 +-
 src/compress/flate/reader_test.go             |   4 +-
 src/compress/flate/writer_test.go             |   9 +-
 src/compress/gzip/gunzip_test.go              |   9 +-
 src/compress/gzip/gzip_test.go                |   9 +-
 src/compress/lzw/reader_test.go               |   4 +-
 src/compress/lzw/writer_test.go               |  10 +-
 src/compress/zlib/writer_test.go              |   4 +-
 src/crypto/tls/handshake_test.go              |   2 +-
 src/crypto/tls/tls_test.go                    |   7 +-
 src/crypto/x509/root_ios_gen.go               |   2 +-
 src/debug/gosym/pclntab_test.go               |   3 +-
 src/encoding/ascii85/ascii85_test.go          |   7 +-
 src/encoding/base32/base32_test.go            |  13 +-
 src/encoding/base64/base64_test.go            |  15 ++-
 src/encoding/binary/binary_test.go            |   3 +-
 src/encoding/gob/encoder_test.go              |   4 +-
 src/encoding/hex/hex_test.go                  |   3 +-
 src/encoding/json/bench_test.go               |   8 +-
 src/encoding/json/stream_test.go              |   5 +-
 src/encoding/pem/pem_test.go                  |   4 +-
 src/flag/flag_test.go                         |   5 +-
 src/go/internal/gccgoimporter/importer.go     |   2 +-
 src/go/internal/gcimporter/gcimporter.go      |   3 +-
 src/go/parser/interface.go                    |   2 +-
 src/go/printer/performance_test.go            |   2 +-
 src/go/types/gotype.go                        |   4 +-
 src/html/template/clone_test.go               |  14 +--
 src/html/template/exec_test.go                |   8 +-
 src/image/gif/writer_test.go                  |  22 ++--
 src/image/jpeg/writer_test.go                 |   6 +-
 src/image/png/writer_test.go                  |  17 ++-
 .../obscuretestdata/obscuretestdata.go        |   2 +-
 src/internal/profile/profile.go               |   5 +-
 src/io/example_test.go                        |   5 +-
 src/io/io.go                                  |   2 +-
 src/io/multi_test.go                          |  11 +-
 src/mime/encodedword_test.go                  |   3 +-
 src/mime/example_test.go                      |   5 +-
 src/mime/multipart/example_test.go            |   3 +-
 src/mime/multipart/multipart.go               |   3 +-
 src/mime/multipart/multipart_test.go          |  13 +-
 src/mime/multipart/writer_test.go             |   8 +-
 src/mime/quotedprintable/example_test.go      |   4 +-
 src/mime/quotedprintable/writer_test.go       |   6 +-
 src/net/http/alpn_test.go                     |   5 +-
 src/net/http/cgi/child.go                     |   3 +-
 src/net/http/client.go                        |   5 +-
 src/net/http/client_test.go                   |  25 ++--
 src/net/http/clientserver_test.go             |  39 +++---
 src/net/http/doc.go                           |   2 +-
 src/net/http/example_test.go                  |   3 +-
 src/net/http/fcgi/child.go                    |   5 +-
 src/net/http/fcgi/fcgi_test.go                |   5 +-
 src/net/http/filetransport_test.go            |   3 +-
 src/net/http/fs_test.go                       |  20 +--
 src/net/http/httptest/example_test.go         |   9 +-
 src/net/http/httptest/httptest.go             |   3 +-
 src/net/http/httptest/httptest_test.go        |   3 +-
 src/net/http/httptest/recorder.go             |   4 +-
 src/net/http/httptest/recorder_test.go        |   3 +-
 src/net/http/httptest/server_test.go          |  10 +-
 src/net/http/httputil/dump.go                 |   9 +-
 src/net/http/httputil/dump_test.go            |   9 +-
 src/net/http/httputil/example_test.go         |   6 +-
 src/net/http/httputil/reverseproxy_test.go    |  49 ++++----
 src/net/http/internal/chunked_test.go         |   5 +-
 src/net/http/main_test.go                     |   4 +-
 src/net/http/pprof/pprof_test.go              |   6 +-
 src/net/http/readrequest_test.go              |   3 +-
 src/net/http/request.go                       |  11 +-
 src/net/http/request_test.go                  |  22 ++--
 src/net/http/requestwrite_test.go             |  27 ++--
 src/net/http/response_test.go                 |   5 +-
 src/net/http/responsewrite_test.go            |  20 +--
 src/net/http/roundtrip_js.go                  |   3 +-
 src/net/http/serve_test.go                    | 119 +++++++++---------
 src/net/http/server.go                        |   5 +-
 src/net/http/sniff_test.go                    |   7 +-
 src/net/http/transfer.go                      |  11 +-
 src/net/http/transfer_test.go                 |  16 +--
 src/net/http/transport_internal_test.go       |   3 +-
 src/net/http/transport_test.go                | 100 +++++++--------
 src/net/mail/example_test.go                  |   4 +-
 src/net/mail/message_test.go                  |   5 +-
 src/net/rpc/jsonrpc/all_test.go               |   5 +-
 src/net/sendfile_test.go                      |   3 +-
 src/net/splice_test.go                        |   3 +-
 src/net/textproto/reader.go                   |   3 +-
 src/net/timeout_test.go                       |   3 +-
 src/net/writev_test.go                        |   5 +-
 src/os/exec/example_test.go                   |   3 +-
 src/os/exec/exec_test.go                      |   4 +-
 src/os/exec/read3.go                          |   4 +-
 src/os/timeout_test.go                        |   4 +-
 src/runtime/crash_unix_test.go                |   2 +-
 src/runtime/testdata/testprogcgo/eintr.go     |   3 +-
 src/strings/reader_test.go                    |   7 +-
 src/syscall/mkpost.go                         |   4 +-
 src/syscall/syscall_unix_test.go              |   2 +-
 src/testing/iotest/reader.go                  |   9 +-
 src/text/tabwriter/tabwriter_test.go          |  11 +-
 src/text/template/exec_test.go                |   8 +-
 src/time/genzabbrs.go                         |   3 +-
 135 files changed, 535 insertions(+), 597 deletions(-)

diff --git a/src/archive/tar/reader.go b/src/archive/tar/reader.go
index 4f9135b7919..1b1d5b46891 100644
--- a/src/archive/tar/reader.go
+++ b/src/archive/tar/reader.go
@@ -7,7 +7,6 @@ package tar
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"strconv"
 	"strings"
 	"time"
@@ -104,7 +103,7 @@ func (tr *Reader) next() (*Header, error) {
 			continue // This is a meta header affecting the next header
 		case TypeGNULongName, TypeGNULongLink:
 			format.mayOnlyBe(FormatGNU)
-			realname, err := ioutil.ReadAll(tr)
+			realname, err := io.ReadAll(tr)
 			if err != nil {
 				return nil, err
 			}
@@ -294,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
 // parsePAX parses PAX headers.
 // If an extended header (type 'x') is invalid, ErrHeader is returned
 func parsePAX(r io.Reader) (map[string]string, error) {
-	buf, err := ioutil.ReadAll(r)
+	buf, err := io.ReadAll(r)
 	if err != nil {
 		return nil, err
 	}
@@ -850,7 +849,7 @@ func discard(r io.Reader, n int64) error {
 		}
 	}
 
-	copySkipped, err := io.CopyN(ioutil.Discard, r, n-seekSkipped)
+	copySkipped, err := io.CopyN(io.Discard, r, n-seekSkipped)
 	if err == io.EOF && seekSkipped+copySkipped < n {
 		err = io.ErrUnexpectedEOF
 	}
diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go
index f153b668def..411d1e0b99d 100644
--- a/src/archive/tar/reader_test.go
+++ b/src/archive/tar/reader_test.go
@@ -865,7 +865,7 @@ func TestReadTruncation(t *testing.T) {
 				}
 				cnt++
 				if s2 == "manual" {
-					if _, err = tr.writeTo(ioutil.Discard); err != nil {
+					if _, err = tr.writeTo(io.Discard); err != nil {
 						break
 					}
 				}
diff --git a/src/archive/tar/tar_test.go b/src/archive/tar/tar_test.go
index f605dae9044..d4a3d423120 100644
--- a/src/archive/tar/tar_test.go
+++ b/src/archive/tar/tar_test.go
@@ -328,7 +328,7 @@ func TestRoundTrip(t *testing.T) {
 	if !reflect.DeepEqual(rHdr, hdr) {
 		t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
 	}
-	rData, err := ioutil.ReadAll(tr)
+	rData, err := io.ReadAll(tr)
 	if err != nil {
 		t.Fatalf("Read: %v", err)
 	}
@@ -805,9 +805,9 @@ func Benchmark(b *testing.B) {
 			b.Run(v.label, func(b *testing.B) {
 				b.ReportAllocs()
 				for i := 0; i < b.N; i++ {
-					// Writing to ioutil.Discard because we want to
+					// Writing to io.Discard because we want to
 					// test purely the writer code and not bring in disk performance into this.
-					tw := NewWriter(ioutil.Discard)
+					tw := NewWriter(io.Discard)
 					for _, file := range v.files {
 						if err := tw.WriteHeader(file.hdr); err != nil {
 							b.Errorf("unexpected WriteHeader error: %v", err)
@@ -845,7 +845,7 @@ func Benchmark(b *testing.B) {
 					if _, err := tr.Next(); err != nil {
 						b.Errorf("unexpected Next error: %v", err)
 					}
-					if _, err := io.Copy(ioutil.Discard, tr); err != nil {
+					if _, err := io.Copy(io.Discard, tr); err != nil {
 						b.Errorf("unexpected Copy error : %v", err)
 					}
 				}
diff --git a/src/archive/zip/reader_test.go b/src/archive/zip/reader_test.go
index 38ff7badd0e..b7a7d7a757a 100644
--- a/src/archive/zip/reader_test.go
+++ b/src/archive/zip/reader_test.go
@@ -930,7 +930,7 @@ func returnBigZipBytes() (r io.ReaderAt, size int64) {
 		if err != nil {
 			panic(err)
 		}
-		b, err = ioutil.ReadAll(f)
+		b, err = io.ReadAll(f)
 		if err != nil {
 			panic(err)
 		}
@@ -987,7 +987,7 @@ func TestIssue10957(t *testing.T) {
 			continue
 		}
 		if f.UncompressedSize64 < 1e6 {
-			n, err := io.Copy(ioutil.Discard, r)
+			n, err := io.Copy(io.Discard, r)
 			if i == 3 && err != io.ErrUnexpectedEOF {
 				t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
 			}
@@ -1029,7 +1029,7 @@ func TestIssue11146(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	_, err = ioutil.ReadAll(r)
+	_, err = io.ReadAll(r)
 	if err != io.ErrUnexpectedEOF {
 		t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
 	}
diff --git a/src/archive/zip/register.go b/src/archive/zip/register.go
index 51e9c3e4d4b..4389246286f 100644
--- a/src/archive/zip/register.go
+++ b/src/archive/zip/register.go
@@ -8,7 +8,6 @@ import (
 	"compress/flate"
 	"errors"
 	"io"
-	"io/ioutil"
 	"sync"
 )
 
@@ -111,7 +110,7 @@ func init() {
 	compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
 	compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
 
-	decompressors.Store(Store, Decompressor(ioutil.NopCloser))
+	decompressors.Store(Store, Decompressor(io.NopCloser))
 	decompressors.Store(Deflate, Decompressor(newFlateReader))
 }
 
diff --git a/src/archive/zip/writer_test.go b/src/archive/zip/writer_test.go
index 282f9ec2163..2c32eaf4a58 100644
--- a/src/archive/zip/writer_test.go
+++ b/src/archive/zip/writer_test.go
@@ -301,7 +301,7 @@ func TestWriterFlush(t *testing.T) {
 }
 
 func TestWriterDir(t *testing.T) {
-	w := NewWriter(ioutil.Discard)
+	w := NewWriter(io.Discard)
 	dw, err := w.Create("dir/")
 	if err != nil {
 		t.Fatal(err)
@@ -380,7 +380,7 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
 	if err != nil {
 		t.Fatal("opening:", err)
 	}
-	b, err := ioutil.ReadAll(rc)
+	b, err := io.ReadAll(rc)
 	if err != nil {
 		t.Fatal("reading:", err)
 	}
diff --git a/src/archive/zip/zip_test.go b/src/archive/zip/zip_test.go
index b3a7caac7f2..ead9cd3aab9 100644
--- a/src/archive/zip/zip_test.go
+++ b/src/archive/zip/zip_test.go
@@ -13,7 +13,6 @@ import (
 	"hash"
 	"internal/testenv"
 	"io"
-	"io/ioutil"
 	"runtime"
 	"sort"
 	"strings"
@@ -620,7 +619,7 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
 			t.Fatal("read:", err)
 		}
 	}
-	gotEnd, err := ioutil.ReadAll(rc)
+	gotEnd, err := io.ReadAll(rc)
 	if err != nil {
 		t.Fatal("read end:", err)
 	}
diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go
index cb68f3ba239..75086f1f240 100644
--- a/src/bufio/bufio_test.go
+++ b/src/bufio/bufio_test.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 	"testing/iotest"
@@ -886,7 +885,7 @@ func TestReadEmptyBuffer(t *testing.T) {
 
 func TestLinesAfterRead(t *testing.T) {
 	l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize)
-	_, err := ioutil.ReadAll(l)
+	_, err := io.ReadAll(l)
 	if err != nil {
 		t.Error(err)
 		return
@@ -1130,7 +1129,7 @@ func TestWriterReadFromCounts(t *testing.T) {
 	}
 }
 
-// A writeCountingDiscard is like ioutil.Discard and counts the number of times
+// A writeCountingDiscard is like io.Discard and counts the number of times
 // Write is called on it.
 type writeCountingDiscard int
 
@@ -1300,7 +1299,7 @@ func TestReaderReset(t *testing.T) {
 		t.Errorf("buf = %q; want foo", buf)
 	}
 	r.Reset(strings.NewReader("bar bar"))
-	all, err := ioutil.ReadAll(r)
+	all, err := io.ReadAll(r)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1645,13 +1644,13 @@ func BenchmarkReaderWriteToOptimal(b *testing.B) {
 	buf := make([]byte, bufSize)
 	r := bytes.NewReader(buf)
 	srcReader := NewReaderSize(onlyReader{r}, 1<<10)
-	if _, ok := ioutil.Discard.(io.ReaderFrom); !ok {
-		b.Fatal("ioutil.Discard doesn't support ReaderFrom")
+	if _, ok := io.Discard.(io.ReaderFrom); !ok {
+		b.Fatal("io.Discard doesn't support ReaderFrom")
 	}
 	for i := 0; i < b.N; i++ {
 		r.Seek(0, io.SeekStart)
 		srcReader.Reset(onlyReader{r})
-		n, err := srcReader.WriteTo(ioutil.Discard)
+		n, err := srcReader.WriteTo(io.Discard)
 		if err != nil {
 			b.Fatal(err)
 		}
@@ -1722,7 +1721,7 @@ func BenchmarkReaderEmpty(b *testing.B) {
 	str := strings.Repeat("x", 16<<10)
 	for i := 0; i < b.N; i++ {
 		br := NewReader(strings.NewReader(str))
-		n, err := io.Copy(ioutil.Discard, br)
+		n, err := io.Copy(io.Discard, br)
 		if err != nil {
 			b.Fatal(err)
 		}
@@ -1737,7 +1736,7 @@ func BenchmarkWriterEmpty(b *testing.B) {
 	str := strings.Repeat("x", 1<<10)
 	bs := []byte(str)
 	for i := 0; i < b.N; i++ {
-		bw := NewWriter(ioutil.Discard)
+		bw := NewWriter(io.Discard)
 		bw.Flush()
 		bw.WriteByte('a')
 		bw.Flush()
@@ -1752,7 +1751,7 @@ func BenchmarkWriterEmpty(b *testing.B) {
 
 func BenchmarkWriterFlush(b *testing.B) {
 	b.ReportAllocs()
-	bw := NewWriter(ioutil.Discard)
+	bw := NewWriter(io.Discard)
 	str := strings.Repeat("x", 50)
 	for i := 0; i < b.N; i++ {
 		bw.WriteString(str)
diff --git a/src/bytes/reader_test.go b/src/bytes/reader_test.go
index d799e036f0c..8baac5046cb 100644
--- a/src/bytes/reader_test.go
+++ b/src/bytes/reader_test.go
@@ -8,7 +8,6 @@ import (
 	. "bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"sync"
 	"testing"
 )
@@ -235,7 +234,7 @@ func TestReaderCopyNothing(t *testing.T) {
 	type justWriter struct {
 		io.Writer
 	}
-	discard := justWriter{ioutil.Discard} // hide ReadFrom
+	discard := justWriter{io.Discard} // hide ReadFrom
 
 	var with, withOut nErr
 	with.n, with.err = io.Copy(discard, NewReader(nil))
@@ -248,7 +247,7 @@ func TestReaderCopyNothing(t *testing.T) {
 // tests that Len is affected by reads, but Size is not.
 func TestReaderLenSize(t *testing.T) {
 	r := NewReader([]byte("abc"))
-	io.CopyN(ioutil.Discard, r, 1)
+	io.CopyN(io.Discard, r, 1)
 	if r.Len() != 2 {
 		t.Errorf("Len = %d; want 2", r.Len())
 	}
@@ -268,7 +267,7 @@ func TestReaderReset(t *testing.T) {
 	if err := r.UnreadRune(); err == nil {
 		t.Errorf("UnreadRune: expected error, got nil")
 	}
-	buf, err := ioutil.ReadAll(r)
+	buf, err := io.ReadAll(r)
 	if err != nil {
 		t.Errorf("ReadAll: unexpected error: %v", err)
 	}
@@ -314,7 +313,7 @@ func TestReaderZero(t *testing.T) {
 		t.Errorf("UnreadRune: got nil, want error")
 	}
 
-	if n, err := (&Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
+	if n, err := (&Reader{}).WriteTo(io.Discard); n != 0 || err != nil {
 		t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
 	}
 }
diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go
index dfba902f483..1cea9a876af 100644
--- a/src/cmd/fix/main.go
+++ b/src/cmd/fix/main.go
@@ -13,6 +13,7 @@ import (
 	"go/parser"
 	"go/scanner"
 	"go/token"
+	"io"
 	"io/fs"
 	"io/ioutil"
 	"os"
@@ -128,7 +129,7 @@ func processFile(filename string, useStdin bool) error {
 		defer f.Close()
 	}
 
-	src, err := ioutil.ReadAll(f)
+	src, err := io.ReadAll(f)
 	if err != nil {
 		return err
 	}
diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go
index 6bfd7ae21e9..095c3cc7135 100644
--- a/src/cmd/go/internal/clean/clean.go
+++ b/src/cmd/go/internal/clean/clean.go
@@ -8,6 +8,7 @@ package clean
 import (
 	"context"
 	"fmt"
+	"io"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -172,7 +173,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
 			f, err := lockedfile.Edit(filepath.Join(dir, "testexpire.txt"))
 			if err == nil {
 				now := time.Now().UnixNano()
-				buf, _ := ioutil.ReadAll(f)
+				buf, _ := io.ReadAll(f)
 				prev, _ := strconv.ParseInt(strings.TrimSpace(string(buf)), 10, 64)
 				if now > prev {
 					if err = f.Truncate(0); err == nil {
diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go
index ba9f05d00b9..28c3f08cb97 100644
--- a/src/cmd/go/internal/fsys/fsys_test.go
+++ b/src/cmd/go/internal/fsys/fsys_test.go
@@ -6,6 +6,7 @@ import (
 	"errors"
 	"fmt"
 	"internal/testenv"
+	"io"
 	"io/fs"
 	"io/ioutil"
 	"os"
@@ -418,7 +419,7 @@ this can exist because the parent directory is deleted
 			t.Errorf("Open(%q): got error %v, want nil", tc.path, err)
 			continue
 		}
-		contents, err := ioutil.ReadAll(f)
+		contents, err := io.ReadAll(f)
 		if err != nil {
 			t.Errorf("unexpected error reading contents of file: %v", err)
 		}
diff --git a/src/cmd/go/internal/imports/read.go b/src/cmd/go/internal/imports/read.go
index 58c2abdc29a..5e270781d77 100644
--- a/src/cmd/go/internal/imports/read.go
+++ b/src/cmd/go/internal/imports/read.go
@@ -198,7 +198,7 @@ func (r *importReader) readImport(imports *[]string) {
 	r.readString(imports)
 }
 
-// ReadComments is like ioutil.ReadAll, except that it only reads the leading
+// ReadComments is like io.ReadAll, except that it only reads the leading
 // block of comments in the file.
 func ReadComments(f io.Reader) ([]byte, error) {
 	r := &importReader{b: bufio.NewReader(f)}
@@ -210,7 +210,7 @@ func ReadComments(f io.Reader) ([]byte, error) {
 	return r.buf, r.err
 }
 
-// ReadImports is like ioutil.ReadAll, except that it expects a Go file as input
+// ReadImports is like io.ReadAll, except that it expects a Go file as input
 // and stops reading the input once the imports have completed.
 func ReadImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
 	r := &importReader{b: bufio.NewReader(f)}
diff --git a/src/cmd/go/internal/lockedfile/lockedfile.go b/src/cmd/go/internal/lockedfile/lockedfile.go
index 503024da4bf..82e1a89675e 100644
--- a/src/cmd/go/internal/lockedfile/lockedfile.go
+++ b/src/cmd/go/internal/lockedfile/lockedfile.go
@@ -10,7 +10,6 @@ import (
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
 	"os"
 	"runtime"
 )
@@ -104,7 +103,7 @@ func Read(name string) ([]byte, error) {
 	}
 	defer f.Close()
 
-	return ioutil.ReadAll(f)
+	return io.ReadAll(f)
 }
 
 // Write opens the named file (creating it with the given permissions if needed),
@@ -136,7 +135,7 @@ func Transform(name string, t func([]byte) ([]byte, error)) (err error) {
 	}
 	defer f.Close()
 
-	old, err := ioutil.ReadAll(f)
+	old, err := io.ReadAll(f)
 	if err != nil {
 		return err
 	}
diff --git a/src/cmd/go/internal/modfetch/codehost/git.go b/src/cmd/go/internal/modfetch/codehost/git.go
index 58b4b2f2d3e..8abc039e7fc 100644
--- a/src/cmd/go/internal/modfetch/codehost/git.go
+++ b/src/cmd/go/internal/modfetch/codehost/git.go
@@ -10,7 +10,6 @@ import (
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
 	"net/url"
 	"os"
 	"os/exec"
@@ -832,7 +831,7 @@ func (r *gitRepo) ReadZip(rev, subdir string, maxSize int64) (zip io.ReadCloser,
 		return nil, err
 	}
 
-	return ioutil.NopCloser(bytes.NewReader(archive)), nil
+	return io.NopCloser(bytes.NewReader(archive)), nil
 }
 
 // ensureGitAttributes makes sure export-subst and export-ignore features are
@@ -863,7 +862,7 @@ func ensureGitAttributes(repoDir string) (err error) {
 		}
 	}()
 
-	b, err := ioutil.ReadAll(f)
+	b, err := io.ReadAll(f)
 	if err != nil {
 		return err
 	}
diff --git a/src/cmd/go/internal/modfetch/codehost/git_test.go b/src/cmd/go/internal/modfetch/codehost/git_test.go
index 16908b3e849..981e3fe91fb 100644
--- a/src/cmd/go/internal/modfetch/codehost/git_test.go
+++ b/src/cmd/go/internal/modfetch/codehost/git_test.go
@@ -10,6 +10,7 @@ import (
 	"flag"
 	"fmt"
 	"internal/testenv"
+	"io"
 	"io/fs"
 	"io/ioutil"
 	"log"
@@ -433,7 +434,7 @@ func TestReadZip(t *testing.T) {
 			if tt.err != "" {
 				t.Fatalf("ReadZip: no error, wanted %v", tt.err)
 			}
-			zipdata, err := ioutil.ReadAll(rc)
+			zipdata, err := io.ReadAll(rc)
 			if err != nil {
 				t.Fatal(err)
 			}
diff --git a/src/cmd/go/internal/modfetch/codehost/shell.go b/src/cmd/go/internal/modfetch/codehost/shell.go
index 2762c557203..b9525adf5e6 100644
--- a/src/cmd/go/internal/modfetch/codehost/shell.go
+++ b/src/cmd/go/internal/modfetch/codehost/shell.go
@@ -14,6 +14,7 @@ import (
 	"bytes"
 	"flag"
 	"fmt"
+	"io"
 	"io/ioutil"
 	"log"
 	"os"
@@ -115,7 +116,7 @@ func main() {
 				fmt.Fprintf(os.Stderr, "?%s\n", err)
 				continue
 			}
-			data, err := ioutil.ReadAll(rc)
+			data, err := io.ReadAll(rc)
 			rc.Close()
 			if err != nil {
 				fmt.Fprintf(os.Stderr, "?%s\n", err)
diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go
index 7f44e18a702..b6bcf83f1a4 100644
--- a/src/cmd/go/internal/modfetch/coderepo.go
+++ b/src/cmd/go/internal/modfetch/coderepo.go
@@ -1052,7 +1052,7 @@ type dataFile struct {
 func (f dataFile) Path() string                { return f.name }
 func (f dataFile) Lstat() (fs.FileInfo, error) { return dataFileInfo{f}, nil }
 func (f dataFile) Open() (io.ReadCloser, error) {
-	return ioutil.NopCloser(bytes.NewReader(f.data)), nil
+	return io.NopCloser(bytes.NewReader(f.data)), nil
 }
 
 type dataFileInfo struct {
diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go
index 6ff455e89ce..40196c4e9a8 100644
--- a/src/cmd/go/internal/modfetch/fetch.go
+++ b/src/cmd/go/internal/modfetch/fetch.go
@@ -461,7 +461,7 @@ func checkMod(mod module.Version) {
 // goModSum returns the checksum for the go.mod contents.
 func goModSum(data []byte) (string, error) {
 	return dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
-		return ioutil.NopCloser(bytes.NewReader(data)), nil
+		return io.NopCloser(bytes.NewReader(data)), nil
 	})
 }
 
diff --git a/src/cmd/go/internal/modfetch/proxy.go b/src/cmd/go/internal/modfetch/proxy.go
index 819990b4030..d75b4da5215 100644
--- a/src/cmd/go/internal/modfetch/proxy.go
+++ b/src/cmd/go/internal/modfetch/proxy.go
@@ -10,7 +10,6 @@ import (
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
 	"net/url"
 	"path"
 	pathpkg "path"
@@ -305,7 +304,7 @@ func (p *proxyRepo) getBytes(path string) ([]byte, error) {
 		return nil, err
 	}
 	defer body.Close()
-	return ioutil.ReadAll(body)
+	return io.ReadAll(body)
 }
 
 func (p *proxyRepo) getBody(path string) (io.ReadCloser, error) {
diff --git a/src/cmd/go/internal/modfetch/sumdb.go b/src/cmd/go/internal/modfetch/sumdb.go
index 5108961a334..4fbc54d15ce 100644
--- a/src/cmd/go/internal/modfetch/sumdb.go
+++ b/src/cmd/go/internal/modfetch/sumdb.go
@@ -12,8 +12,8 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
+	"io"
 	"io/fs"
-	"io/ioutil"
 	"net/url"
 	"os"
 	"path/filepath"
@@ -228,7 +228,7 @@ func (*dbClient) WriteConfig(file string, old, new []byte) error {
 		return err
 	}
 	defer f.Close()
-	data, err := ioutil.ReadAll(f)
+	data, err := io.ReadAll(f)
 	if err != nil {
 		return err
 	}
diff --git a/src/cmd/go/internal/web/api.go b/src/cmd/go/internal/web/api.go
index f7d3ed60f69..9053b16b629 100644
--- a/src/cmd/go/internal/web/api.go
+++ b/src/cmd/go/internal/web/api.go
@@ -14,7 +14,6 @@ import (
 	"fmt"
 	"io"
 	"io/fs"
-	"io/ioutil"
 	"net/url"
 	"strings"
 	"unicode"
@@ -87,7 +86,7 @@ func GetBytes(u *url.URL) ([]byte, error) {
 	if err := resp.Err(); err != nil {
 		return nil, err
 	}
-	b, err := ioutil.ReadAll(resp.Body)
+	b, err := io.ReadAll(resp.Body)
 	if err != nil {
 		return nil, fmt.Errorf("reading %s: %v", u.Redacted(), err)
 	}
@@ -130,7 +129,7 @@ func (r *Response) formatErrorDetail() string {
 	}
 
 	// Ensure that r.errorDetail has been populated.
-	_, _ = io.Copy(ioutil.Discard, r.Body)
+	_, _ = io.Copy(io.Discard, r.Body)
 
 	s := r.errorDetail.buf.String()
 	if !utf8.ValidString(s) {
diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go
index 8b0dbb74b2b..3ed42face23 100644
--- a/src/cmd/go/proxy_test.go
+++ b/src/cmd/go/proxy_test.go
@@ -471,13 +471,13 @@ func proxyGoSum(path, vers string) ([]byte, error) {
 	}
 	h1, err := dirhash.Hash1(names, func(name string) (io.ReadCloser, error) {
 		data := files[name]
-		return ioutil.NopCloser(bytes.NewReader(data)), nil
+		return io.NopCloser(bytes.NewReader(data)), nil
 	})
 	if err != nil {
 		return nil, err
 	}
 	h1mod, err := dirhash.Hash1([]string{"go.mod"}, func(string) (io.ReadCloser, error) {
-		return ioutil.NopCloser(bytes.NewReader(gomod)), nil
+		return io.NopCloser(bytes.NewReader(gomod)), nil
 	})
 	if err != nil {
 		return nil, err
diff --git a/src/cmd/go/testdata/script/test_cache_inputs.txt b/src/cmd/go/testdata/script/test_cache_inputs.txt
index 57602e91dc1..97ae4af51f0 100644
--- a/src/cmd/go/testdata/script/test_cache_inputs.txt
+++ b/src/cmd/go/testdata/script/test_cache_inputs.txt
@@ -159,7 +159,7 @@ func TestOddFileContent(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	data, err := ioutil.ReadAll(f)
+	data, err := io.ReadAll(f)
 	f.Close()
 	if err != nil {
 		t.Fatal(err)
diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go
index 48b6ad6f539..dba2411eed3 100644
--- a/src/cmd/gofmt/gofmt.go
+++ b/src/cmd/gofmt/gofmt.go
@@ -97,7 +97,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error
 		perm = fi.Mode().Perm()
 	}
 
-	src, err := ioutil.ReadAll(in)
+	src, err := io.ReadAll(in)
 	if err != nil {
 		return err
 	}
diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go
index c1ddbe372f6..11f91cbedb9 100644
--- a/src/cmd/pprof/pprof.go
+++ b/src/cmd/pprof/pprof.go
@@ -13,7 +13,7 @@ import (
 	"crypto/tls"
 	"debug/dwarf"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/url"
 	"os"
@@ -94,7 +94,7 @@ func getProfile(source string, timeout time.Duration) (*profile.Profile, error)
 func statusCodeError(resp *http.Response) error {
 	if resp.Header.Get("X-Go-Pprof") != "" && strings.Contains(resp.Header.Get("Content-Type"), "text/plain") {
 		// error is from pprof endpoint
-		if body, err := ioutil.ReadAll(resp.Body); err == nil {
+		if body, err := io.ReadAll(resp.Body); err == nil {
 			return fmt.Errorf("server response: %s - %s", resp.Status, body)
 		}
 	}
diff --git a/src/cmd/trace/trace_test.go b/src/cmd/trace/trace_test.go
index dd12e8cd207..ea0cc6f8800 100644
--- a/src/cmd/trace/trace_test.go
+++ b/src/cmd/trace/trace_test.go
@@ -10,7 +10,7 @@ import (
 	"cmd/internal/traceviewer"
 	"context"
 	"internal/trace"
-	"io/ioutil"
+	"io"
 	rtrace "runtime/trace"
 	"strings"
 	"sync"
@@ -78,7 +78,7 @@ func TestGoroutineCount(t *testing.T) {
 
 	// Use the default viewerDataTraceConsumer but replace
 	// consumeViewerEvent to intercept the ViewerEvents for testing.
-	c := viewerDataTraceConsumer(ioutil.Discard, 0, 1<<63-1)
+	c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
 	c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
 		if ev.Name == "Goroutines" {
 			cnt := ev.Arg.(*goroutineCountersArg)
@@ -131,7 +131,7 @@ func TestGoroutineFilter(t *testing.T) {
 		gs:      map[uint64]bool{10: true},
 	}
 
-	c := viewerDataTraceConsumer(ioutil.Discard, 0, 1<<63-1)
+	c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
 	if err := generateTrace(params, c); err != nil {
 		t.Fatalf("generateTrace failed: %v", err)
 	}
@@ -163,7 +163,7 @@ func TestPreemptedMarkAssist(t *testing.T) {
 		endTime: int64(1<<63 - 1),
 	}
 
-	c := viewerDataTraceConsumer(ioutil.Discard, 0, 1<<63-1)
+	c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
 
 	marks := 0
 	c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
@@ -214,7 +214,7 @@ func TestFoo(t *testing.T) {
 		tasks:     []*taskDesc{task},
 	}
 
-	c := viewerDataTraceConsumer(ioutil.Discard, 0, 1<<63-1)
+	c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
 
 	var logBeforeTaskEnd, logAfterTaskEnd bool
 	c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
diff --git a/src/cmd/trace/trace_unix_test.go b/src/cmd/trace/trace_unix_test.go
index 645978e0f88..c569b40bb24 100644
--- a/src/cmd/trace/trace_unix_test.go
+++ b/src/cmd/trace/trace_unix_test.go
@@ -10,7 +10,7 @@ import (
 	"bytes"
 	"cmd/internal/traceviewer"
 	traceparser "internal/trace"
-	"io/ioutil"
+	"io"
 	"runtime"
 	"runtime/trace"
 	"sync"
@@ -83,7 +83,7 @@ func TestGoroutineInSyscall(t *testing.T) {
 
 	// Check only one thread for the pipe read goroutine is
 	// considered in-syscall.
-	c := viewerDataTraceConsumer(ioutil.Discard, 0, 1<<63-1)
+	c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
 	c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
 		if ev.Name == "Threads" {
 			arg := ev.Arg.(*threadCountersArg)
diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go
index c432bb5226f..98477791b36 100644
--- a/src/compress/bzip2/bzip2_test.go
+++ b/src/compress/bzip2/bzip2_test.go
@@ -133,7 +133,7 @@ func TestReader(t *testing.T) {
 
 	for i, v := range vectors {
 		rd := NewReader(bytes.NewReader(v.input))
-		buf, err := ioutil.ReadAll(rd)
+		buf, err := io.ReadAll(rd)
 
 		if fail := bool(err != nil); fail != v.fail {
 			if fail {
@@ -220,7 +220,7 @@ var (
 
 func benchmarkDecode(b *testing.B, compressed []byte) {
 	// Determine the uncompressed size of testfile.
-	uncompressedSize, err := io.Copy(ioutil.Discard, NewReader(bytes.NewReader(compressed)))
+	uncompressedSize, err := io.Copy(io.Discard, NewReader(bytes.NewReader(compressed)))
 	if err != nil {
 		b.Fatal(err)
 	}
@@ -231,7 +231,7 @@ func benchmarkDecode(b *testing.B, compressed []byte) {
 
 	for i := 0; i < b.N; i++ {
 		r := bytes.NewReader(compressed)
-		io.Copy(ioutil.Discard, NewReader(r))
+		io.Copy(io.Discard, NewReader(r))
 	}
 }
 
diff --git a/src/compress/flate/deflate_test.go b/src/compress/flate/deflate_test.go
index b19cbec5a9a..6fc5abf4d5f 100644
--- a/src/compress/flate/deflate_test.go
+++ b/src/compress/flate/deflate_test.go
@@ -157,7 +157,7 @@ func TestVeryLongSparseChunk(t *testing.T) {
 	if testing.Short() {
 		t.Skip("skipping sparse chunk during short test")
 	}
-	w, err := NewWriter(ioutil.Discard, 1)
+	w, err := NewWriter(io.Discard, 1)
 	if err != nil {
 		t.Errorf("NewWriter: %v", err)
 		return
@@ -294,7 +294,7 @@ func testSync(t *testing.T, level int, input []byte, name string) {
 
 	// stream should work for ordinary reader too
 	r = NewReader(buf1)
-	out, err = ioutil.ReadAll(r)
+	out, err = io.ReadAll(r)
 	if err != nil {
 		t.Errorf("testSync: read: %s", err)
 		return
@@ -322,7 +322,7 @@ func testToFromWithLevelAndLimit(t *testing.T, level int, input []byte, name str
 		t.Logf("level: %d, size:%.2f%%, %d b\n", level, float64(buffer.Len()*100)/float64(limit), buffer.Len())
 	}
 	r := NewReader(&buffer)
-	out, err := ioutil.ReadAll(r)
+	out, err := io.ReadAll(r)
 	if err != nil {
 		t.Errorf("read: %s", err)
 		return
@@ -415,7 +415,7 @@ func TestReaderDict(t *testing.T) {
 	w.Close()
 
 	r := NewReaderDict(&b, []byte(dict))
-	data, err := ioutil.ReadAll(r)
+	data, err := io.ReadAll(r)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -456,7 +456,7 @@ func TestRegression2508(t *testing.T) {
 		t.Logf("test disabled with -short")
 		return
 	}
-	w, err := NewWriter(ioutil.Discard, 1)
+	w, err := NewWriter(io.Discard, 1)
 	if err != nil {
 		t.Fatalf("NewWriter: %v", err)
 	}
@@ -475,7 +475,7 @@ func TestWriterReset(t *testing.T) {
 		if testing.Short() && level > 1 {
 			break
 		}
-		w, err := NewWriter(ioutil.Discard, level)
+		w, err := NewWriter(io.Discard, level)
 		if err != nil {
 			t.Fatalf("NewWriter: %v", err)
 		}
@@ -487,9 +487,9 @@ func TestWriterReset(t *testing.T) {
 		for i := 0; i < n; i++ {
 			w.Write(buf)
 		}
-		w.Reset(ioutil.Discard)
+		w.Reset(io.Discard)
 
-		wref, err := NewWriter(ioutil.Discard, level)
+		wref, err := NewWriter(io.Discard, level)
 		if err != nil {
 			t.Fatalf("NewWriter: %v", err)
 		}
@@ -654,7 +654,7 @@ func TestBestSpeed(t *testing.T) {
 				}
 
 				r := NewReader(buf)
-				got, err := ioutil.ReadAll(r)
+				got, err := io.ReadAll(r)
 				if err != nil {
 					t.Errorf("i=%d, firstN=%d, flush=%t: ReadAll: %v", i, firstN, flush, err)
 					continue
@@ -881,7 +881,7 @@ func TestBestSpeedMaxMatchOffset(t *testing.T) {
 				}
 
 				r := NewReader(buf)
-				dst, err := ioutil.ReadAll(r)
+				dst, err := io.ReadAll(r)
 				r.Close()
 				if err != nil {
 					report("ReadAll: ", err)
@@ -968,7 +968,7 @@ func TestMaxStackSize(t *testing.T) {
 		wg.Add(1)
 		go func(level int) {
 			defer wg.Done()
-			zw, err := NewWriter(ioutil.Discard, level)
+			zw, err := NewWriter(io.Discard, level)
 			if err != nil {
 				t.Errorf("level %d, NewWriter() = %v, want nil", level, err)
 			}
@@ -978,7 +978,7 @@ func TestMaxStackSize(t *testing.T) {
 			if err := zw.Close(); err != nil {
 				t.Errorf("level %d, Close() = %v, want nil", level, err)
 			}
-			zw.Reset(ioutil.Discard)
+			zw.Reset(io.Discard)
 		}(level)
 	}
 }
diff --git a/src/compress/flate/flate_test.go b/src/compress/flate/flate_test.go
index 1e45077bd5b..23f4c47b037 100644
--- a/src/compress/flate/flate_test.go
+++ b/src/compress/flate/flate_test.go
@@ -12,7 +12,6 @@ import (
 	"bytes"
 	"encoding/hex"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -243,7 +242,7 @@ func TestStreams(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		data, err = ioutil.ReadAll(NewReader(bytes.NewReader(data)))
+		data, err = io.ReadAll(NewReader(bytes.NewReader(data)))
 		if tc.want == "fail" {
 			if err == nil {
 				t.Errorf("#%d (%s): got nil error, want non-nil", i, tc.desc)
@@ -266,7 +265,7 @@ func TestTruncatedStreams(t *testing.T) {
 
 	for i := 0; i < len(data)-1; i++ {
 		r := NewReader(strings.NewReader(data[:i]))
-		_, err := io.Copy(ioutil.Discard, r)
+		_, err := io.Copy(io.Discard, r)
 		if err != io.ErrUnexpectedEOF {
 			t.Errorf("io.Copy(%d) on truncated stream: got %v, want %v", i, err, io.ErrUnexpectedEOF)
 		}
diff --git a/src/compress/flate/inflate_test.go b/src/compress/flate/inflate_test.go
index 951decd7754..9575be1cf27 100644
--- a/src/compress/flate/inflate_test.go
+++ b/src/compress/flate/inflate_test.go
@@ -7,7 +7,6 @@ package flate
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -57,7 +56,7 @@ func TestReaderTruncated(t *testing.T) {
 	for i, v := range vectors {
 		r := strings.NewReader(v.input)
 		zr := NewReader(r)
-		b, err := ioutil.ReadAll(zr)
+		b, err := io.ReadAll(zr)
 		if err != io.ErrUnexpectedEOF {
 			t.Errorf("test %d, error mismatch: got %v, want io.ErrUnexpectedEOF", i, err)
 		}
diff --git a/src/compress/flate/reader_test.go b/src/compress/flate/reader_test.go
index 9d2943a5407..eb32c891842 100644
--- a/src/compress/flate/reader_test.go
+++ b/src/compress/flate/reader_test.go
@@ -16,7 +16,7 @@ import (
 func TestNlitOutOfRange(t *testing.T) {
 	// Trying to decode this bogus flate data, which has a Huffman table
 	// with nlit=288, should not panic.
-	io.Copy(ioutil.Discard, NewReader(strings.NewReader(
+	io.Copy(io.Discard, NewReader(strings.NewReader(
 		"\xfc\xfe\x36\xe7\x5e\x1c\xef\xb3\x55\x58\x77\xb6\x56\xb5\x43\xf4"+
 			"\x6f\xf2\xd2\xe6\x3d\x99\xa0\x85\x8c\x48\xeb\xf8\xda\x83\x04\x2a"+
 			"\x75\xc4\xf8\x0f\x12\x11\xb9\xb4\x4b\x09\xa0\xbe\x8b\x91\x4c")))
@@ -54,7 +54,7 @@ func BenchmarkDecode(b *testing.B) {
 		runtime.GC()
 		b.StartTimer()
 		for i := 0; i < b.N; i++ {
-			io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1)))
+			io.Copy(io.Discard, NewReader(bytes.NewReader(buf1)))
 		}
 	})
 }
diff --git a/src/compress/flate/writer_test.go b/src/compress/flate/writer_test.go
index 881cb71cc3a..c413735cd2c 100644
--- a/src/compress/flate/writer_test.go
+++ b/src/compress/flate/writer_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"math/rand"
 	"runtime"
 	"testing"
@@ -27,14 +26,14 @@ func BenchmarkEncode(b *testing.B) {
 			copy(buf1[i:], buf0)
 		}
 		buf0 = nil
-		w, err := NewWriter(ioutil.Discard, level)
+		w, err := NewWriter(io.Discard, level)
 		if err != nil {
 			b.Fatal(err)
 		}
 		runtime.GC()
 		b.StartTimer()
 		for i := 0; i < b.N; i++ {
-			w.Reset(ioutil.Discard)
+			w.Reset(io.Discard)
 			w.Write(buf1)
 			w.Close()
 		}
@@ -96,7 +95,7 @@ func TestWriteError(t *testing.T) {
 				t.Fatal("Level", l, "Expected an error on close")
 			}
 
-			w.Reset(ioutil.Discard)
+			w.Reset(io.Discard)
 			n2, err = w.Write([]byte{1, 2, 3, 4, 5, 6})
 			if err != nil {
 				t.Fatal("Level", l, "Got unexpected error after reset:", err)
@@ -206,7 +205,7 @@ func TestDeflateFast_Reset(t *testing.T) {
 	w.Close()
 
 	for ; offset <= 256; offset *= 2 {
-		w, err := NewWriter(ioutil.Discard, level)
+		w, err := NewWriter(io.Discard, level)
 		if err != nil {
 			t.Fatalf("NewWriter: level %d: %v", level, err)
 		}
diff --git a/src/compress/gzip/gunzip_test.go b/src/compress/gzip/gunzip_test.go
index 1b014041692..17c23e8a9be 100644
--- a/src/compress/gzip/gunzip_test.go
+++ b/src/compress/gzip/gunzip_test.go
@@ -9,7 +9,6 @@ import (
 	"compress/flate"
 	"encoding/base64"
 	"io"
-	"io/ioutil"
 	"os"
 	"strings"
 	"testing"
@@ -430,7 +429,7 @@ func TestIssue6550(t *testing.T) {
 	defer gzip.Close()
 	done := make(chan bool, 1)
 	go func() {
-		_, err := io.Copy(ioutil.Discard, gzip)
+		_, err := io.Copy(io.Discard, gzip)
 		if err == nil {
 			t.Errorf("Copy succeeded")
 		} else {
@@ -467,7 +466,7 @@ Found:
 	const hello = "hello world\n"
 
 	r.Multistream(false)
-	data, err := ioutil.ReadAll(&r)
+	data, err := io.ReadAll(&r)
 	if string(data) != hello || err != nil {
 		t.Fatalf("first stream = %q, %v, want %q, %v", string(data), err, hello, nil)
 	}
@@ -476,7 +475,7 @@ Found:
 		t.Fatalf("second reset: %v", err)
 	}
 	r.Multistream(false)
-	data, err = ioutil.ReadAll(&r)
+	data, err = io.ReadAll(&r)
 	if string(data) != hello || err != nil {
 		t.Fatalf("second stream = %q, %v, want %q, %v", string(data), err, hello, nil)
 	}
@@ -507,7 +506,7 @@ func TestTruncatedStreams(t *testing.T) {
 			}
 			continue
 		}
-		_, err = io.Copy(ioutil.Discard, r)
+		_, err = io.Copy(io.Discard, r)
 		if ferr, ok := err.(*flate.ReadError); ok {
 			err = ferr.Err
 		}
diff --git a/src/compress/gzip/gzip_test.go b/src/compress/gzip/gzip_test.go
index f18c5cb4547..12c8e182078 100644
--- a/src/compress/gzip/gzip_test.go
+++ b/src/compress/gzip/gzip_test.go
@@ -8,7 +8,6 @@ import (
 	"bufio"
 	"bytes"
 	"io"
-	"io/ioutil"
 	"reflect"
 	"testing"
 	"time"
@@ -29,7 +28,7 @@ func TestEmpty(t *testing.T) {
 	if want := (Header{OS: 255}); !reflect.DeepEqual(r.Header, want) {
 		t.Errorf("Header mismatch:\ngot  %#v\nwant %#v", r.Header, want)
 	}
-	b, err := ioutil.ReadAll(r)
+	b, err := io.ReadAll(r)
 	if err != nil {
 		t.Fatalf("ReadAll: %v", err)
 	}
@@ -62,7 +61,7 @@ func TestRoundTrip(t *testing.T) {
 	if err != nil {
 		t.Fatalf("NewReader: %v", err)
 	}
-	b, err := ioutil.ReadAll(r)
+	b, err := io.ReadAll(r)
 	if err != nil {
 		t.Fatalf("ReadAll: %v", err)
 	}
@@ -147,7 +146,7 @@ func TestLatin1RoundTrip(t *testing.T) {
 			t.Errorf("NewReader: %v", err)
 			continue
 		}
-		_, err = ioutil.ReadAll(r)
+		_, err = io.ReadAll(r)
 		if err != nil {
 			t.Errorf("ReadAll: %v", err)
 			continue
@@ -217,7 +216,7 @@ func TestConcat(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	data, err := ioutil.ReadAll(r)
+	data, err := io.ReadAll(r)
 	if string(data) != "hello world\n" || err != nil {
 		t.Fatalf("ReadAll = %q, %v, want %q, nil", data, err, "hello world")
 	}
diff --git a/src/compress/lzw/reader_test.go b/src/compress/lzw/reader_test.go
index 98bbfbb763e..6d91dd806fe 100644
--- a/src/compress/lzw/reader_test.go
+++ b/src/compress/lzw/reader_test.go
@@ -206,7 +206,7 @@ func TestNoLongerSavingPriorExpansions(t *testing.T) {
 	in = append(in, 0x80, 0xff, 0x0f, 0x08)
 
 	r := NewReader(bytes.NewReader(in), LSB, 8)
-	nDecoded, err := io.Copy(ioutil.Discard, r)
+	nDecoded, err := io.Copy(io.Discard, r)
 	if err != nil {
 		t.Fatalf("Copy: %v", err)
 	}
@@ -246,7 +246,7 @@ func BenchmarkDecoder(b *testing.B) {
 			runtime.GC()
 			b.StartTimer()
 			for i := 0; i < b.N; i++ {
-				io.Copy(ioutil.Discard, NewReader(bytes.NewReader(buf1), LSB, 8))
+				io.Copy(io.Discard, NewReader(bytes.NewReader(buf1), LSB, 8))
 			}
 		})
 	}
diff --git a/src/compress/lzw/writer_test.go b/src/compress/lzw/writer_test.go
index 4979f8b3521..33a28bdd3ab 100644
--- a/src/compress/lzw/writer_test.go
+++ b/src/compress/lzw/writer_test.go
@@ -67,8 +67,8 @@ func testFile(t *testing.T, fn string, order Order, litWidth int) {
 	defer lzwr.Close()
 
 	// Compare the two.
-	b0, err0 := ioutil.ReadAll(golden)
-	b1, err1 := ioutil.ReadAll(lzwr)
+	b0, err0 := io.ReadAll(golden)
+	b1, err1 := io.ReadAll(lzwr)
 	if err0 != nil {
 		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
 		return
@@ -107,7 +107,7 @@ func TestWriter(t *testing.T) {
 }
 
 func TestWriterReturnValues(t *testing.T) {
-	w := NewWriter(ioutil.Discard, LSB, 8)
+	w := NewWriter(io.Discard, LSB, 8)
 	n, err := w.Write([]byte("asdf"))
 	if n != 4 || err != nil {
 		t.Errorf("got %d, %v, want 4, nil", n, err)
@@ -115,7 +115,7 @@ func TestWriterReturnValues(t *testing.T) {
 }
 
 func TestSmallLitWidth(t *testing.T) {
-	w := NewWriter(ioutil.Discard, LSB, 2)
+	w := NewWriter(io.Discard, LSB, 2)
 	if _, err := w.Write([]byte{0x03}); err != nil {
 		t.Fatalf("write a byte < 1<<2: %v", err)
 	}
@@ -148,7 +148,7 @@ func BenchmarkEncoder(b *testing.B) {
 		b.Run(fmt.Sprint("1e", e), func(b *testing.B) {
 			b.SetBytes(int64(n))
 			for i := 0; i < b.N; i++ {
-				w := NewWriter(ioutil.Discard, LSB, 8)
+				w := NewWriter(io.Discard, LSB, 8)
 				w.Write(buf1)
 				w.Close()
 			}
diff --git a/src/compress/zlib/writer_test.go b/src/compress/zlib/writer_test.go
index d5019740783..c5187291460 100644
--- a/src/compress/zlib/writer_test.go
+++ b/src/compress/zlib/writer_test.go
@@ -34,7 +34,7 @@ func testFileLevelDict(t *testing.T, fn string, level int, d string) {
 		return
 	}
 	defer golden.Close()
-	b0, err0 := ioutil.ReadAll(golden)
+	b0, err0 := io.ReadAll(golden)
 	if err0 != nil {
 		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0)
 		return
@@ -74,7 +74,7 @@ func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) {
 	defer zlibr.Close()
 
 	// Compare the decompressed data.
-	b1, err1 := ioutil.ReadAll(zlibr)
+	b1, err1 := io.ReadAll(zlibr)
 	if err1 != nil {
 		t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1)
 		return
diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go
index f55cd16ca81..224edcd5c79 100644
--- a/src/crypto/tls/handshake_test.go
+++ b/src/crypto/tls/handshake_test.go
@@ -403,7 +403,7 @@ func testHandshake(t *testing.T, clientConfig, serverConfig *Config) (serverStat
 		}
 		defer cli.Close()
 		clientState = cli.ConnectionState()
-		buf, err := ioutil.ReadAll(cli)
+		buf, err := io.ReadAll(cli)
 		if err != nil {
 			t.Errorf("failed to call cli.Read: %v", err)
 		}
diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go
index 4ab8a430ba3..9995538871e 100644
--- a/src/crypto/tls/tls_test.go
+++ b/src/crypto/tls/tls_test.go
@@ -14,7 +14,6 @@ import (
 	"fmt"
 	"internal/testenv"
 	"io"
-	"io/ioutil"
 	"math"
 	"net"
 	"os"
@@ -594,7 +593,7 @@ func TestConnCloseWrite(t *testing.T) {
 		}
 		defer srv.Close()
 
-		data, err := ioutil.ReadAll(srv)
+		data, err := io.ReadAll(srv)
 		if err != nil {
 			return err
 		}
@@ -635,7 +634,7 @@ func TestConnCloseWrite(t *testing.T) {
 			return fmt.Errorf("CloseWrite error = %v; want errShutdown", err)
 		}
 
-		data, err := ioutil.ReadAll(conn)
+		data, err := io.ReadAll(conn)
 		if err != nil {
 			return err
 		}
@@ -698,7 +697,7 @@ func TestWarningAlertFlood(t *testing.T) {
 		}
 		defer srv.Close()
 
-		_, err = ioutil.ReadAll(srv)
+		_, err = io.ReadAll(srv)
 		if err == nil {
 			return errors.New("unexpected lack of error from server")
 		}
diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go
index 34dd5d5b227..0641c073ead 100644
--- a/src/crypto/x509/root_ios_gen.go
+++ b/src/crypto/x509/root_ios_gen.go
@@ -81,7 +81,7 @@ func main() {
 			continue
 		}
 
-		der, err := ioutil.ReadAll(tr)
+		der, err := io.ReadAll(tr)
 		if err != nil {
 			log.Fatal(err)
 		}
diff --git a/src/debug/gosym/pclntab_test.go b/src/debug/gosym/pclntab_test.go
index 33772c78136..f93a5bf5e52 100644
--- a/src/debug/gosym/pclntab_test.go
+++ b/src/debug/gosym/pclntab_test.go
@@ -9,6 +9,7 @@ import (
 	"compress/gzip"
 	"debug/elf"
 	"internal/testenv"
+	"io"
 	"io/ioutil"
 	"os"
 	"os/exec"
@@ -287,7 +288,7 @@ func Test115PclnParsing(t *testing.T) {
 		t.Fatal(err)
 	}
 	var dat []byte
-	dat, err = ioutil.ReadAll(gzReader)
+	dat, err = io.ReadAll(gzReader)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/encoding/ascii85/ascii85_test.go b/src/encoding/ascii85/ascii85_test.go
index 1a3a87a596d..c6371039426 100644
--- a/src/encoding/ascii85/ascii85_test.go
+++ b/src/encoding/ascii85/ascii85_test.go
@@ -7,7 +7,6 @@ package ascii85
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -118,7 +117,7 @@ func TestDecode(t *testing.T) {
 func TestDecoder(t *testing.T) {
 	for _, p := range pairs {
 		decoder := NewDecoder(strings.NewReader(p.encoded))
-		dbuf, err := ioutil.ReadAll(decoder)
+		dbuf, err := io.ReadAll(decoder)
 		if err != nil {
 			t.Fatal("Read failed", err)
 		}
@@ -187,7 +186,7 @@ func TestBig(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Encoder.Close() = %v want nil", err)
 	}
-	decoded, err := ioutil.ReadAll(NewDecoder(encoded))
+	decoded, err := io.ReadAll(NewDecoder(encoded))
 	if err != nil {
 		t.Fatalf("io.ReadAll(NewDecoder(...)): %v", err)
 	}
@@ -205,7 +204,7 @@ func TestBig(t *testing.T) {
 
 func TestDecoderInternalWhitespace(t *testing.T) {
 	s := strings.Repeat(" ", 2048) + "z"
-	decoded, err := ioutil.ReadAll(NewDecoder(strings.NewReader(s)))
+	decoded, err := io.ReadAll(NewDecoder(strings.NewReader(s)))
 	if err != nil {
 		t.Errorf("Decode gave error %v", err)
 	}
diff --git a/src/encoding/base32/base32_test.go b/src/encoding/base32/base32_test.go
index 0b611db0b24..8fb22b90781 100644
--- a/src/encoding/base32/base32_test.go
+++ b/src/encoding/base32/base32_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"errors"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -361,9 +360,9 @@ func TestBig(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Encoder.Close() = %v want nil", err)
 	}
-	decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded))
+	decoded, err := io.ReadAll(NewDecoder(StdEncoding, encoded))
 	if err != nil {
-		t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
+		t.Fatalf("io.ReadAll(NewDecoder(...)): %v", err)
 	}
 
 	if !bytes.Equal(raw, decoded) {
@@ -428,14 +427,14 @@ LNEBUWIIDFON2CA3DBMJXXE5LNFY==
 	encodedShort := strings.ReplaceAll(encoded, "\n", "")
 
 	dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
-	res1, err := ioutil.ReadAll(dec)
+	res1, err := io.ReadAll(dec)
 	if err != nil {
 		t.Errorf("ReadAll failed: %v", err)
 	}
 
 	dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort))
 	var res2 []byte
-	res2, err = ioutil.ReadAll(dec)
+	res2, err = io.ReadAll(dec)
 	if err != nil {
 		t.Errorf("ReadAll failed: %v", err)
 	}
@@ -619,7 +618,7 @@ func TestBufferedDecodingSameError(t *testing.T) {
 			}()
 
 			decoder := NewDecoder(StdEncoding, pr)
-			_, err := ioutil.ReadAll(decoder)
+			_, err := io.ReadAll(decoder)
 
 			if err != testcase.expected {
 				t.Errorf("Expected %v, got %v; case %s %+v", testcase.expected, err, testcase.prefix, chunks)
@@ -718,7 +717,7 @@ func TestDecodeReadAll(t *testing.T) {
 				encoded = strings.ReplaceAll(encoded, "=", "")
 			}
 
-			decReader, err := ioutil.ReadAll(NewDecoder(encoding, strings.NewReader(encoded)))
+			decReader, err := io.ReadAll(NewDecoder(encoding, strings.NewReader(encoded)))
 			if err != nil {
 				t.Errorf("NewDecoder error: %v", err)
 			}
diff --git a/src/encoding/base64/base64_test.go b/src/encoding/base64/base64_test.go
index c2c9478a437..51047402bd4 100644
--- a/src/encoding/base64/base64_test.go
+++ b/src/encoding/base64/base64_test.go
@@ -9,7 +9,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"reflect"
 	"runtime/debug"
 	"strings"
@@ -324,9 +323,9 @@ func TestBig(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Encoder.Close() = %v want nil", err)
 	}
-	decoded, err := ioutil.ReadAll(NewDecoder(StdEncoding, encoded))
+	decoded, err := io.ReadAll(NewDecoder(StdEncoding, encoded))
 	if err != nil {
-		t.Fatalf("ioutil.ReadAll(NewDecoder(...)): %v", err)
+		t.Fatalf("io.ReadAll(NewDecoder(...)): %v", err)
 	}
 
 	if !bytes.Equal(raw, decoded) {
@@ -403,7 +402,7 @@ func TestDecoderIssue3577(t *testing.T) {
 	})
 	errc := make(chan error, 1)
 	go func() {
-		_, err := ioutil.ReadAll(d)
+		_, err := io.ReadAll(d)
 		errc <- err
 	}()
 	select {
@@ -436,14 +435,14 @@ bqbPb06551Y4
 	encodedShort := strings.ReplaceAll(encoded, "\n", "")
 
 	dec := NewDecoder(StdEncoding, strings.NewReader(encoded))
-	res1, err := ioutil.ReadAll(dec)
+	res1, err := io.ReadAll(dec)
 	if err != nil {
 		t.Errorf("ReadAll failed: %v", err)
 	}
 
 	dec = NewDecoder(StdEncoding, strings.NewReader(encodedShort))
 	var res2 []byte
-	res2, err = ioutil.ReadAll(dec)
+	res2, err = io.ReadAll(dec)
 	if err != nil {
 		t.Errorf("ReadAll failed: %v", err)
 	}
@@ -517,14 +516,14 @@ func TestDecoderRaw(t *testing.T) {
 
 	// Through reader. Used to fail.
 	r := NewDecoder(RawURLEncoding, bytes.NewReader([]byte(source)))
-	dec2, err := ioutil.ReadAll(io.LimitReader(r, 100))
+	dec2, err := io.ReadAll(io.LimitReader(r, 100))
 	if err != nil || !bytes.Equal(dec2, want) {
 		t.Errorf("reading NewDecoder(RawURLEncoding, %q) = %x, %v, want %x, nil", source, dec2, err, want)
 	}
 
 	// Should work with padding.
 	r = NewDecoder(URLEncoding, bytes.NewReader([]byte(source+"==")))
-	dec3, err := ioutil.ReadAll(r)
+	dec3, err := io.ReadAll(r)
 	if err != nil || !bytes.Equal(dec3, want) {
 		t.Errorf("reading NewDecoder(URLEncoding, %q) = %x, %v, want %x, nil", source+"==", dec3, err, want)
 	}
diff --git a/src/encoding/binary/binary_test.go b/src/encoding/binary/binary_test.go
index 5971e0966ad..83af89e8a7c 100644
--- a/src/encoding/binary/binary_test.go
+++ b/src/encoding/binary/binary_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"math"
 	"reflect"
 	"strings"
@@ -524,7 +523,7 @@ func BenchmarkWriteStruct(b *testing.B) {
 	b.SetBytes(int64(Size(&s)))
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Write(ioutil.Discard, BigEndian, &s)
+		Write(io.Discard, BigEndian, &s)
 	}
 }
 
diff --git a/src/encoding/gob/encoder_test.go b/src/encoding/gob/encoder_test.go
index 825f0d6f03e..fe2774948a7 100644
--- a/src/encoding/gob/encoder_test.go
+++ b/src/encoding/gob/encoder_test.go
@@ -8,7 +8,7 @@ import (
 	"bytes"
 	"encoding/hex"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"reflect"
 	"strings"
 	"testing"
@@ -938,7 +938,7 @@ func encodeAndRecover(value interface{}) (encodeErr, panicErr error) {
 		}
 	}()
 
-	encodeErr = NewEncoder(ioutil.Discard).Encode(value)
+	encodeErr = NewEncoder(io.Discard).Encode(value)
 	return
 }
 
diff --git a/src/encoding/hex/hex_test.go b/src/encoding/hex/hex_test.go
index 31e3f689365..7593e20db58 100644
--- a/src/encoding/hex/hex_test.go
+++ b/src/encoding/hex/hex_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -150,7 +149,7 @@ func TestEncoderDecoder(t *testing.T) {
 func TestDecoderErr(t *testing.T) {
 	for _, tt := range errTests {
 		dec := NewDecoder(strings.NewReader(tt.in))
-		out, err := ioutil.ReadAll(dec)
+		out, err := io.ReadAll(dec)
 		wantErr := tt.err
 		// Decoder is reading from stream, so it reports io.ErrUnexpectedEOF instead of ErrLength.
 		if wantErr == ErrLength {
diff --git a/src/encoding/json/bench_test.go b/src/encoding/json/bench_test.go
index 4a5fe7ec84e..73c7b09fb6f 100644
--- a/src/encoding/json/bench_test.go
+++ b/src/encoding/json/bench_test.go
@@ -15,7 +15,7 @@ import (
 	"compress/gzip"
 	"fmt"
 	"internal/testenv"
-	"io/ioutil"
+	"io"
 	"os"
 	"reflect"
 	"runtime"
@@ -52,7 +52,7 @@ func codeInit() {
 	if err != nil {
 		panic(err)
 	}
-	data, err := ioutil.ReadAll(gz)
+	data, err := io.ReadAll(gz)
 	if err != nil {
 		panic(err)
 	}
@@ -89,7 +89,7 @@ func BenchmarkCodeEncoder(b *testing.B) {
 		b.StartTimer()
 	}
 	b.RunParallel(func(pb *testing.PB) {
-		enc := NewEncoder(ioutil.Discard)
+		enc := NewEncoder(io.Discard)
 		for pb.Next() {
 			if err := enc.Encode(&codeStruct); err != nil {
 				b.Fatal("Encode:", err)
@@ -399,7 +399,7 @@ func BenchmarkEncodeMarshaler(b *testing.B) {
 	}{}
 
 	b.RunParallel(func(pb *testing.PB) {
-		enc := NewEncoder(ioutil.Discard)
+		enc := NewEncoder(io.Discard)
 
 		for pb.Next() {
 			if err := enc.Encode(&m); err != nil {
diff --git a/src/encoding/json/stream_test.go b/src/encoding/json/stream_test.go
index c9e5334337d..c284f2d9650 100644
--- a/src/encoding/json/stream_test.go
+++ b/src/encoding/json/stream_test.go
@@ -7,7 +7,6 @@ package json
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"net/http"
@@ -215,7 +214,7 @@ func TestDecoderBuffered(t *testing.T) {
 	if m.Name != "Gopher" {
 		t.Errorf("Name = %q; want Gopher", m.Name)
 	}
-	rest, err := ioutil.ReadAll(d.Buffered())
+	rest, err := io.ReadAll(d.Buffered())
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -318,7 +317,7 @@ func BenchmarkEncoderEncode(b *testing.B) {
 	v := &T{"foo", "bar"}
 	b.RunParallel(func(pb *testing.PB) {
 		for pb.Next() {
-			if err := NewEncoder(ioutil.Discard).Encode(v); err != nil {
+			if err := NewEncoder(io.Discard).Encode(v); err != nil {
 				b.Fatal(err)
 			}
 		}
diff --git a/src/encoding/pem/pem_test.go b/src/encoding/pem/pem_test.go
index 8515b46498d..b2b6b15e736 100644
--- a/src/encoding/pem/pem_test.go
+++ b/src/encoding/pem/pem_test.go
@@ -6,7 +6,7 @@ package pem
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"reflect"
 	"strings"
 	"testing"
@@ -271,7 +271,7 @@ func BenchmarkEncode(b *testing.B) {
 	data := &Block{Bytes: make([]byte, 65536)}
 	b.SetBytes(int64(len(data.Bytes)))
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, data)
+		Encode(io.Discard, data)
 	}
 }
 
diff --git a/src/flag/flag_test.go b/src/flag/flag_test.go
index 27930645116..06cab79405a 100644
--- a/src/flag/flag_test.go
+++ b/src/flag/flag_test.go
@@ -10,7 +10,6 @@ import (
 	"fmt"
 	"internal/testenv"
 	"io"
-	"io/ioutil"
 	"os"
 	"os/exec"
 	"runtime"
@@ -545,7 +544,7 @@ func TestGetters(t *testing.T) {
 func TestParseError(t *testing.T) {
 	for _, typ := range []string{"bool", "int", "int64", "uint", "uint64", "float64", "duration"} {
 		fs := NewFlagSet("parse error test", ContinueOnError)
-		fs.SetOutput(ioutil.Discard)
+		fs.SetOutput(io.Discard)
 		_ = fs.Bool("bool", false, "")
 		_ = fs.Int("int", 0, "")
 		_ = fs.Int64("int64", 0, "")
@@ -576,7 +575,7 @@ func TestRangeError(t *testing.T) {
 	}
 	for _, arg := range bad {
 		fs := NewFlagSet("parse error test", ContinueOnError)
-		fs.SetOutput(ioutil.Discard)
+		fs.SetOutput(io.Discard)
 		_ = fs.Int("int", 0, "")
 		_ = fs.Int64("int64", 0, "")
 		_ = fs.Uint("uint", 0, "")
diff --git a/src/go/internal/gccgoimporter/importer.go b/src/go/internal/gccgoimporter/importer.go
index 2494fd7b2a5..94f2defd8d3 100644
--- a/src/go/internal/gccgoimporter/importer.go
+++ b/src/go/internal/gccgoimporter/importer.go
@@ -221,7 +221,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
 		// Excluded for now: Standard gccgo doesn't support this import format currently.
 		// case goimporterMagic:
 		// 	var data []byte
-		// 	data, err = ioutil.ReadAll(reader)
+		// 	data, err = io.ReadAll(reader)
 		// 	if err != nil {
 		// 		return
 		// 	}
diff --git a/src/go/internal/gcimporter/gcimporter.go b/src/go/internal/gcimporter/gcimporter.go
index fda15eaaaed..b74daca2463 100644
--- a/src/go/internal/gcimporter/gcimporter.go
+++ b/src/go/internal/gcimporter/gcimporter.go
@@ -12,7 +12,6 @@ import (
 	"go/token"
 	"go/types"
 	"io"
-	"io/ioutil"
 	"os"
 	"path/filepath"
 	"strings"
@@ -147,7 +146,7 @@ func Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDi
 
 	case "$$B\n":
 		var data []byte
-		data, err = ioutil.ReadAll(buf)
+		data, err = io.ReadAll(buf)
 		if err != nil {
 			break
 		}
diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go
index b2d834fdecf..cc7e455c4db 100644
--- a/src/go/parser/interface.go
+++ b/src/go/parser/interface.go
@@ -35,7 +35,7 @@ func readSource(filename string, src interface{}) ([]byte, error) {
 				return s.Bytes(), nil
 			}
 		case io.Reader:
-			return ioutil.ReadAll(s)
+			return io.ReadAll(s)
 		}
 		return nil, errors.New("invalid source")
 	}
diff --git a/src/go/printer/performance_test.go b/src/go/printer/performance_test.go
index 2e67154e6b4..e23de3fbaed 100644
--- a/src/go/printer/performance_test.go
+++ b/src/go/printer/performance_test.go
@@ -53,6 +53,6 @@ func BenchmarkPrint(b *testing.B) {
 		initialize()
 	}
 	for i := 0; i < b.N; i++ {
-		testprint(ioutil.Discard, testfile)
+		testprint(io.Discard, testfile)
 	}
 }
diff --git a/src/go/types/gotype.go b/src/go/types/gotype.go
index eacf68f52f2..52709df17bd 100644
--- a/src/go/types/gotype.go
+++ b/src/go/types/gotype.go
@@ -88,7 +88,7 @@ import (
 	"go/scanner"
 	"go/token"
 	"go/types"
-	"io/ioutil"
+	"io"
 	"os"
 	"path/filepath"
 	"sync"
@@ -191,7 +191,7 @@ func parse(filename string, src interface{}) (*ast.File, error) {
 }
 
 func parseStdin() (*ast.File, error) {
-	src, err := ioutil.ReadAll(os.Stdin)
+	src, err := io.ReadAll(os.Stdin)
 	if err != nil {
 		return nil, err
 	}
diff --git a/src/html/template/clone_test.go b/src/html/template/clone_test.go
index c9c619f0d45..7cb1b9ca062 100644
--- a/src/html/template/clone_test.go
+++ b/src/html/template/clone_test.go
@@ -8,7 +8,7 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"strings"
 	"sync"
 	"testing"
@@ -171,7 +171,7 @@ func TestCloneThenParse(t *testing.T) {
 		t.Error("adding a template to a clone added it to the original")
 	}
 	// double check that the embedded template isn't available in the original
-	err := t0.ExecuteTemplate(ioutil.Discard, "a", nil)
+	err := t0.ExecuteTemplate(io.Discard, "a", nil)
 	if err == nil {
 		t.Error("expected 'no such template' error")
 	}
@@ -185,13 +185,13 @@ func TestFuncMapWorksAfterClone(t *testing.T) {
 
 	// get the expected error output (no clone)
 	uncloned := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
-	wantErr := uncloned.Execute(ioutil.Discard, nil)
+	wantErr := uncloned.Execute(io.Discard, nil)
 
 	// toClone must be the same as uncloned. It has to be recreated from scratch,
 	// since cloning cannot occur after execution.
 	toClone := Must(New("").Funcs(funcs).Parse("{{customFunc}}"))
 	cloned := Must(toClone.Clone())
-	gotErr := cloned.Execute(ioutil.Discard, nil)
+	gotErr := cloned.Execute(io.Discard, nil)
 
 	if wantErr.Error() != gotErr.Error() {
 		t.Errorf("clone error message mismatch want %q got %q", wantErr, gotErr)
@@ -213,7 +213,7 @@ func TestTemplateCloneExecuteRace(t *testing.T) {
 		go func() {
 			defer wg.Done()
 			for i := 0; i < 100; i++ {
-				if err := tmpl.Execute(ioutil.Discard, "data"); err != nil {
+				if err := tmpl.Execute(io.Discard, "data"); err != nil {
 					panic(err)
 				}
 			}
@@ -237,7 +237,7 @@ func TestCloneGrowth(t *testing.T) {
 	tmpl = Must(tmpl.Clone())
 	Must(tmpl.Parse(`{{define "B"}}Text{{end}}`))
 	for i := 0; i < 10; i++ {
-		tmpl.Execute(ioutil.Discard, nil)
+		tmpl.Execute(io.Discard, nil)
 	}
 	if len(tmpl.DefinedTemplates()) > 200 {
 		t.Fatalf("too many templates: %v", len(tmpl.DefinedTemplates()))
@@ -257,7 +257,7 @@ func TestCloneRedefinedName(t *testing.T) {
 	for i := 0; i < 2; i++ {
 		t2 := Must(t1.Clone())
 		t2 = Must(t2.New(fmt.Sprintf("%d", i)).Parse(page))
-		err := t2.Execute(ioutil.Discard, nil)
+		err := t2.Execute(io.Discard, nil)
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/src/html/template/exec_test.go b/src/html/template/exec_test.go
index fc76ee40e56..232945a0bb1 100644
--- a/src/html/template/exec_test.go
+++ b/src/html/template/exec_test.go
@@ -11,7 +11,7 @@ import (
 	"errors"
 	"flag"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"reflect"
 	"strings"
 	"testing"
@@ -1335,7 +1335,7 @@ func TestExecuteGivesExecError(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = tmpl.Execute(ioutil.Discard, 0)
+	err = tmpl.Execute(io.Discard, 0)
 	if err == nil {
 		t.Fatal("expected error; got none")
 	}
@@ -1481,7 +1481,7 @@ func TestEvalFieldErrors(t *testing.T) {
 	for _, tc := range tests {
 		t.Run(tc.name, func(t *testing.T) {
 			tmpl := Must(New("tmpl").Parse(tc.src))
-			err := tmpl.Execute(ioutil.Discard, tc.value)
+			err := tmpl.Execute(io.Discard, tc.value)
 			got := ""
 			if err != nil {
 				got = err.Error()
@@ -1498,7 +1498,7 @@ func TestMaxExecDepth(t *testing.T) {
 		t.Skip("skipping in -short mode")
 	}
 	tmpl := Must(New("tmpl").Parse(`{{template "tmpl" .}}`))
-	err := tmpl.Execute(ioutil.Discard, nil)
+	err := tmpl.Execute(io.Discard, nil)
 	got := ""
 	if err != nil {
 		got = err.Error()
diff --git a/src/image/gif/writer_test.go b/src/image/gif/writer_test.go
index 1e622b3674e..af0105c6bea 100644
--- a/src/image/gif/writer_test.go
+++ b/src/image/gif/writer_test.go
@@ -11,7 +11,7 @@ import (
 	"image/color/palette"
 	"image/draw"
 	_ "image/png"
-	"io/ioutil"
+	"io"
 	"math/rand"
 	"os"
 	"reflect"
@@ -285,7 +285,7 @@ func TestEncodeMismatchDelay(t *testing.T) {
 		Image: images,
 		Delay: make([]int, 1),
 	}
-	if err := EncodeAll(ioutil.Discard, g0); err == nil {
+	if err := EncodeAll(io.Discard, g0); err == nil {
 		t.Error("expected error from mismatched delay and image slice lengths")
 	}
 
@@ -297,13 +297,13 @@ func TestEncodeMismatchDelay(t *testing.T) {
 	for i := range g1.Disposal {
 		g1.Disposal[i] = DisposalNone
 	}
-	if err := EncodeAll(ioutil.Discard, g1); err == nil {
+	if err := EncodeAll(io.Discard, g1); err == nil {
 		t.Error("expected error from mismatched disposal and image slice lengths")
 	}
 }
 
 func TestEncodeZeroGIF(t *testing.T) {
-	if err := EncodeAll(ioutil.Discard, &GIF{}); err == nil {
+	if err := EncodeAll(io.Discard, &GIF{}); err == nil {
 		t.Error("expected error from providing empty gif")
 	}
 }
@@ -324,7 +324,7 @@ func TestEncodeAllFramesOutOfBounds(t *testing.T) {
 				Height: upperBound,
 			},
 		}
-		err := EncodeAll(ioutil.Discard, g)
+		err := EncodeAll(io.Discard, g)
 		if upperBound >= 8 {
 			if err != nil {
 				t.Errorf("upperBound=%d: %v", upperBound, err)
@@ -430,7 +430,7 @@ func TestEncodeImplicitConfigSize(t *testing.T) {
 			Image: images,
 			Delay: make([]int, len(images)),
 		}
-		err := EncodeAll(ioutil.Discard, g)
+		err := EncodeAll(io.Discard, g)
 		if lowerBound >= 0 {
 			if err != nil {
 				t.Errorf("lowerBound=%d: %v", lowerBound, err)
@@ -509,7 +509,7 @@ func TestEncodeBadPalettes(t *testing.T) {
 				}
 			}
 
-			err := EncodeAll(ioutil.Discard, &GIF{
+			err := EncodeAll(io.Discard, &GIF{
 				Image: []*image.Paletted{
 					image.NewPaletted(image.Rect(0, 0, w, h), pal),
 				},
@@ -668,7 +668,7 @@ func BenchmarkEncodeRandomPaletted(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, paletted, nil)
+		Encode(io.Discard, paletted, nil)
 	}
 }
 
@@ -691,7 +691,7 @@ func BenchmarkEncodeRandomRGBA(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, rgba, nil)
+		Encode(io.Discard, rgba, nil)
 	}
 }
 
@@ -708,7 +708,7 @@ func BenchmarkEncodeRealisticPaletted(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, paletted, nil)
+		Encode(io.Discard, paletted, nil)
 	}
 }
 
@@ -729,6 +729,6 @@ func BenchmarkEncodeRealisticRGBA(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, rgba, nil)
+		Encode(io.Discard, rgba, nil)
 	}
 }
diff --git a/src/image/jpeg/writer_test.go b/src/image/jpeg/writer_test.go
index 3aff7426325..abd5e323339 100644
--- a/src/image/jpeg/writer_test.go
+++ b/src/image/jpeg/writer_test.go
@@ -10,7 +10,7 @@ import (
 	"image"
 	"image/color"
 	"image/png"
-	"io/ioutil"
+	"io"
 	"math/rand"
 	"os"
 	"testing"
@@ -261,7 +261,7 @@ func BenchmarkEncodeRGBA(b *testing.B) {
 	b.ResetTimer()
 	options := &Options{Quality: 90}
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img, options)
+		Encode(io.Discard, img, options)
 	}
 }
 
@@ -283,6 +283,6 @@ func BenchmarkEncodeYCbCr(b *testing.B) {
 	b.ResetTimer()
 	options := &Options{Quality: 90}
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img, options)
+		Encode(io.Discard, img, options)
 	}
 }
diff --git a/src/image/png/writer_test.go b/src/image/png/writer_test.go
index 5d131ff823a..47aa8613398 100644
--- a/src/image/png/writer_test.go
+++ b/src/image/png/writer_test.go
@@ -12,7 +12,6 @@ import (
 	"image"
 	"image/color"
 	"io"
-	"io/ioutil"
 	"testing"
 )
 
@@ -169,7 +168,7 @@ func TestWriterPaletted(t *testing.T) {
 						t.Error(err)
 						return
 					}
-					n, err := io.Copy(ioutil.Discard, r)
+					n, err := io.Copy(io.Discard, r)
 					if err != nil {
 						t.Errorf("got error while reading image data: %v", err)
 					}
@@ -234,7 +233,7 @@ func BenchmarkEncodeGray(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img)
+		Encode(io.Discard, img)
 	}
 }
 
@@ -259,7 +258,7 @@ func BenchmarkEncodeGrayWithBufferPool(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		e.Encode(ioutil.Discard, img)
+		e.Encode(io.Discard, img)
 	}
 }
 
@@ -279,7 +278,7 @@ func BenchmarkEncodeNRGBOpaque(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img)
+		Encode(io.Discard, img)
 	}
 }
 
@@ -292,7 +291,7 @@ func BenchmarkEncodeNRGBA(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img)
+		Encode(io.Discard, img)
 	}
 }
 
@@ -305,7 +304,7 @@ func BenchmarkEncodePaletted(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img)
+		Encode(io.Discard, img)
 	}
 }
 
@@ -325,7 +324,7 @@ func BenchmarkEncodeRGBOpaque(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img)
+		Encode(io.Discard, img)
 	}
 }
 
@@ -338,6 +337,6 @@ func BenchmarkEncodeRGBA(b *testing.B) {
 	b.ReportAllocs()
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
-		Encode(ioutil.Discard, img)
+		Encode(io.Discard, img)
 	}
 }
diff --git a/src/internal/obscuretestdata/obscuretestdata.go b/src/internal/obscuretestdata/obscuretestdata.go
index 512f3759b4c..06cd1df22c1 100644
--- a/src/internal/obscuretestdata/obscuretestdata.go
+++ b/src/internal/obscuretestdata/obscuretestdata.go
@@ -47,5 +47,5 @@ func ReadFile(name string) ([]byte, error) {
 		return nil, err
 	}
 	defer f.Close()
-	return ioutil.ReadAll(base64.NewDecoder(base64.StdEncoding, f))
+	return io.ReadAll(base64.NewDecoder(base64.StdEncoding, f))
 }
diff --git a/src/internal/profile/profile.go b/src/internal/profile/profile.go
index a6275bc6de4..29568aa4b5f 100644
--- a/src/internal/profile/profile.go
+++ b/src/internal/profile/profile.go
@@ -12,7 +12,6 @@ import (
 	"compress/gzip"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"regexp"
 	"strings"
 	"time"
@@ -125,7 +124,7 @@ type Function struct {
 // may be a gzip-compressed encoded protobuf or one of many legacy
 // profile formats which may be unsupported in the future.
 func Parse(r io.Reader) (*Profile, error) {
-	orig, err := ioutil.ReadAll(r)
+	orig, err := io.ReadAll(r)
 	if err != nil {
 		return nil, err
 	}
@@ -136,7 +135,7 @@ func Parse(r io.Reader) (*Profile, error) {
 		if err != nil {
 			return nil, fmt.Errorf("decompressing profile: %v", err)
 		}
-		data, err := ioutil.ReadAll(gz)
+		data, err := io.ReadAll(gz)
 		if err != nil {
 			return nil, fmt.Errorf("decompressing profile: %v", err)
 		}
diff --git a/src/io/example_test.go b/src/io/example_test.go
index 47060324298..6d338acd140 100644
--- a/src/io/example_test.go
+++ b/src/io/example_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"os"
 	"strings"
@@ -141,7 +140,7 @@ func ExampleTeeReader() {
 	r = io.TeeReader(r, os.Stdout)
 
 	// Everything read from r will be copied to stdout.
-	ioutil.ReadAll(r)
+	io.ReadAll(r)
 
 	// Output:
 	// some io.Reader stream to be read
@@ -245,7 +244,7 @@ func ExamplePipe() {
 func ExampleReadAll() {
 	r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
 
-	b, err := ioutil.ReadAll(r)
+	b, err := io.ReadAll(r)
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/src/io/io.go b/src/io/io.go
index 269ebf6ed06..ffd3cedc254 100644
--- a/src/io/io.go
+++ b/src/io/io.go
@@ -573,7 +573,7 @@ var Discard Writer = discard{}
 type discard struct{}
 
 // discard implements ReaderFrom as an optimization so Copy to
-// ioutil.Discard can avoid doing unnecessary work.
+// io.Discard can avoid doing unnecessary work.
 var _ ReaderFrom = discard{}
 
 func (discard) Write(p []byte) (int, error) {
diff --git a/src/io/multi_test.go b/src/io/multi_test.go
index f05d5f74ef9..909b6d8be28 100644
--- a/src/io/multi_test.go
+++ b/src/io/multi_test.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	. "io"
-	"io/ioutil"
 	"runtime"
 	"strings"
 	"testing"
@@ -142,7 +141,7 @@ func testMultiWriter(t *testing.T, sink interface {
 	}
 }
 
-// writerFunc is an io.Writer implemented by the underlying func.
+// writerFunc is an Writer implemented by the underlying func.
 type writerFunc func(p []byte) (int, error)
 
 func (f writerFunc) Write(p []byte) (int, error) {
@@ -196,7 +195,7 @@ func TestMultiReaderCopy(t *testing.T) {
 	slice := []Reader{strings.NewReader("hello world")}
 	r := MultiReader(slice...)
 	slice[0] = nil
-	data, err := ioutil.ReadAll(r)
+	data, err := ReadAll(r)
 	if err != nil || string(data) != "hello world" {
 		t.Errorf("ReadAll() = %q, %v, want %q, nil", data, err, "hello world")
 	}
@@ -217,7 +216,7 @@ func TestMultiWriterCopy(t *testing.T) {
 	}
 }
 
-// readerFunc is an io.Reader implemented by the underlying func.
+// readerFunc is an Reader implemented by the underlying func.
 type readerFunc func(p []byte) (int, error)
 
 func (f readerFunc) Read(p []byte) (int, error) {
@@ -261,7 +260,7 @@ func TestMultiReaderFlatten(t *testing.T) {
 }
 
 // byteAndEOFReader is a Reader which reads one byte (the underlying
-// byte) and io.EOF at once in its Read call.
+// byte) and EOF at once in its Read call.
 type byteAndEOFReader byte
 
 func (b byteAndEOFReader) Read(p []byte) (n int, err error) {
@@ -276,7 +275,7 @@ func (b byteAndEOFReader) Read(p []byte) (n int, err error) {
 
 // This used to yield bytes forever; issue 16795.
 func TestMultiReaderSingleByteWithEOF(t *testing.T) {
-	got, err := ioutil.ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10))
+	got, err := ReadAll(LimitReader(MultiReader(byteAndEOFReader('a'), byteAndEOFReader('b')), 10))
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/mime/encodedword_test.go b/src/mime/encodedword_test.go
index 6c54e502adb..2a98794380f 100644
--- a/src/mime/encodedword_test.go
+++ b/src/mime/encodedword_test.go
@@ -7,7 +7,6 @@ package mime
 import (
 	"errors"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -182,7 +181,7 @@ func TestCharsetDecoder(t *testing.T) {
 				if charset != test.charsets[i] {
 					t.Errorf("DecodeHeader(%q), got charset %q, want %q", test.src, charset, test.charsets[i])
 				}
-				content, err := ioutil.ReadAll(input)
+				content, err := io.ReadAll(input)
 				if err != nil {
 					t.Errorf("DecodeHeader(%q), error in reader: %v", test.src, err)
 				}
diff --git a/src/mime/example_test.go b/src/mime/example_test.go
index 85795976f09..8a96873e5dc 100644
--- a/src/mime/example_test.go
+++ b/src/mime/example_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime"
 )
 
@@ -38,7 +37,7 @@ func ExampleWordDecoder_Decode() {
 			// Fake character set for example.
 			// Real use would integrate with packages such
 			// as code.google.com/p/go-charset
-			content, err := ioutil.ReadAll(input)
+			content, err := io.ReadAll(input)
 			if err != nil {
 				return nil, err
 			}
@@ -77,7 +76,7 @@ func ExampleWordDecoder_DecodeHeader() {
 			// Fake character set for example.
 			// Real use would integrate with packages such
 			// as code.google.com/p/go-charset
-			content, err := ioutil.ReadAll(input)
+			content, err := io.ReadAll(input)
 			if err != nil {
 				return nil, err
 			}
diff --git a/src/mime/multipart/example_test.go b/src/mime/multipart/example_test.go
index 6d6ba81d5e6..fe154ac4f69 100644
--- a/src/mime/multipart/example_test.go
+++ b/src/mime/multipart/example_test.go
@@ -7,7 +7,6 @@ package multipart_test
 import (
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"mime"
 	"mime/multipart"
@@ -39,7 +38,7 @@ func ExampleNewReader() {
 			if err != nil {
 				log.Fatal(err)
 			}
-			slurp, err := ioutil.ReadAll(p)
+			slurp, err := io.ReadAll(p)
 			if err != nil {
 				log.Fatal(err)
 			}
diff --git a/src/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
index 1750300fb53..cb8bf393383 100644
--- a/src/mime/multipart/multipart.go
+++ b/src/mime/multipart/multipart.go
@@ -17,7 +17,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime"
 	"mime/quotedprintable"
 	"net/textproto"
@@ -278,7 +277,7 @@ func matchAfterPrefix(buf, prefix []byte, readErr error) int {
 }
 
 func (p *Part) Close() error {
-	io.Copy(ioutil.Discard, p)
+	io.Copy(io.Discard, p)
 	return nil
 }
 
diff --git a/src/mime/multipart/multipart_test.go b/src/mime/multipart/multipart_test.go
index b60c54a2042..741d2304ed4 100644
--- a/src/mime/multipart/multipart_test.go
+++ b/src/mime/multipart/multipart_test.go
@@ -9,7 +9,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/textproto"
 	"os"
 	"reflect"
@@ -307,7 +306,7 @@ Oh no, premature EOF!
 	if err != nil {
 		t.Fatalf("didn't get a part")
 	}
-	_, err = io.Copy(ioutil.Discard, part)
+	_, err = io.Copy(io.Discard, part)
 	if err != io.ErrUnexpectedEOF {
 		t.Fatalf("expected error io.ErrUnexpectedEOF; got %v", err)
 	}
@@ -372,7 +371,7 @@ Body 2
 		if !reflect.DeepEqual(part.Header, hdr) {
 			t.Errorf("Part %d: part.Header = %v, want %v", i, part.Header, hdr)
 		}
-		data, err := ioutil.ReadAll(part)
+		data, err := io.ReadAll(part)
 		expectEq(t, body, string(data), fmt.Sprintf("Part %d body", i))
 		if err != nil {
 			t.Fatalf("Part %d: ReadAll failed: %v", i, err)
@@ -530,14 +529,14 @@ func TestNested(t *testing.T) {
 	if err != nil {
 		t.Fatalf("reading text/plain part: %v", err)
 	}
-	if b, err := ioutil.ReadAll(p); string(b) != "*body*\r\n" || err != nil {
+	if b, err := io.ReadAll(p); string(b) != "*body*\r\n" || err != nil {
 		t.Fatalf("reading text/plain part: got %q, %v", b, err)
 	}
 	p, err = mr2.NextPart()
 	if err != nil {
 		t.Fatalf("reading text/html part: %v", err)
 	}
-	if b, err := ioutil.ReadAll(p); string(b) != "body\r\n" || err != nil {
+	if b, err := io.ReadAll(p); string(b) != "body\r\n" || err != nil {
 		t.Fatalf("reading text/html part: got %q, %v", b, err)
 	}
 
@@ -850,7 +849,7 @@ Cases:
 				t.Errorf("in test %q, NextPart: %v", tt.name, err)
 				continue Cases
 			}
-			pbody, err := ioutil.ReadAll(p)
+			pbody, err := io.ReadAll(p)
 			if err != nil {
 				t.Errorf("in test %q, error reading part: %v", tt.name, err)
 				continue Cases
@@ -882,7 +881,7 @@ func partsFromReader(r *Reader) ([]headerBody, error) {
 		if err != nil {
 			return nil, fmt.Errorf("NextPart: %v", err)
 		}
-		pbody, err := ioutil.ReadAll(p)
+		pbody, err := io.ReadAll(p)
 		if err != nil {
 			return nil, fmt.Errorf("error reading part: %v", err)
 		}
diff --git a/src/mime/multipart/writer_test.go b/src/mime/multipart/writer_test.go
index b89b093fff6..cfc0f09f37f 100644
--- a/src/mime/multipart/writer_test.go
+++ b/src/mime/multipart/writer_test.go
@@ -6,7 +6,7 @@ package multipart
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"mime"
 	"net/textproto"
 	"strings"
@@ -51,7 +51,7 @@ func TestWriter(t *testing.T) {
 	if g, e := part.FormName(), "myfile"; g != e {
 		t.Errorf("part 1: want form name %q, got %q", e, g)
 	}
-	slurp, err := ioutil.ReadAll(part)
+	slurp, err := io.ReadAll(part)
 	if err != nil {
 		t.Fatalf("part 1: ReadAll: %v", err)
 	}
@@ -66,7 +66,7 @@ func TestWriter(t *testing.T) {
 	if g, e := part.FormName(), "key"; g != e {
 		t.Errorf("part 2: want form name %q, got %q", e, g)
 	}
-	slurp, err = ioutil.ReadAll(part)
+	slurp, err = io.ReadAll(part)
 	if err != nil {
 		t.Fatalf("part 2: ReadAll: %v", err)
 	}
@@ -134,7 +134,7 @@ func TestWriterBoundaryGoroutines(t *testing.T) {
 	// different goroutines. This was previously broken by
 	// https://codereview.appspot.com/95760043/ and reverted in
 	// https://codereview.appspot.com/117600043/
-	w := NewWriter(ioutil.Discard)
+	w := NewWriter(io.Discard)
 	done := make(chan int)
 	go func() {
 		w.CreateFormField("foo")
diff --git a/src/mime/quotedprintable/example_test.go b/src/mime/quotedprintable/example_test.go
index 5a9ab450a3c..e5a479a3a7f 100644
--- a/src/mime/quotedprintable/example_test.go
+++ b/src/mime/quotedprintable/example_test.go
@@ -6,7 +6,7 @@ package quotedprintable_test
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"mime/quotedprintable"
 	"os"
 	"strings"
@@ -18,7 +18,7 @@ func ExampleNewReader() {
 		`invalid escape: hello`,
 		"Hello, Gophers! This symbol will be unescaped: =3D and this will be written in =\r\none line.",
 	} {
-		b, err := ioutil.ReadAll(quotedprintable.NewReader(strings.NewReader(s)))
+		b, err := io.ReadAll(quotedprintable.NewReader(strings.NewReader(s)))
 		fmt.Printf("%s %v\n", b, err)
 	}
 	// Output:
diff --git a/src/mime/quotedprintable/writer_test.go b/src/mime/quotedprintable/writer_test.go
index d494c1e3dc3..42de0f3d6e8 100644
--- a/src/mime/quotedprintable/writer_test.go
+++ b/src/mime/quotedprintable/writer_test.go
@@ -6,7 +6,7 @@ package quotedprintable
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"strings"
 	"testing"
 )
@@ -128,7 +128,7 @@ func TestRoundTrip(t *testing.T) {
 	}
 
 	r := NewReader(buf)
-	gotBytes, err := ioutil.ReadAll(r)
+	gotBytes, err := io.ReadAll(r)
 	if err != nil {
 		t.Fatalf("Error while reading from Reader: %v", err)
 	}
@@ -151,7 +151,7 @@ var testMsg = []byte("Quoted-Printable (QP) est un format d'encodage de données
 
 func BenchmarkWriter(b *testing.B) {
 	for i := 0; i < b.N; i++ {
-		w := NewWriter(ioutil.Discard)
+		w := NewWriter(io.Discard)
 		w.Write(testMsg)
 		w.Close()
 	}
diff --git a/src/net/http/alpn_test.go b/src/net/http/alpn_test.go
index 618bdbe54a6..a51038c355a 100644
--- a/src/net/http/alpn_test.go
+++ b/src/net/http/alpn_test.go
@@ -11,7 +11,6 @@ import (
 	"crypto/x509"
 	"fmt"
 	"io"
-	"io/ioutil"
 	. "net/http"
 	"net/http/httptest"
 	"strings"
@@ -49,7 +48,7 @@ func TestNextProtoUpgrade(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		body, err := ioutil.ReadAll(res.Body)
+		body, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -93,7 +92,7 @@ func TestNextProtoUpgrade(t *testing.T) {
 			t.Fatal(err)
 		}
 		conn.Write([]byte("GET /foo\n"))
-		body, err := ioutil.ReadAll(conn)
+		body, err := io.ReadAll(conn)
 		if err != nil {
 			t.Fatal(err)
 		}
diff --git a/src/net/http/cgi/child.go b/src/net/http/cgi/child.go
index 690986335c0..0114da377b5 100644
--- a/src/net/http/cgi/child.go
+++ b/src/net/http/cgi/child.go
@@ -13,7 +13,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/url"
@@ -32,7 +31,7 @@ func Request() (*http.Request, error) {
 		return nil, err
 	}
 	if r.ContentLength > 0 {
-		r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, r.ContentLength))
+		r.Body = io.NopCloser(io.LimitReader(os.Stdin, r.ContentLength))
 	}
 	return r, nil
 }
diff --git a/src/net/http/client.go b/src/net/http/client.go
index 6ca0d2e6cf3..88e2028bc34 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -16,7 +16,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/url"
 	"reflect"
@@ -282,7 +281,7 @@ func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, d
 		if resp.ContentLength > 0 && req.Method != "HEAD" {
 			return nil, didTimeout, fmt.Errorf("http: RoundTripper implementation (%T) returned a *Response with content length %d but a nil Body", rt, resp.ContentLength)
 		}
-		resp.Body = ioutil.NopCloser(strings.NewReader(""))
+		resp.Body = io.NopCloser(strings.NewReader(""))
 	}
 	if !deadline.IsZero() {
 		resp.Body = &cancelTimerBody{
@@ -697,7 +696,7 @@ func (c *Client) do(req *Request) (retres *Response, reterr error) {
 			// fails, the Transport won't reuse it anyway.
 			const maxBodySlurpSize = 2 << 10
 			if resp.ContentLength == -1 || resp.ContentLength <= maxBodySlurpSize {
-				io.CopyN(ioutil.Discard, resp.Body, maxBodySlurpSize)
+				io.CopyN(io.Discard, resp.Body, maxBodySlurpSize)
 			}
 			resp.Body.Close()
 
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
index 4bd62735e84..d90b4841c66 100644
--- a/src/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -14,7 +14,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	. "net/http"
@@ -35,7 +34,7 @@ var robotsTxtHandler = HandlerFunc(func(w ResponseWriter, r *Request) {
 	fmt.Fprintf(w, "User-agent: go\nDisallow: /something/")
 })
 
-// pedanticReadAll works like ioutil.ReadAll but additionally
+// pedanticReadAll works like io.ReadAll but additionally
 // verifies that r obeys the documented io.Reader contract.
 func pedanticReadAll(r io.Reader) (b []byte, err error) {
 	var bufa [64]byte
@@ -190,7 +189,7 @@ func TestPostFormRequestFormat(t *testing.T) {
 	if g, e := tr.req.ContentLength, int64(len(expectedBody)); g != e {
 		t.Errorf("got ContentLength %d, want %d", g, e)
 	}
-	bodyb, err := ioutil.ReadAll(tr.req.Body)
+	bodyb, err := io.ReadAll(tr.req.Body)
 	if err != nil {
 		t.Fatalf("ReadAll on req.Body: %v", err)
 	}
@@ -421,7 +420,7 @@ func testRedirectsByMethod(t *testing.T, method string, table []redirectTest, wa
 	var ts *httptest.Server
 	ts = httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
 		log.Lock()
-		slurp, _ := ioutil.ReadAll(r.Body)
+		slurp, _ := io.ReadAll(r.Body)
 		fmt.Fprintf(&log.Buffer, "%s %s %q", r.Method, r.RequestURI, slurp)
 		if cl := r.Header.Get("Content-Length"); r.Method == "GET" && len(slurp) == 0 && (r.ContentLength != 0 || cl != "") {
 			fmt.Fprintf(&log.Buffer, " (but with body=%T, content-length = %v, %q)", r.Body, r.ContentLength, cl)
@@ -452,7 +451,7 @@ func testRedirectsByMethod(t *testing.T, method string, table []redirectTest, wa
 	for _, tt := range table {
 		content := tt.redirectBody
 		req, _ := NewRequest(method, ts.URL+tt.suffix, strings.NewReader(content))
-		req.GetBody = func() (io.ReadCloser, error) { return ioutil.NopCloser(strings.NewReader(content)), nil }
+		req.GetBody = func() (io.ReadCloser, error) { return io.NopCloser(strings.NewReader(content)), nil }
 		res, err := c.Do(req)
 
 		if err != nil {
@@ -522,7 +521,7 @@ func TestClientRedirectUseResponse(t *testing.T) {
 		t.Errorf("status = %d; want %d", res.StatusCode, StatusFound)
 	}
 	defer res.Body.Close()
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1042,7 +1041,7 @@ func testClientHeadContentLength(t *testing.T, h2 bool) {
 		if res.ContentLength != tt.want {
 			t.Errorf("Content-Length = %d; want %d", res.ContentLength, tt.want)
 		}
-		bs, err := ioutil.ReadAll(res.Body)
+		bs, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -1257,7 +1256,7 @@ func testClientTimeout(t *testing.T, h2 bool) {
 
 	errc := make(chan error, 1)
 	go func() {
-		_, err := ioutil.ReadAll(res.Body)
+		_, err := io.ReadAll(res.Body)
 		errc <- err
 		res.Body.Close()
 	}()
@@ -1348,7 +1347,7 @@ func TestClientTimeoutCancel(t *testing.T) {
 		t.Fatal(err)
 	}
 	cancel()
-	_, err = io.Copy(ioutil.Discard, res.Body)
+	_, err = io.Copy(io.Discard, res.Body)
 	if err != ExportErrRequestCanceled {
 		t.Fatalf("error = %v; want errRequestCanceled", err)
 	}
@@ -1372,7 +1371,7 @@ func testClientRedirectEatsBody(t *testing.T, h2 bool) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	_, err = ioutil.ReadAll(res.Body)
+	_, err = io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		t.Fatal(err)
@@ -1450,7 +1449,7 @@ func (issue15577Tripper) RoundTrip(*Request) (*Response, error) {
 	resp := &Response{
 		StatusCode: 303,
 		Header:     map[string][]string{"Location": {"http://www.example.com/"}},
-		Body:       ioutil.NopCloser(strings.NewReader("")),
+		Body:       io.NopCloser(strings.NewReader("")),
 	}
 	return resp, nil
 }
@@ -1591,7 +1590,7 @@ func TestClientCopyHostOnRedirect(t *testing.T) {
 	if resp.StatusCode != 200 {
 		t.Fatal(resp.Status)
 	}
-	if got, err := ioutil.ReadAll(resp.Body); err != nil || string(got) != wantBody {
+	if got, err := io.ReadAll(resp.Body); err != nil || string(got) != wantBody {
 		t.Errorf("body = %q; want %q", got, wantBody)
 	}
 }
@@ -2020,7 +2019,7 @@ func TestClientPopulatesNilResponseBody(t *testing.T) {
 		}
 	}()
 
-	if b, err := ioutil.ReadAll(resp.Body); err != nil {
+	if b, err := io.ReadAll(resp.Body); err != nil {
 		t.Errorf("read error from substitute Response.Body: %v", err)
 	} else if len(b) != 0 {
 		t.Errorf("substitute Response.Body was unexpectedly non-empty: %q", b)
diff --git a/src/net/http/clientserver_test.go b/src/net/http/clientserver_test.go
index 439818bb2f4..5e227181acb 100644
--- a/src/net/http/clientserver_test.go
+++ b/src/net/http/clientserver_test.go
@@ -15,7 +15,6 @@ import (
 	"fmt"
 	"hash"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	. "net/http"
@@ -53,7 +52,7 @@ func (t *clientServerTest) getURL(u string) string {
 		t.t.Fatal(err)
 	}
 	defer res.Body.Close()
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.t.Fatal(err)
 	}
@@ -152,7 +151,7 @@ func TestChunkedResponseHeaders_h2(t *testing.T) { testChunkedResponseHeaders(t,
 
 func testChunkedResponseHeaders(t *testing.T, h2 bool) {
 	defer afterTest(t)
-	log.SetOutput(ioutil.Discard) // is noisy otherwise
+	log.SetOutput(io.Discard) // is noisy otherwise
 	defer log.SetOutput(os.Stderr)
 	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		w.Header().Set("Content-Length", "intentional gibberish") // we check that this is deleted
@@ -266,11 +265,11 @@ func (tt h12Compare) normalizeRes(t *testing.T, res *Response, wantProto string)
 	} else {
 		t.Errorf("got %q response; want %q", res.Proto, wantProto)
 	}
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 
 	res.Body.Close()
 	res.Body = slurpResult{
-		ReadCloser: ioutil.NopCloser(bytes.NewReader(slurp)),
+		ReadCloser: io.NopCloser(bytes.NewReader(slurp)),
 		body:       slurp,
 		err:        err,
 	}
@@ -477,7 +476,7 @@ func test304Responses(t *testing.T, h2 bool) {
 	if len(res.TransferEncoding) > 0 {
 		t.Errorf("expected no TransferEncoding; got %v", res.TransferEncoding)
 	}
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Error(err)
 	}
@@ -564,7 +563,7 @@ func testCancelRequestMidBody(t *testing.T, h2 bool) {
 
 	close(cancel)
 
-	rest, err := ioutil.ReadAll(res.Body)
+	rest, err := io.ReadAll(res.Body)
 	all := string(firstRead) + string(rest)
 	if all != "Hello" {
 		t.Errorf("Read %q (%q + %q); want Hello", all, firstRead, rest)
@@ -587,7 +586,7 @@ func testTrailersClientToServer(t *testing.T, h2 bool) {
 		}
 		sort.Strings(decl)
 
-		slurp, err := ioutil.ReadAll(r.Body)
+		slurp, err := io.ReadAll(r.Body)
 		if err != nil {
 			t.Errorf("Server reading request body: %v", err)
 		}
@@ -721,7 +720,7 @@ func testResponseBodyReadAfterClose(t *testing.T, h2 bool) {
 		t.Fatal(err)
 	}
 	res.Body.Close()
-	data, err := ioutil.ReadAll(res.Body)
+	data, err := io.ReadAll(res.Body)
 	if len(data) != 0 || err == nil {
 		t.Fatalf("ReadAll returned %q, %v; want error", data, err)
 	}
@@ -740,7 +739,7 @@ func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) {
 		// Read in one goroutine.
 		go func() {
 			defer wg.Done()
-			data, err := ioutil.ReadAll(r.Body)
+			data, err := io.ReadAll(r.Body)
 			if string(data) != reqBody {
 				t.Errorf("Handler read %q; want %q", data, reqBody)
 			}
@@ -770,7 +769,7 @@ func testConcurrentReadWriteReqBody(t *testing.T, h2 bool) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	data, err := ioutil.ReadAll(res.Body)
+	data, err := io.ReadAll(res.Body)
 	defer res.Body.Close()
 	if err != nil {
 		t.Fatal(err)
@@ -887,7 +886,7 @@ func testTransportUserAgent(t *testing.T, h2 bool) {
 			t.Errorf("%d. RoundTrip = %v", i, err)
 			continue
 		}
-		slurp, err := ioutil.ReadAll(res.Body)
+		slurp, err := io.ReadAll(res.Body)
 		res.Body.Close()
 		if err != nil {
 			t.Errorf("%d. read body = %v", i, err)
@@ -1019,7 +1018,7 @@ func TestTransportDiscardsUnneededConns(t *testing.T) {
 				}
 			}
 			defer resp.Body.Close()
-			slurp, err := ioutil.ReadAll(resp.Body)
+			slurp, err := io.ReadAll(resp.Body)
 			if err != nil {
 				t.Error(err)
 			}
@@ -1064,7 +1063,7 @@ func testTransportGCRequest(t *testing.T, h2, body bool) {
 	setParallel(t)
 	defer afterTest(t)
 	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
-		ioutil.ReadAll(r.Body)
+		io.ReadAll(r.Body)
 		if body {
 			io.WriteString(w, "Hello.")
 		}
@@ -1080,7 +1079,7 @@ func testTransportGCRequest(t *testing.T, h2, body bool) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		if _, err := ioutil.ReadAll(res.Body); err != nil {
+		if _, err := io.ReadAll(res.Body); err != nil {
 			t.Fatal(err)
 		}
 		if err := res.Body.Close(); err != nil {
@@ -1141,7 +1140,7 @@ func testTransportRejectsInvalidHeaders(t *testing.T, h2 bool) {
 		res, err := cst.c.Do(req)
 		var body []byte
 		if err == nil {
-			body, _ = ioutil.ReadAll(res.Body)
+			body, _ = io.ReadAll(res.Body)
 			res.Body.Close()
 		}
 		var dialed bool
@@ -1198,7 +1197,7 @@ func testInterruptWithPanic(t *testing.T, h2 bool, panicValue interface{}) {
 	}
 	gotHeaders <- true
 	defer res.Body.Close()
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if string(slurp) != msg {
 		t.Errorf("client read %q; want %q", slurp, msg)
 	}
@@ -1363,7 +1362,7 @@ func testServerUndeclaredTrailers(t *testing.T, h2 bool) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+	if _, err := io.Copy(io.Discard, res.Body); err != nil {
 		t.Fatal(err)
 	}
 	res.Body.Close()
@@ -1381,7 +1380,7 @@ func testServerUndeclaredTrailers(t *testing.T, h2 bool) {
 func TestBadResponseAfterReadingBody(t *testing.T) {
 	defer afterTest(t)
 	cst := newClientServerTest(t, false, HandlerFunc(func(w ResponseWriter, r *Request) {
-		_, err := io.Copy(ioutil.Discard, r.Body)
+		_, err := io.Copy(io.Discard, r.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -1474,7 +1473,7 @@ func testWriteHeaderAfterWrite(t *testing.T, h2, hijack bool) {
 		t.Fatal(err)
 	}
 	defer res.Body.Close()
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/net/http/doc.go b/src/net/http/doc.go
index 7855feaaa99..ae9b708c695 100644
--- a/src/net/http/doc.go
+++ b/src/net/http/doc.go
@@ -21,7 +21,7 @@ The client must close the response body when finished with it:
 		// handle error
 	}
 	defer resp.Body.Close()
-	body, err := ioutil.ReadAll(resp.Body)
+	body, err := io.ReadAll(resp.Body)
 	// ...
 
 For control over HTTP client headers, redirect policy, and other
diff --git a/src/net/http/example_test.go b/src/net/http/example_test.go
index a783b466185..c677d522385 100644
--- a/src/net/http/example_test.go
+++ b/src/net/http/example_test.go
@@ -8,7 +8,6 @@ import (
 	"context"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
@@ -46,7 +45,7 @@ func ExampleGet() {
 	if err != nil {
 		log.Fatal(err)
 	}
-	robots, err := ioutil.ReadAll(res.Body)
+	robots, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		log.Fatal(err)
diff --git a/src/net/http/fcgi/child.go b/src/net/http/fcgi/child.go
index 34761f32ee1..e97b8440e1d 100644
--- a/src/net/http/fcgi/child.go
+++ b/src/net/http/fcgi/child.go
@@ -11,7 +11,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/http/cgi"
@@ -186,7 +185,7 @@ func (c *child) serve() {
 
 var errCloseConn = errors.New("fcgi: connection should be closed")
 
-var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+var emptyBody = io.NopCloser(strings.NewReader(""))
 
 // ErrRequestAborted is returned by Read when a handler attempts to read the
 // body of a request that has been aborted by the web server.
@@ -325,7 +324,7 @@ func (c *child) serveRequest(req *request, body io.ReadCloser) {
 	// some sort of abort request to the host, so the host
 	// can properly cut off the client sending all the data.
 	// For now just bound it a little and
-	io.CopyN(ioutil.Discard, body, 100<<20)
+	io.CopyN(io.Discard, body, 100<<20)
 	body.Close()
 
 	if !req.keepConn {
diff --git a/src/net/http/fcgi/fcgi_test.go b/src/net/http/fcgi/fcgi_test.go
index 4a27a12c35a..d3b704f8219 100644
--- a/src/net/http/fcgi/fcgi_test.go
+++ b/src/net/http/fcgi/fcgi_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"errors"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"strings"
 	"testing"
@@ -243,7 +242,7 @@ func TestChildServeCleansUp(t *testing.T) {
 			r *http.Request,
 		) {
 			// block on reading body of request
-			_, err := io.Copy(ioutil.Discard, r.Body)
+			_, err := io.Copy(io.Discard, r.Body)
 			if err != tt.err {
 				t.Errorf("Expected %#v, got %#v", tt.err, err)
 			}
@@ -275,7 +274,7 @@ func TestMalformedParams(t *testing.T) {
 		// end of params
 		1, 4, 0, 1, 0, 0, 0, 0,
 	}
-	rw := rwNopCloser{bytes.NewReader(input), ioutil.Discard}
+	rw := rwNopCloser{bytes.NewReader(input), io.Discard}
 	c := newChild(rw, http.DefaultServeMux)
 	c.serve()
 }
diff --git a/src/net/http/filetransport_test.go b/src/net/http/filetransport_test.go
index 2a2f32c7694..fdfd44d967a 100644
--- a/src/net/http/filetransport_test.go
+++ b/src/net/http/filetransport_test.go
@@ -5,6 +5,7 @@
 package http
 
 import (
+	"io"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -48,7 +49,7 @@ func TestFileTransport(t *testing.T) {
 		if res.Body == nil {
 			t.Fatalf("for %s, nil Body", urlstr)
 		}
-		slurp, err := ioutil.ReadAll(res.Body)
+		slurp, err := io.ReadAll(res.Body)
 		res.Body.Close()
 		check("ReadAll "+urlstr, err)
 		if string(slurp) != "Bar" {
diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go
index c9f324cff6f..2e4751114de 100644
--- a/src/net/http/fs_test.go
+++ b/src/net/http/fs_test.go
@@ -160,7 +160,7 @@ Cases:
 				if g, w := part.Header.Get("Content-Range"), wantContentRange; g != w {
 					t.Errorf("range=%q: part Content-Range = %q; want %q", rt.r, g, w)
 				}
-				body, err := ioutil.ReadAll(part)
+				body, err := io.ReadAll(part)
 				if err != nil {
 					t.Errorf("range=%q, reading part index %d body: %v", rt.r, ri, err)
 					continue Cases
@@ -312,7 +312,7 @@ func TestFileServerEscapesNames(t *testing.T) {
 		if err != nil {
 			t.Fatalf("test %q: Get: %v", test.name, err)
 		}
-		b, err := ioutil.ReadAll(res.Body)
+		b, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatalf("test %q: read Body: %v", test.name, err)
 		}
@@ -360,7 +360,7 @@ func TestFileServerSortsNames(t *testing.T) {
 	}
 	defer res.Body.Close()
 
-	b, err := ioutil.ReadAll(res.Body)
+	b, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatalf("read Body: %v", err)
 	}
@@ -394,7 +394,7 @@ func TestFileServerImplicitLeadingSlash(t *testing.T) {
 		if err != nil {
 			t.Fatalf("Get %s: %v", suffix, err)
 		}
-		b, err := ioutil.ReadAll(res.Body)
+		b, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatalf("ReadAll %s: %v", suffix, err)
 		}
@@ -617,7 +617,7 @@ func TestServeIndexHtmlFS(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		b, err := ioutil.ReadAll(res.Body)
+		b, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatal("reading Body:", err)
 		}
@@ -745,7 +745,7 @@ func TestDirectoryIfNotModified(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	b, err := ioutil.ReadAll(res.Body)
+	b, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1082,7 +1082,7 @@ func TestServeContent(t *testing.T) {
 			if err != nil {
 				t.Fatal(err)
 			}
-			io.Copy(ioutil.Discard, res.Body)
+			io.Copy(io.Discard, res.Body)
 			res.Body.Close()
 			if res.StatusCode != tt.wantStatus {
 				t.Errorf("test %q using %q: got status = %d; want %d", testName, method, res.StatusCode, tt.wantStatus)
@@ -1196,7 +1196,7 @@ func TestLinuxSendfile(t *testing.T) {
 	if err != nil {
 		t.Fatalf("http client error: %v", err)
 	}
-	_, err = io.Copy(ioutil.Discard, res.Body)
+	_, err = io.Copy(io.Discard, res.Body)
 	if err != nil {
 		t.Fatalf("client body read error: %v", err)
 	}
@@ -1218,7 +1218,7 @@ func getBody(t *testing.T, testName string, req Request, client *Client) (*Respo
 	if err != nil {
 		t.Fatalf("%s: for URL %q, send error: %v", testName, req.URL.String(), err)
 	}
-	b, err := ioutil.ReadAll(r.Body)
+	b, err := io.ReadAll(r.Body)
 	if err != nil {
 		t.Fatalf("%s: for URL %q, reading body: %v", testName, req.URL.String(), err)
 	}
@@ -1401,7 +1401,7 @@ func testServeFileRejectsInvalidSuffixLengths(t *testing.T, h2 bool) {
 			if g, w := res.StatusCode, tt.wantCode; g != w {
 				t.Errorf("StatusCode mismatch: got %d want %d", g, w)
 			}
-			slurp, err := ioutil.ReadAll(res.Body)
+			slurp, err := io.ReadAll(res.Body)
 			res.Body.Close()
 			if err != nil {
 				t.Fatal(err)
diff --git a/src/net/http/httptest/example_test.go b/src/net/http/httptest/example_test.go
index 54e77dbb84c..a6738432ebf 100644
--- a/src/net/http/httptest/example_test.go
+++ b/src/net/http/httptest/example_test.go
@@ -7,7 +7,6 @@ package httptest_test
 import (
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -23,7 +22,7 @@ func ExampleResponseRecorder() {
 	handler(w, req)
 
 	resp := w.Result()
-	body, _ := ioutil.ReadAll(resp.Body)
+	body, _ := io.ReadAll(resp.Body)
 
 	fmt.Println(resp.StatusCode)
 	fmt.Println(resp.Header.Get("Content-Type"))
@@ -45,7 +44,7 @@ func ExampleServer() {
 	if err != nil {
 		log.Fatal(err)
 	}
-	greeting, err := ioutil.ReadAll(res.Body)
+	greeting, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		log.Fatal(err)
@@ -67,7 +66,7 @@ func ExampleServer_hTTP2() {
 	if err != nil {
 		log.Fatal(err)
 	}
-	greeting, err := ioutil.ReadAll(res.Body)
+	greeting, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		log.Fatal(err)
@@ -89,7 +88,7 @@ func ExampleNewTLSServer() {
 		log.Fatal(err)
 	}
 
-	greeting, err := ioutil.ReadAll(res.Body)
+	greeting, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		log.Fatal(err)
diff --git a/src/net/http/httptest/httptest.go b/src/net/http/httptest/httptest.go
index f7202da92ff..9bedefd2bc0 100644
--- a/src/net/http/httptest/httptest.go
+++ b/src/net/http/httptest/httptest.go
@@ -10,7 +10,6 @@ import (
 	"bytes"
 	"crypto/tls"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"strings"
 )
@@ -66,7 +65,7 @@ func NewRequest(method, target string, body io.Reader) *http.Request {
 		if rc, ok := body.(io.ReadCloser); ok {
 			req.Body = rc
 		} else {
-			req.Body = ioutil.NopCloser(body)
+			req.Body = io.NopCloser(body)
 		}
 	}
 
diff --git a/src/net/http/httptest/httptest_test.go b/src/net/http/httptest/httptest_test.go
index ef7d9438377..071add67ea6 100644
--- a/src/net/http/httptest/httptest_test.go
+++ b/src/net/http/httptest/httptest_test.go
@@ -7,7 +7,6 @@ package httptest
 import (
 	"crypto/tls"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"reflect"
@@ -155,7 +154,7 @@ func TestNewRequest(t *testing.T) {
 	} {
 		t.Run(tt.name, func(t *testing.T) {
 			got := NewRequest(tt.method, tt.uri, tt.body)
-			slurp, err := ioutil.ReadAll(got.Body)
+			slurp, err := io.ReadAll(got.Body)
 			if err != nil {
 				t.Errorf("ReadAll: %v", err)
 			}
diff --git a/src/net/http/httptest/recorder.go b/src/net/http/httptest/recorder.go
index 66e67e78b30..24284826122 100644
--- a/src/net/http/httptest/recorder.go
+++ b/src/net/http/httptest/recorder.go
@@ -7,7 +7,7 @@ package httptest
 import (
 	"bytes"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/textproto"
 	"strconv"
@@ -179,7 +179,7 @@ func (rw *ResponseRecorder) Result() *http.Response {
 	}
 	res.Status = fmt.Sprintf("%03d %s", res.StatusCode, http.StatusText(res.StatusCode))
 	if rw.Body != nil {
-		res.Body = ioutil.NopCloser(bytes.NewReader(rw.Body.Bytes()))
+		res.Body = io.NopCloser(bytes.NewReader(rw.Body.Bytes()))
 	} else {
 		res.Body = http.NoBody
 	}
diff --git a/src/net/http/httptest/recorder_test.go b/src/net/http/httptest/recorder_test.go
index e9534894b6c..a865e878b9b 100644
--- a/src/net/http/httptest/recorder_test.go
+++ b/src/net/http/httptest/recorder_test.go
@@ -7,7 +7,6 @@ package httptest
 import (
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"testing"
 )
@@ -42,7 +41,7 @@ func TestRecorder(t *testing.T) {
 	}
 	hasResultContents := func(want string) checkFunc {
 		return func(rec *ResponseRecorder) error {
-			contentBytes, err := ioutil.ReadAll(rec.Result().Body)
+			contentBytes, err := io.ReadAll(rec.Result().Body)
 			if err != nil {
 				return err
 			}
diff --git a/src/net/http/httptest/server_test.go b/src/net/http/httptest/server_test.go
index 0aad15c5ed2..39568b358c2 100644
--- a/src/net/http/httptest/server_test.go
+++ b/src/net/http/httptest/server_test.go
@@ -6,7 +6,7 @@ package httptest
 
 import (
 	"bufio"
-	"io/ioutil"
+	"io"
 	"net"
 	"net/http"
 	"testing"
@@ -61,7 +61,7 @@ func testServer(t *testing.T, newServer newServerFunc) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	got, err := ioutil.ReadAll(res.Body)
+	got, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		t.Fatal(err)
@@ -81,7 +81,7 @@ func testGetAfterClose(t *testing.T, newServer newServerFunc) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	got, err := ioutil.ReadAll(res.Body)
+	got, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -93,7 +93,7 @@ func testGetAfterClose(t *testing.T, newServer newServerFunc) {
 
 	res, err = http.Get(ts.URL)
 	if err == nil {
-		body, _ := ioutil.ReadAll(res.Body)
+		body, _ := io.ReadAll(res.Body)
 		t.Fatalf("Unexpected response after close: %v, %v, %s", res.Status, res.Header, body)
 	}
 }
@@ -152,7 +152,7 @@ func testServerClient(t *testing.T, newTLSServer newServerFunc) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	got, err := ioutil.ReadAll(res.Body)
+	got, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		t.Fatal(err)
diff --git a/src/net/http/httputil/dump.go b/src/net/http/httputil/dump.go
index c97be066d7d..4c9d28bed8f 100644
--- a/src/net/http/httputil/dump.go
+++ b/src/net/http/httputil/dump.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http"
 	"net/url"
@@ -35,7 +34,7 @@ func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
 	if err = b.Close(); err != nil {
 		return nil, b, err
 	}
-	return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
+	return io.NopCloser(&buf), io.NopCloser(bytes.NewReader(buf.Bytes())), nil
 }
 
 // dumpConn is a net.Conn which writes to Writer and reads from Reader
@@ -81,7 +80,7 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
 	if !body {
 		contentLength := outgoingLength(req)
 		if contentLength != 0 {
-			req.Body = ioutil.NopCloser(io.LimitReader(neverEnding('x'), contentLength))
+			req.Body = io.NopCloser(io.LimitReader(neverEnding('x'), contentLength))
 			dummyBody = true
 		}
 	} else {
@@ -133,7 +132,7 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
 		if err == nil {
 			// Ensure all the body is read; otherwise
 			// we'll get a partial dump.
-			io.Copy(ioutil.Discard, req.Body)
+			io.Copy(io.Discard, req.Body)
 			req.Body.Close()
 		}
 		select {
@@ -296,7 +295,7 @@ func (failureToReadBody) Read([]byte) (int, error) { return 0, errNoBody }
 func (failureToReadBody) Close() error             { return nil }
 
 // emptyBody is an instance of empty reader.
-var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+var emptyBody = io.NopCloser(strings.NewReader(""))
 
 // DumpResponse is like DumpRequest but dumps a response.
 func DumpResponse(resp *http.Response, body bool) ([]byte, error) {
diff --git a/src/net/http/httputil/dump_test.go b/src/net/http/httputil/dump_test.go
index ead56bc172b..7571eb0820d 100644
--- a/src/net/http/httputil/dump_test.go
+++ b/src/net/http/httputil/dump_test.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http"
 	"net/url"
 	"runtime"
@@ -268,7 +267,7 @@ func TestDumpRequest(t *testing.T) {
 			}
 			switch b := ti.Body.(type) {
 			case []byte:
-				req.Body = ioutil.NopCloser(bytes.NewReader(b))
+				req.Body = io.NopCloser(bytes.NewReader(b))
 			case func() io.ReadCloser:
 				req.Body = b()
 			default:
@@ -363,7 +362,7 @@ var dumpResTests = []struct {
 			Header: http.Header{
 				"Foo": []string{"Bar"},
 			},
-			Body: ioutil.NopCloser(strings.NewReader("foo")), // shouldn't be used
+			Body: io.NopCloser(strings.NewReader("foo")), // shouldn't be used
 		},
 		body: false, // to verify we see 50, not empty or 3.
 		want: `HTTP/1.1 200 OK
@@ -379,7 +378,7 @@ Foo: Bar`,
 			ProtoMajor:    1,
 			ProtoMinor:    1,
 			ContentLength: 3,
-			Body:          ioutil.NopCloser(strings.NewReader("foo")),
+			Body:          io.NopCloser(strings.NewReader("foo")),
 		},
 		body: true,
 		want: `HTTP/1.1 200 OK
@@ -396,7 +395,7 @@ foo`,
 			ProtoMajor:       1,
 			ProtoMinor:       1,
 			ContentLength:    -1,
-			Body:             ioutil.NopCloser(strings.NewReader("foo")),
+			Body:             io.NopCloser(strings.NewReader("foo")),
 			TransferEncoding: []string{"chunked"},
 		},
 		body: true,
diff --git a/src/net/http/httputil/example_test.go b/src/net/http/httputil/example_test.go
index 61916036745..b77a243ca3a 100644
--- a/src/net/http/httputil/example_test.go
+++ b/src/net/http/httputil/example_test.go
@@ -6,7 +6,7 @@ package httputil_test
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -39,7 +39,7 @@ func ExampleDumpRequest() {
 	}
 	defer resp.Body.Close()
 
-	b, err := ioutil.ReadAll(resp.Body)
+	b, err := io.ReadAll(resp.Body)
 	if err != nil {
 		log.Fatal(err)
 	}
@@ -111,7 +111,7 @@ func ExampleReverseProxy() {
 		log.Fatal(err)
 	}
 
-	b, err := ioutil.ReadAll(resp.Body)
+	b, err := io.ReadAll(resp.Body)
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/src/net/http/httputil/reverseproxy_test.go b/src/net/http/httputil/reverseproxy_test.go
index cc05d55d879..3acbd940e4b 100644
--- a/src/net/http/httputil/reverseproxy_test.go
+++ b/src/net/http/httputil/reverseproxy_test.go
@@ -13,7 +13,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net/http"
 	"net/http/httptest"
@@ -84,7 +83,7 @@ func TestReverseProxy(t *testing.T) {
 		t.Fatal(err)
 	}
 	proxyHandler := NewSingleHostReverseProxy(backendURL)
-	proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+	proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 	frontend := httptest.NewServer(proxyHandler)
 	defer frontend.Close()
 	frontendClient := frontend.Client()
@@ -124,7 +123,7 @@ func TestReverseProxy(t *testing.T) {
 	if cookie := res.Cookies()[0]; cookie.Name != "flavor" {
 		t.Errorf("unexpected cookie %q", cookie.Name)
 	}
-	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	bodyBytes, _ := io.ReadAll(res.Body)
 	if g, e := string(bodyBytes), backendResponse; g != e {
 		t.Errorf("got body %q; expected %q", g, e)
 	}
@@ -218,7 +217,7 @@ func TestReverseProxyStripHeadersPresentInConnection(t *testing.T) {
 		t.Fatalf("Get: %v", err)
 	}
 	defer res.Body.Close()
-	bodyBytes, err := ioutil.ReadAll(res.Body)
+	bodyBytes, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatalf("reading body: %v", err)
 	}
@@ -271,7 +270,7 @@ func TestXForwardedFor(t *testing.T) {
 	if g, e := res.StatusCode, backendStatus; g != e {
 		t.Errorf("got res.StatusCode %d; expected %d", g, e)
 	}
-	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	bodyBytes, _ := io.ReadAll(res.Body)
 	if g, e := string(bodyBytes), backendResponse; g != e {
 		t.Errorf("got body %q; expected %q", g, e)
 	}
@@ -373,7 +372,7 @@ func TestReverseProxyFlushInterval(t *testing.T) {
 		t.Fatalf("Get: %v", err)
 	}
 	defer res.Body.Close()
-	if bodyBytes, _ := ioutil.ReadAll(res.Body); string(bodyBytes) != expected {
+	if bodyBytes, _ := io.ReadAll(res.Body); string(bodyBytes) != expected {
 		t.Errorf("got body %q; expected %q", bodyBytes, expected)
 	}
 }
@@ -441,7 +440,7 @@ func TestReverseProxyCancellation(t *testing.T) {
 
 	defer backend.Close()
 
-	backend.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+	backend.Config.ErrorLog = log.New(io.Discard, "", 0)
 
 	backendURL, err := url.Parse(backend.URL)
 	if err != nil {
@@ -452,7 +451,7 @@ func TestReverseProxyCancellation(t *testing.T) {
 
 	// Discards errors of the form:
 	// http: proxy error: read tcp 127.0.0.1:44643: use of closed network connection
-	proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0)
+	proxyHandler.ErrorLog = log.New(io.Discard, "", 0)
 
 	frontend := httptest.NewServer(proxyHandler)
 	defer frontend.Close()
@@ -504,7 +503,7 @@ func TestNilBody(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer res.Body.Close()
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -533,7 +532,7 @@ func TestUserAgentHeader(t *testing.T) {
 		t.Fatal(err)
 	}
 	proxyHandler := NewSingleHostReverseProxy(backendURL)
-	proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+	proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 	frontend := httptest.NewServer(proxyHandler)
 	defer frontend.Close()
 	frontendClient := frontend.Client()
@@ -606,7 +605,7 @@ func TestReverseProxyGetPutBuffer(t *testing.T) {
 	if err != nil {
 		t.Fatalf("Get: %v", err)
 	}
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	res.Body.Close()
 	if err != nil {
 		t.Fatalf("reading body: %v", err)
@@ -627,7 +626,7 @@ func TestReverseProxy_Post(t *testing.T) {
 	const backendStatus = 200
 	var requestBody = bytes.Repeat([]byte("a"), 1<<20)
 	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		slurp, err := ioutil.ReadAll(r.Body)
+		slurp, err := io.ReadAll(r.Body)
 		if err != nil {
 			t.Errorf("Backend body read = %v", err)
 		}
@@ -656,7 +655,7 @@ func TestReverseProxy_Post(t *testing.T) {
 	if g, e := res.StatusCode, backendStatus; g != e {
 		t.Errorf("got res.StatusCode %d; expected %d", g, e)
 	}
-	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	bodyBytes, _ := io.ReadAll(res.Body)
 	if g, e := string(bodyBytes), backendResponse; g != e {
 		t.Errorf("got body %q; expected %q", g, e)
 	}
@@ -672,7 +671,7 @@ func (fn RoundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error)
 func TestReverseProxy_NilBody(t *testing.T) {
 	backendURL, _ := url.Parse("http://fake.tld/")
 	proxyHandler := NewSingleHostReverseProxy(backendURL)
-	proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+	proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 	proxyHandler.Transport = RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
 		if req.Body != nil {
 			t.Error("Body != nil; want a nil Body")
@@ -695,8 +694,8 @@ func TestReverseProxy_NilBody(t *testing.T) {
 // Issue 33142: always allocate the request headers
 func TestReverseProxy_AllocatedHeader(t *testing.T) {
 	proxyHandler := new(ReverseProxy)
-	proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
-	proxyHandler.Director = func(*http.Request) {}         // noop
+	proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
+	proxyHandler.Director = func(*http.Request) {}     // noop
 	proxyHandler.Transport = RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
 		if req.Header == nil {
 			t.Error("Header == nil; want a non-nil Header")
@@ -722,7 +721,7 @@ func TestReverseProxyModifyResponse(t *testing.T) {
 
 	rpURL, _ := url.Parse(backendServer.URL)
 	rproxy := NewSingleHostReverseProxy(rpURL)
-	rproxy.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+	rproxy.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 	rproxy.ModifyResponse = func(resp *http.Response) error {
 		if resp.Header.Get("X-Hit-Mod") != "true" {
 			return fmt.Errorf("tried to by-pass proxy")
@@ -821,7 +820,7 @@ func TestReverseProxyErrorHandler(t *testing.T) {
 			if rproxy.Transport == nil {
 				rproxy.Transport = failingRoundTripper{}
 			}
-			rproxy.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+			rproxy.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 			if tt.errorHandler != nil {
 				rproxy.ErrorHandler = tt.errorHandler
 			}
@@ -896,7 +895,7 @@ func (t *staticTransport) RoundTrip(r *http.Request) (*http.Response, error) {
 func BenchmarkServeHTTP(b *testing.B) {
 	res := &http.Response{
 		StatusCode: 200,
-		Body:       ioutil.NopCloser(strings.NewReader("")),
+		Body:       io.NopCloser(strings.NewReader("")),
 	}
 	proxy := &ReverseProxy{
 		Director:  func(*http.Request) {},
@@ -953,7 +952,7 @@ func TestServeHTTPDeepCopy(t *testing.T) {
 // Issue 18327: verify we always do a deep copy of the Request.Header map
 // before any mutations.
 func TestClonesRequestHeaders(t *testing.T) {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 	defer log.SetOutput(os.Stderr)
 	req, _ := http.NewRequest("GET", "http://foo.tld/", nil)
 	req.RemoteAddr = "1.2.3.4:56789"
@@ -1031,7 +1030,7 @@ func (cc *checkCloser) Read(b []byte) (int, error) {
 
 // Issue 23643: panic on body copy error
 func TestReverseProxy_PanicBodyError(t *testing.T) {
-	log.SetOutput(ioutil.Discard)
+	log.SetOutput(io.Discard)
 	defer log.SetOutput(os.Stderr)
 	backendServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		out := "this call was relayed by the reverse proxy"
@@ -1148,7 +1147,7 @@ func TestReverseProxyWebSocket(t *testing.T) {
 
 	backURL, _ := url.Parse(backendServer.URL)
 	rproxy := NewSingleHostReverseProxy(backURL)
-	rproxy.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+	rproxy.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 	rproxy.ModifyResponse = func(res *http.Response) error {
 		res.Header.Add("X-Modified", "true")
 		return nil
@@ -1265,7 +1264,7 @@ func TestReverseProxyWebSocketCancelation(t *testing.T) {
 
 	backendURL, _ := url.Parse(cst.URL)
 	rproxy := NewSingleHostReverseProxy(backendURL)
-	rproxy.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+	rproxy.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 	rproxy.ModifyResponse = func(res *http.Response) error {
 		res.Header.Add("X-Modified", "true")
 		return nil
@@ -1352,7 +1351,7 @@ func TestUnannouncedTrailer(t *testing.T) {
 		t.Fatal(err)
 	}
 	proxyHandler := NewSingleHostReverseProxy(backendURL)
-	proxyHandler.ErrorLog = log.New(ioutil.Discard, "", 0) // quiet for tests
+	proxyHandler.ErrorLog = log.New(io.Discard, "", 0) // quiet for tests
 	frontend := httptest.NewServer(proxyHandler)
 	defer frontend.Close()
 	frontendClient := frontend.Client()
@@ -1362,7 +1361,7 @@ func TestUnannouncedTrailer(t *testing.T) {
 		t.Fatalf("Get: %v", err)
 	}
 
-	ioutil.ReadAll(res.Body)
+	io.ReadAll(res.Body)
 
 	if g, w := res.Trailer.Get("X-Unannounced-Trailer"), "unannounced_trailer_value"; g != w {
 		t.Errorf("Trailer(X-Unannounced-Trailer) = %q; want %q", g, w)
diff --git a/src/net/http/internal/chunked_test.go b/src/net/http/internal/chunked_test.go
index d06716591ab..08152ed1e24 100644
--- a/src/net/http/internal/chunked_test.go
+++ b/src/net/http/internal/chunked_test.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"testing"
 )
@@ -29,7 +28,7 @@ func TestChunk(t *testing.T) {
 	}
 
 	r := NewChunkedReader(&b)
-	data, err := ioutil.ReadAll(r)
+	data, err := io.ReadAll(r)
 	if err != nil {
 		t.Logf(`data: "%s"`, data)
 		t.Fatalf("ReadAll from reader: %v", err)
@@ -177,7 +176,7 @@ func TestChunkReadingIgnoresExtensions(t *testing.T) {
 		"17;someext\r\n" + // token without value
 		"world! 0123456789abcdef\r\n" +
 		"0;someextension=sometoken\r\n" // token=token
-	data, err := ioutil.ReadAll(NewChunkedReader(strings.NewReader(in)))
+	data, err := io.ReadAll(NewChunkedReader(strings.NewReader(in)))
 	if err != nil {
 		t.Fatalf("ReadAll = %q, %v", data, err)
 	}
diff --git a/src/net/http/main_test.go b/src/net/http/main_test.go
index 35cc80977c4..6564627998f 100644
--- a/src/net/http/main_test.go
+++ b/src/net/http/main_test.go
@@ -6,7 +6,7 @@ package http_test
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/http"
 	"os"
@@ -17,7 +17,7 @@ import (
 	"time"
 )
 
-var quietLog = log.New(ioutil.Discard, "", 0)
+var quietLog = log.New(io.Discard, "", 0)
 
 func TestMain(m *testing.M) {
 	v := m.Run()
diff --git a/src/net/http/pprof/pprof_test.go b/src/net/http/pprof/pprof_test.go
index f6f9ef5b041..84757e401aa 100644
--- a/src/net/http/pprof/pprof_test.go
+++ b/src/net/http/pprof/pprof_test.go
@@ -8,7 +8,7 @@ import (
 	"bytes"
 	"fmt"
 	"internal/profile"
-	"io/ioutil"
+	"io"
 	"net/http"
 	"net/http/httptest"
 	"runtime"
@@ -63,7 +63,7 @@ func TestHandlers(t *testing.T) {
 				t.Errorf("status code: got %d; want %d", got, want)
 			}
 
-			body, err := ioutil.ReadAll(resp.Body)
+			body, err := io.ReadAll(resp.Body)
 			if err != nil {
 				t.Errorf("when reading response body, expected non-nil err; got %v", err)
 			}
@@ -227,7 +227,7 @@ func query(endpoint string) (*profile.Profile, error) {
 		return nil, fmt.Errorf("failed to fetch %q: %v", url, r.Status)
 	}
 
-	b, err := ioutil.ReadAll(r.Body)
+	b, err := io.ReadAll(r.Body)
 	r.Body.Close()
 	if err != nil {
 		return nil, fmt.Errorf("failed to read and parse the result from %q: %v", url, err)
diff --git a/src/net/http/readrequest_test.go b/src/net/http/readrequest_test.go
index b227bb6d38b..1950f4907ad 100644
--- a/src/net/http/readrequest_test.go
+++ b/src/net/http/readrequest_test.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/url"
 	"reflect"
 	"strings"
@@ -468,7 +467,7 @@ func TestReadRequest_Bad(t *testing.T) {
 	for _, tt := range badRequestTests {
 		got, err := ReadRequest(bufio.NewReader(bytes.NewReader(tt.req)))
 		if err == nil {
-			all, err := ioutil.ReadAll(got.Body)
+			all, err := io.ReadAll(got.Body)
 			t.Errorf("%s: got unexpected request = %#v\n  Body = %q, %v", tt.name, got, all, err)
 		}
 	}
diff --git a/src/net/http/request.go b/src/net/http/request.go
index df73d5f62d4..adba5406e90 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -15,7 +15,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"mime"
 	"mime/multipart"
 	"net"
@@ -870,7 +869,7 @@ func NewRequestWithContext(ctx context.Context, method, url string, body io.Read
 	}
 	rc, ok := body.(io.ReadCloser)
 	if !ok && body != nil {
-		rc = ioutil.NopCloser(body)
+		rc = io.NopCloser(body)
 	}
 	// The host's colon:port should be normalized. See Issue 14836.
 	u.Host = removeEmptyPort(u.Host)
@@ -892,21 +891,21 @@ func NewRequestWithContext(ctx context.Context, method, url string, body io.Read
 			buf := v.Bytes()
 			req.GetBody = func() (io.ReadCloser, error) {
 				r := bytes.NewReader(buf)
-				return ioutil.NopCloser(r), nil
+				return io.NopCloser(r), nil
 			}
 		case *bytes.Reader:
 			req.ContentLength = int64(v.Len())
 			snapshot := *v
 			req.GetBody = func() (io.ReadCloser, error) {
 				r := snapshot
-				return ioutil.NopCloser(&r), nil
+				return io.NopCloser(&r), nil
 			}
 		case *strings.Reader:
 			req.ContentLength = int64(v.Len())
 			snapshot := *v
 			req.GetBody = func() (io.ReadCloser, error) {
 				r := snapshot
-				return ioutil.NopCloser(&r), nil
+				return io.NopCloser(&r), nil
 			}
 		default:
 			// This is where we'd set it to -1 (at least
@@ -1205,7 +1204,7 @@ func parsePostForm(r *Request) (vs url.Values, err error) {
 			maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
 			reader = io.LimitReader(r.Body, maxFormSize+1)
 		}
-		b, e := ioutil.ReadAll(reader)
+		b, e := io.ReadAll(reader)
 		if e != nil {
 			if err == nil {
 				err = e
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index 461d66e05d7..b4ef472e712 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -103,7 +103,7 @@ func TestParseFormUnknownContentType(t *testing.T) {
 				req := &Request{
 					Method: "POST",
 					Header: test.contentType,
-					Body:   ioutil.NopCloser(strings.NewReader("body")),
+					Body:   io.NopCloser(strings.NewReader("body")),
 				}
 				err := req.ParseForm()
 				switch {
@@ -150,7 +150,7 @@ func TestMultipartReader(t *testing.T) {
 		req := &Request{
 			Method: "POST",
 			Header: Header{"Content-Type": {test.contentType}},
-			Body:   ioutil.NopCloser(new(bytes.Buffer)),
+			Body:   io.NopCloser(new(bytes.Buffer)),
 		}
 		multipart, err := req.MultipartReader()
 		if test.shouldError {
@@ -187,7 +187,7 @@ binary data
 	req := &Request{
 		Method: "POST",
 		Header: Header{"Content-Type": {`multipart/form-data; boundary=xxx`}},
-		Body:   ioutil.NopCloser(strings.NewReader(postData)),
+		Body:   io.NopCloser(strings.NewReader(postData)),
 	}
 
 	initialFormItems := map[string]string{
@@ -231,7 +231,7 @@ func TestParseMultipartForm(t *testing.T) {
 	req := &Request{
 		Method: "POST",
 		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
-		Body:   ioutil.NopCloser(new(bytes.Buffer)),
+		Body:   io.NopCloser(new(bytes.Buffer)),
 	}
 	err := req.ParseMultipartForm(25)
 	if err == nil {
@@ -756,10 +756,10 @@ func (dr delayedEOFReader) Read(p []byte) (n int, err error) {
 }
 
 func TestIssue10884_MaxBytesEOF(t *testing.T) {
-	dst := ioutil.Discard
+	dst := io.Discard
 	_, err := io.Copy(dst, MaxBytesReader(
 		responseWriterJustWriter{dst},
-		ioutil.NopCloser(delayedEOFReader{strings.NewReader("12345")}),
+		io.NopCloser(delayedEOFReader{strings.NewReader("12345")}),
 		5))
 	if err != nil {
 		t.Fatal(err)
@@ -799,7 +799,7 @@ func TestMaxBytesReaderStickyError(t *testing.T) {
 		2: {101, 100},
 	}
 	for i, tt := range tests {
-		rc := MaxBytesReader(nil, ioutil.NopCloser(bytes.NewReader(make([]byte, tt.readable))), tt.limit)
+		rc := MaxBytesReader(nil, io.NopCloser(bytes.NewReader(make([]byte, tt.readable))), tt.limit)
 		if err := isSticky(rc); err != nil {
 			t.Errorf("%d. error: %v", i, err)
 		}
@@ -900,7 +900,7 @@ func TestNewRequestGetBody(t *testing.T) {
 			t.Errorf("test[%d]: GetBody = nil", i)
 			continue
 		}
-		slurp1, err := ioutil.ReadAll(req.Body)
+		slurp1, err := io.ReadAll(req.Body)
 		if err != nil {
 			t.Errorf("test[%d]: ReadAll(Body) = %v", i, err)
 		}
@@ -908,7 +908,7 @@ func TestNewRequestGetBody(t *testing.T) {
 		if err != nil {
 			t.Errorf("test[%d]: GetBody = %v", i, err)
 		}
-		slurp2, err := ioutil.ReadAll(newBody)
+		slurp2, err := io.ReadAll(newBody)
 		if err != nil {
 			t.Errorf("test[%d]: ReadAll(GetBody()) = %v", i, err)
 		}
@@ -1145,7 +1145,7 @@ func benchmarkFileAndServer(b *testing.B, n int64) {
 func runFileAndServerBenchmarks(b *testing.B, tlsOption bool, f *os.File, n int64) {
 	handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
 		defer req.Body.Close()
-		nc, err := io.Copy(ioutil.Discard, req.Body)
+		nc, err := io.Copy(io.Discard, req.Body)
 		if err != nil {
 			panic(err)
 		}
@@ -1172,7 +1172,7 @@ func runFileAndServerBenchmarks(b *testing.B, tlsOption bool, f *os.File, n int6
 		}
 
 		b.StartTimer()
-		req, err := NewRequest("PUT", cst.URL, ioutil.NopCloser(f))
+		req, err := NewRequest("PUT", cst.URL, io.NopCloser(f))
 		if err != nil {
 			b.Fatal(err)
 		}
diff --git a/src/net/http/requestwrite_test.go b/src/net/http/requestwrite_test.go
index 9ac6701cfdd..1157bdfff94 100644
--- a/src/net/http/requestwrite_test.go
+++ b/src/net/http/requestwrite_test.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/url"
 	"strings"
@@ -229,7 +228,7 @@ var reqWriteTests = []reqWriteTest{
 			ContentLength: 0, // as if unset by user
 		},
 
-		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
+		Body: func() io.ReadCloser { return io.NopCloser(io.LimitReader(strings.NewReader("xx"), 0)) },
 
 		WantWrite: "POST / HTTP/1.1\r\n" +
 			"Host: example.com\r\n" +
@@ -281,7 +280,7 @@ var reqWriteTests = []reqWriteTest{
 			ContentLength: 0, // as if unset by user
 		},
 
-		Body: func() io.ReadCloser { return ioutil.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
+		Body: func() io.ReadCloser { return io.NopCloser(io.LimitReader(strings.NewReader("xx"), 1)) },
 
 		WantWrite: "POST / HTTP/1.1\r\n" +
 			"Host: example.com\r\n" +
@@ -351,7 +350,7 @@ var reqWriteTests = []reqWriteTest{
 		Body: func() io.ReadCloser {
 			err := errors.New("Custom reader error")
 			errReader := iotest.ErrReader(err)
-			return ioutil.NopCloser(io.MultiReader(strings.NewReader("x"), errReader))
+			return io.NopCloser(io.MultiReader(strings.NewReader("x"), errReader))
 		},
 
 		WantError: errors.New("Custom reader error"),
@@ -371,7 +370,7 @@ var reqWriteTests = []reqWriteTest{
 		Body: func() io.ReadCloser {
 			err := errors.New("Custom reader error")
 			errReader := iotest.ErrReader(err)
-			return ioutil.NopCloser(errReader)
+			return io.NopCloser(errReader)
 		},
 
 		WantError: errors.New("Custom reader error"),
@@ -620,7 +619,7 @@ func TestRequestWrite(t *testing.T) {
 			}
 			switch b := tt.Body.(type) {
 			case []byte:
-				tt.Req.Body = ioutil.NopCloser(bytes.NewReader(b))
+				tt.Req.Body = io.NopCloser(bytes.NewReader(b))
 			case func() io.ReadCloser:
 				tt.Req.Body = b()
 			}
@@ -716,20 +715,20 @@ func TestRequestWriteTransport(t *testing.T) {
 		},
 		{
 			method: "GET",
-			body:   ioutil.NopCloser(strings.NewReader("")),
+			body:   io.NopCloser(strings.NewReader("")),
 			want:   noContentLengthOrTransferEncoding,
 		},
 		{
 			method: "GET",
 			clen:   -1,
-			body:   ioutil.NopCloser(strings.NewReader("")),
+			body:   io.NopCloser(strings.NewReader("")),
 			want:   noContentLengthOrTransferEncoding,
 		},
 		// A GET with a body, with explicit content length:
 		{
 			method: "GET",
 			clen:   7,
-			body:   ioutil.NopCloser(strings.NewReader("foobody")),
+			body:   io.NopCloser(strings.NewReader("foobody")),
 			want: all(matchSubstr("Content-Length: 7"),
 				matchSubstr("foobody")),
 		},
@@ -737,7 +736,7 @@ func TestRequestWriteTransport(t *testing.T) {
 		{
 			method: "GET",
 			clen:   -1,
-			body:   ioutil.NopCloser(strings.NewReader("foobody")),
+			body:   io.NopCloser(strings.NewReader("foobody")),
 			want: all(matchSubstr("Transfer-Encoding: chunked"),
 				matchSubstr("\r\n1\r\nf\r\n"),
 				matchSubstr("oobody")),
@@ -747,14 +746,14 @@ func TestRequestWriteTransport(t *testing.T) {
 		{
 			method: "POST",
 			clen:   -1,
-			body:   ioutil.NopCloser(strings.NewReader("foobody")),
+			body:   io.NopCloser(strings.NewReader("foobody")),
 			want: all(matchSubstr("Transfer-Encoding: chunked"),
 				matchSubstr("foobody")),
 		},
 		{
 			method: "POST",
 			clen:   -1,
-			body:   ioutil.NopCloser(strings.NewReader("")),
+			body:   io.NopCloser(strings.NewReader("")),
 			want:   all(matchSubstr("Transfer-Encoding: chunked")),
 		},
 		// Verify that a blocking Request.Body doesn't block forever.
@@ -766,7 +765,7 @@ func TestRequestWriteTransport(t *testing.T) {
 				tt.afterReqRead = func() {
 					pw.Close()
 				}
-				tt.body = ioutil.NopCloser(pr)
+				tt.body = io.NopCloser(pr)
 			},
 			want: matchSubstr("Transfer-Encoding: chunked"),
 		},
@@ -937,7 +936,7 @@ func dumpRequestOut(req *Request, onReadHeaders func()) ([]byte, error) {
 			}
 			// Ensure all the body is read; otherwise
 			// we'll get a partial dump.
-			io.Copy(ioutil.Discard, req.Body)
+			io.Copy(io.Discard, req.Body)
 			req.Body.Close()
 		}
 		dr.c <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n")
diff --git a/src/net/http/response_test.go b/src/net/http/response_test.go
index ce872606b14..8eef65474e4 100644
--- a/src/net/http/response_test.go
+++ b/src/net/http/response_test.go
@@ -12,7 +12,6 @@ import (
 	"fmt"
 	"go/token"
 	"io"
-	"io/ioutil"
 	"net/http/internal"
 	"net/url"
 	"reflect"
@@ -620,7 +619,7 @@ func TestWriteResponse(t *testing.T) {
 			t.Errorf("#%d: %v", i, err)
 			continue
 		}
-		err = resp.Write(ioutil.Discard)
+		err = resp.Write(io.Discard)
 		if err != nil {
 			t.Errorf("#%d: %v", i, err)
 			continue
@@ -722,7 +721,7 @@ func TestReadResponseCloseInMiddle(t *testing.T) {
 		}
 		resp.Body.Close()
 
-		rest, err := ioutil.ReadAll(bufr)
+		rest, err := io.ReadAll(bufr)
 		checkErr(err, "ReadAll on remainder")
 		if e, g := "Next Request Here", string(rest); e != g {
 			g = regexp.MustCompile(`(xx+)`).ReplaceAllStringFunc(g, func(match string) string {
diff --git a/src/net/http/responsewrite_test.go b/src/net/http/responsewrite_test.go
index d41d89896ef..1cc87b942ed 100644
--- a/src/net/http/responsewrite_test.go
+++ b/src/net/http/responsewrite_test.go
@@ -6,7 +6,7 @@ package http
 
 import (
 	"bytes"
-	"io/ioutil"
+	"io"
 	"strings"
 	"testing"
 )
@@ -26,7 +26,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:    0,
 				Request:       dummyReq("GET"),
 				Header:        Header{},
-				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				Body:          io.NopCloser(strings.NewReader("abcdef")),
 				ContentLength: 6,
 			},
 
@@ -42,7 +42,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:    0,
 				Request:       dummyReq("GET"),
 				Header:        Header{},
-				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				Body:          io.NopCloser(strings.NewReader("abcdef")),
 				ContentLength: -1,
 			},
 			"HTTP/1.0 200 OK\r\n" +
@@ -57,7 +57,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:    1,
 				Request:       dummyReq("GET"),
 				Header:        Header{},
-				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				Body:          io.NopCloser(strings.NewReader("abcdef")),
 				ContentLength: -1,
 				Close:         true,
 			},
@@ -74,7 +74,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:    1,
 				Request:       dummyReq11("GET"),
 				Header:        Header{},
-				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				Body:          io.NopCloser(strings.NewReader("abcdef")),
 				ContentLength: -1,
 				Close:         false,
 			},
@@ -92,7 +92,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:       1,
 				Request:          dummyReq11("GET"),
 				Header:           Header{},
-				Body:             ioutil.NopCloser(strings.NewReader("abcdef")),
+				Body:             io.NopCloser(strings.NewReader("abcdef")),
 				ContentLength:    -1,
 				TransferEncoding: []string{"chunked"},
 				Close:            false,
@@ -125,7 +125,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:    1,
 				Request:       dummyReq11("GET"),
 				Header:        Header{},
-				Body:          ioutil.NopCloser(strings.NewReader("")),
+				Body:          io.NopCloser(strings.NewReader("")),
 				ContentLength: 0,
 				Close:         false,
 			},
@@ -141,7 +141,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:    1,
 				Request:       dummyReq11("GET"),
 				Header:        Header{},
-				Body:          ioutil.NopCloser(strings.NewReader("foo")),
+				Body:          io.NopCloser(strings.NewReader("foo")),
 				ContentLength: 0,
 				Close:         false,
 			},
@@ -157,7 +157,7 @@ func TestResponseWrite(t *testing.T) {
 				ProtoMinor:       1,
 				Request:          dummyReq("GET"),
 				Header:           Header{},
-				Body:             ioutil.NopCloser(strings.NewReader("abcdef")),
+				Body:             io.NopCloser(strings.NewReader("abcdef")),
 				ContentLength:    6,
 				TransferEncoding: []string{"chunked"},
 				Close:            true,
@@ -218,7 +218,7 @@ func TestResponseWrite(t *testing.T) {
 				Request:       &Request{Method: "POST"},
 				Header:        Header{},
 				ContentLength: -1,
-				Body:          ioutil.NopCloser(strings.NewReader("abcdef")),
+				Body:          io.NopCloser(strings.NewReader("abcdef")),
 			},
 			"HTTP/1.1 200 OK\r\nConnection: close\r\n\r\nabcdef",
 		},
diff --git a/src/net/http/roundtrip_js.go b/src/net/http/roundtrip_js.go
index b09923c3860..c6a221ac628 100644
--- a/src/net/http/roundtrip_js.go
+++ b/src/net/http/roundtrip_js.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strconv"
 	"syscall/js"
 )
@@ -92,7 +91,7 @@ func (t *Transport) RoundTrip(req *Request) (*Response, error) {
 		// See https://github.com/web-platform-tests/wpt/issues/7693 for WHATWG tests issue.
 		// See https://developer.mozilla.org/en-US/docs/Web/API/Streams_API for more details on the Streams API
 		// and browser support.
-		body, err := ioutil.ReadAll(req.Body)
+		body, err := io.ReadAll(req.Body)
 		if err != nil {
 			req.Body.Close() // RoundTrip must always close the body, including on errors.
 			return nil, err
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index d84804c2e9c..ba54b31a29d 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -18,7 +18,6 @@ import (
 	"fmt"
 	"internal/testenv"
 	"io"
-	"io/ioutil"
 	"log"
 	"math/rand"
 	"net"
@@ -529,7 +528,7 @@ func TestServeWithSlashRedirectKeepsQueryString(t *testing.T) {
 		if err != nil {
 			continue
 		}
-		slurp, _ := ioutil.ReadAll(res.Body)
+		slurp, _ := io.ReadAll(res.Body)
 		res.Body.Close()
 		if !tt.statusOk {
 			if got, want := res.StatusCode, 404; got != want {
@@ -689,7 +688,7 @@ func testServerTimeouts(timeout time.Duration) error {
 	if err != nil {
 		return fmt.Errorf("http Get #1: %v", err)
 	}
-	got, err := ioutil.ReadAll(r.Body)
+	got, err := io.ReadAll(r.Body)
 	expected := "req=1"
 	if string(got) != expected || err != nil {
 		return fmt.Errorf("Unexpected response for request #1; got %q ,%v; expected %q, nil",
@@ -721,7 +720,7 @@ func testServerTimeouts(timeout time.Duration) error {
 	if err != nil {
 		return fmt.Errorf("http Get #2: %v", err)
 	}
-	got, err = ioutil.ReadAll(r.Body)
+	got, err = io.ReadAll(r.Body)
 	r.Body.Close()
 	expected = "req=2"
 	if string(got) != expected || err != nil {
@@ -734,7 +733,7 @@ func testServerTimeouts(timeout time.Duration) error {
 			return fmt.Errorf("long Dial: %v", err)
 		}
 		defer conn.Close()
-		go io.Copy(ioutil.Discard, conn)
+		go io.Copy(io.Discard, conn)
 		for i := 0; i < 5; i++ {
 			_, err := conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"))
 			if err != nil {
@@ -954,7 +953,7 @@ func TestOnlyWriteTimeout(t *testing.T) {
 			errc <- err
 			return
 		}
-		_, err = io.Copy(ioutil.Discard, res.Body)
+		_, err = io.Copy(io.Discard, res.Body)
 		res.Body.Close()
 		errc <- err
 	}()
@@ -1058,7 +1057,7 @@ func TestIdentityResponse(t *testing.T) {
 	}
 
 	// The ReadAll will hang for a failing test.
-	got, _ := ioutil.ReadAll(conn)
+	got, _ := io.ReadAll(conn)
 	expectedSuffix := "\r\n\r\ntoo short"
 	if !strings.HasSuffix(string(got), expectedSuffix) {
 		t.Errorf("Expected output to end with %q; got response body %q",
@@ -1099,7 +1098,7 @@ func testTCPConnectionCloses(t *testing.T, req string, h Handler) {
 		}
 	}()
 
-	_, err = ioutil.ReadAll(r)
+	_, err = io.ReadAll(r)
 	if err != nil {
 		t.Fatal("read error:", err)
 	}
@@ -1129,7 +1128,7 @@ func testTCPConnectionStaysOpen(t *testing.T, req string, handler Handler) {
 		if err != nil {
 			t.Fatalf("res %d: %v", i+1, err)
 		}
-		if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+		if _, err := io.Copy(io.Discard, res.Body); err != nil {
 			t.Fatalf("res %d body copy: %v", i+1, err)
 		}
 		res.Body.Close()
@@ -1235,7 +1234,7 @@ func testSetsRemoteAddr(t *testing.T, h2 bool) {
 	if err != nil {
 		t.Fatalf("Get error: %v", err)
 	}
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatalf("ReadAll error: %v", err)
 	}
@@ -1299,7 +1298,7 @@ func TestServerAllowsBlockingRemoteAddr(t *testing.T) {
 			return
 		}
 		defer resp.Body.Close()
-		body, err := ioutil.ReadAll(resp.Body)
+		body, err := io.ReadAll(resp.Body)
 		if err != nil {
 			t.Errorf("Request %d: %v", num, err)
 			response <- ""
@@ -1381,7 +1380,7 @@ func testHeadResponses(t *testing.T, h2 bool) {
 	if v := res.ContentLength; v != 10 {
 		t.Errorf("Content-Length: %d; want 10", v)
 	}
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Error(err)
 	}
@@ -1432,7 +1431,7 @@ func TestTLSServer(t *testing.T) {
 			}
 		}
 	}))
-	ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+	ts.Config.ErrorLog = log.New(io.Discard, "", 0)
 	defer ts.Close()
 
 	// Connect an idle TCP connection to this server before we run
@@ -1540,7 +1539,7 @@ func TestTLSServerRejectHTTPRequests(t *testing.T) {
 	}
 	defer conn.Close()
 	io.WriteString(conn, "GET / HTTP/1.1\r\nHost: foo\r\n\r\n")
-	slurp, err := ioutil.ReadAll(conn)
+	slurp, err := io.ReadAll(conn)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1734,7 +1733,7 @@ func TestServerExpect(t *testing.T) {
 		// requests that would read from r.Body, which we only
 		// conditionally want to do.
 		if strings.Contains(r.URL.RawQuery, "readbody=true") {
-			ioutil.ReadAll(r.Body)
+			io.ReadAll(r.Body)
 			w.Write([]byte("Hi"))
 		} else {
 			w.WriteHeader(StatusUnauthorized)
@@ -1773,7 +1772,7 @@ func TestServerExpect(t *testing.T) {
 					io.Closer
 				}{
 					conn,
-					ioutil.NopCloser(nil),
+					io.NopCloser(nil),
 				}
 				if test.chunked {
 					targ = httputil.NewChunkedWriter(conn)
@@ -2072,7 +2071,7 @@ type testHandlerBodyConsumer struct {
 var testHandlerBodyConsumers = []testHandlerBodyConsumer{
 	{"nil", func(io.ReadCloser) {}},
 	{"close", func(r io.ReadCloser) { r.Close() }},
-	{"discard", func(r io.ReadCloser) { io.Copy(ioutil.Discard, r) }},
+	{"discard", func(r io.ReadCloser) { io.Copy(io.Discard, r) }},
 }
 
 func TestRequestBodyReadErrorClosesConnection(t *testing.T) {
@@ -2298,7 +2297,7 @@ func testTimeoutHandler(t *testing.T, h2 bool) {
 	if g, e := res.StatusCode, StatusOK; g != e {
 		t.Errorf("got res.StatusCode %d; expected %d", g, e)
 	}
-	body, _ := ioutil.ReadAll(res.Body)
+	body, _ := io.ReadAll(res.Body)
 	if g, e := string(body), "hi"; g != e {
 		t.Errorf("got body %q; expected %q", g, e)
 	}
@@ -2315,7 +2314,7 @@ func testTimeoutHandler(t *testing.T, h2 bool) {
 	if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
 		t.Errorf("got res.StatusCode %d; expected %d", g, e)
 	}
-	body, _ = ioutil.ReadAll(res.Body)
+	body, _ = io.ReadAll(res.Body)
 	if !strings.Contains(string(body), "Timeout") {
 		t.Errorf("expected timeout body; got %q", string(body))
 	}
@@ -2367,7 +2366,7 @@ func TestTimeoutHandlerRace(t *testing.T) {
 			defer func() { <-gate }()
 			res, err := c.Get(fmt.Sprintf("%s/%d", ts.URL, rand.Intn(50)))
 			if err == nil {
-				io.Copy(ioutil.Discard, res.Body)
+				io.Copy(io.Discard, res.Body)
 				res.Body.Close()
 			}
 		}()
@@ -2410,7 +2409,7 @@ func TestTimeoutHandlerRaceHeader(t *testing.T) {
 				return
 			}
 			defer res.Body.Close()
-			io.Copy(ioutil.Discard, res.Body)
+			io.Copy(io.Discard, res.Body)
 		}()
 	}
 	wg.Wait()
@@ -2441,7 +2440,7 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
 	if g, e := res.StatusCode, StatusOK; g != e {
 		t.Errorf("got res.StatusCode %d; expected %d", g, e)
 	}
-	body, _ := ioutil.ReadAll(res.Body)
+	body, _ := io.ReadAll(res.Body)
 	if g, e := string(body), "hi"; g != e {
 		t.Errorf("got body %q; expected %q", g, e)
 	}
@@ -2458,7 +2457,7 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
 	if g, e := res.StatusCode, StatusServiceUnavailable; g != e {
 		t.Errorf("got res.StatusCode %d; expected %d", g, e)
 	}
-	body, _ = ioutil.ReadAll(res.Body)
+	body, _ = io.ReadAll(res.Body)
 	if !strings.Contains(string(body), "Timeout") {
 		t.Errorf("expected timeout body; got %q", string(body))
 	}
@@ -2630,7 +2629,7 @@ func TestRedirectContentTypeAndBody(t *testing.T) {
 			t.Errorf("Redirect(%q, %#v) generated Content-Type header %q; want %q", tt.method, tt.ct, got, want)
 		}
 		resp := rec.Result()
-		body, err := ioutil.ReadAll(resp.Body)
+		body, err := io.ReadAll(resp.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -2657,7 +2656,7 @@ func testZeroLengthPostAndResponse(t *testing.T, h2 bool) {
 	setParallel(t)
 	defer afterTest(t)
 	cst := newClientServerTest(t, h2, HandlerFunc(func(rw ResponseWriter, r *Request) {
-		all, err := ioutil.ReadAll(r.Body)
+		all, err := io.ReadAll(r.Body)
 		if err != nil {
 			t.Fatalf("handler ReadAll: %v", err)
 		}
@@ -2683,7 +2682,7 @@ func testZeroLengthPostAndResponse(t *testing.T, h2 bool) {
 	}
 
 	for i := range resp {
-		all, err := ioutil.ReadAll(resp[i].Body)
+		all, err := io.ReadAll(resp[i].Body)
 		if err != nil {
 			t.Fatalf("req #%d: client ReadAll: %v", i, err)
 		}
@@ -2710,7 +2709,7 @@ func TestHandlerPanicWithHijack(t *testing.T) {
 
 func testHandlerPanic(t *testing.T, withHijack, h2 bool, wrapper func(Handler) Handler, panicValue interface{}) {
 	defer afterTest(t)
-	// Unlike the other tests that set the log output to ioutil.Discard
+	// Unlike the other tests that set the log output to io.Discard
 	// to quiet the output, this test uses a pipe. The pipe serves three
 	// purposes:
 	//
@@ -2970,7 +2969,7 @@ func testRequestBodyLimit(t *testing.T, h2 bool) {
 	const limit = 1 << 20
 	cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
 		r.Body = MaxBytesReader(w, r.Body, limit)
-		n, err := io.Copy(ioutil.Discard, r.Body)
+		n, err := io.Copy(io.Discard, r.Body)
 		if err == nil {
 			t.Errorf("expected error from io.Copy")
 		}
@@ -3020,7 +3019,7 @@ func TestClientWriteShutdown(t *testing.T) {
 	donec := make(chan bool)
 	go func() {
 		defer close(donec)
-		bs, err := ioutil.ReadAll(conn)
+		bs, err := io.ReadAll(conn)
 		if err != nil {
 			t.Errorf("ReadAll: %v", err)
 		}
@@ -3341,7 +3340,7 @@ func TestHijackBeforeRequestBodyRead(t *testing.T) {
 		r.Body = nil // to test that server.go doesn't use this value.
 
 		gone := w.(CloseNotifier).CloseNotify()
-		slurp, err := ioutil.ReadAll(reqBody)
+		slurp, err := io.ReadAll(reqBody)
 		if err != nil {
 			t.Errorf("Body read: %v", err)
 			return
@@ -3643,7 +3642,7 @@ func TestAcceptMaxFds(t *testing.T) {
 		}}}
 	server := &Server{
 		Handler:  HandlerFunc(HandlerFunc(func(ResponseWriter, *Request) {})),
-		ErrorLog: log.New(ioutil.Discard, "", 0), // noisy otherwise
+		ErrorLog: log.New(io.Discard, "", 0), // noisy otherwise
 	}
 	err := server.Serve(ln)
 	if err != io.EOF {
@@ -3782,7 +3781,7 @@ func testServerReaderFromOrder(t *testing.T, h2 bool) {
 			close(done)
 		}()
 		time.Sleep(25 * time.Millisecond) // give Copy a chance to break things
-		n, err := io.Copy(ioutil.Discard, req.Body)
+		n, err := io.Copy(io.Discard, req.Body)
 		if err != nil {
 			t.Errorf("handler Copy: %v", err)
 			return
@@ -3804,7 +3803,7 @@ func testServerReaderFromOrder(t *testing.T, h2 bool) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	all, err := ioutil.ReadAll(res.Body)
+	all, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -3929,7 +3928,7 @@ func testTransportAndServerSharedBodyRace(t *testing.T, h2 bool) {
 			errorf("Proxy outbound request: %v", err)
 			return
 		}
-		_, err = io.CopyN(ioutil.Discard, bresp.Body, bodySize/2)
+		_, err = io.CopyN(io.Discard, bresp.Body, bodySize/2)
 		if err != nil {
 			errorf("Proxy copy error: %v", err)
 			return
@@ -4136,7 +4135,7 @@ func TestServerConnState(t *testing.T) {
 		ts.Close()
 	}()
 
-	ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+	ts.Config.ErrorLog = log.New(io.Discard, "", 0)
 	ts.Config.ConnState = func(c net.Conn, state ConnState) {
 		if c == nil {
 			t.Errorf("nil conn seen in state %s", state)
@@ -4176,7 +4175,7 @@ func TestServerConnState(t *testing.T) {
 			t.Errorf("Error fetching %s: %v", url, err)
 			return
 		}
-		_, err = ioutil.ReadAll(res.Body)
+		_, err = io.ReadAll(res.Body)
 		defer res.Body.Close()
 		if err != nil {
 			t.Errorf("Error reading %s: %v", url, err)
@@ -4233,7 +4232,7 @@ func TestServerConnState(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+		if _, err := io.Copy(io.Discard, res.Body); err != nil {
 			t.Fatal(err)
 		}
 		c.Close()
@@ -4285,7 +4284,7 @@ func testServerEmptyBodyRace(t *testing.T, h2 bool) {
 				}
 			}
 			defer res.Body.Close()
-			_, err = io.Copy(ioutil.Discard, res.Body)
+			_, err = io.Copy(io.Discard, res.Body)
 			if err != nil {
 				t.Error(err)
 				return
@@ -4311,7 +4310,7 @@ func TestServerConnStateNew(t *testing.T) {
 	srv.Serve(&oneConnListener{
 		conn: &rwTestConn{
 			Reader: strings.NewReader("GET / HTTP/1.1\r\nHost: foo\r\n\r\n"),
-			Writer: ioutil.Discard,
+			Writer: io.Discard,
 		},
 	})
 	if !sawNew { // testing that this read isn't racy
@@ -4367,7 +4366,7 @@ func TestServerFlushAndHijack(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer res.Body.Close()
-	all, err := ioutil.ReadAll(res.Body)
+	all, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -4555,7 +4554,7 @@ Host: foo
 	go Serve(ln, HandlerFunc(func(w ResponseWriter, r *Request) {
 		numReq++
 		if r.URL.Path == "/readbody" {
-			ioutil.ReadAll(r.Body)
+			io.ReadAll(r.Body)
 		}
 		io.WriteString(w, "Hello world!")
 	}))
@@ -4608,7 +4607,7 @@ func testHandlerSetsBodyNil(t *testing.T, h2 bool) {
 			t.Fatal(err)
 		}
 		defer res.Body.Close()
-		slurp, err := ioutil.ReadAll(res.Body)
+		slurp, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -4724,7 +4723,7 @@ func TestServerHandlersCanHandleH2PRI(t *testing.T) {
 	}
 	defer c.Close()
 	io.WriteString(c, "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")
-	slurp, err := ioutil.ReadAll(c)
+	slurp, err := io.ReadAll(c)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -4958,7 +4957,7 @@ func BenchmarkClientServer(b *testing.B) {
 		if err != nil {
 			b.Fatal("Get:", err)
 		}
-		all, err := ioutil.ReadAll(res.Body)
+		all, err := io.ReadAll(res.Body)
 		res.Body.Close()
 		if err != nil {
 			b.Fatal("ReadAll:", err)
@@ -5009,7 +5008,7 @@ func benchmarkClientServerParallel(b *testing.B, parallelism int, useTLS bool) {
 				b.Logf("Get: %v", err)
 				continue
 			}
-			all, err := ioutil.ReadAll(res.Body)
+			all, err := io.ReadAll(res.Body)
 			res.Body.Close()
 			if err != nil {
 				b.Logf("ReadAll: %v", err)
@@ -5044,7 +5043,7 @@ func BenchmarkServer(b *testing.B) {
 			if err != nil {
 				log.Panicf("Get: %v", err)
 			}
-			all, err := ioutil.ReadAll(res.Body)
+			all, err := io.ReadAll(res.Body)
 			res.Body.Close()
 			if err != nil {
 				log.Panicf("ReadAll: %v", err)
@@ -5167,7 +5166,7 @@ func BenchmarkClient(b *testing.B) {
 		if err != nil {
 			b.Fatalf("Get: %v", err)
 		}
-		body, err := ioutil.ReadAll(res.Body)
+		body, err := io.ReadAll(res.Body)
 		res.Body.Close()
 		if err != nil {
 			b.Fatalf("ReadAll: %v", err)
@@ -5257,7 +5256,7 @@ Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
 
 	conn := &rwTestConn{
 		Reader: &repeatReader{content: req, count: b.N},
-		Writer: ioutil.Discard,
+		Writer: io.Discard,
 		closec: make(chan bool, 1),
 	}
 	handled := 0
@@ -5286,7 +5285,7 @@ Host: golang.org
 
 	conn := &rwTestConn{
 		Reader: &repeatReader{content: req, count: b.N},
-		Writer: ioutil.Discard,
+		Writer: io.Discard,
 		closec: make(chan bool, 1),
 	}
 	handled := 0
@@ -5346,7 +5345,7 @@ Host: golang.org
 `)
 	conn := &rwTestConn{
 		Reader: &repeatReader{content: req, count: b.N},
-		Writer: ioutil.Discard,
+		Writer: io.Discard,
 		closec: make(chan bool, 1),
 	}
 	handled := 0
@@ -5375,7 +5374,7 @@ Host: golang.org
 		conn.Close()
 	})
 	conn := &rwTestConn{
-		Writer: ioutil.Discard,
+		Writer: io.Discard,
 		closec: make(chan bool, 1),
 	}
 	ln := &oneConnListener{conn: conn}
@@ -5438,7 +5437,7 @@ func TestServerIdleTimeout(t *testing.T) {
 	setParallel(t)
 	defer afterTest(t)
 	ts := httptest.NewUnstartedServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		io.Copy(ioutil.Discard, r.Body)
+		io.Copy(io.Discard, r.Body)
 		io.WriteString(w, r.RemoteAddr)
 	}))
 	ts.Config.ReadHeaderTimeout = 1 * time.Second
@@ -5453,7 +5452,7 @@ func TestServerIdleTimeout(t *testing.T) {
 			t.Fatal(err)
 		}
 		defer res.Body.Close()
-		slurp, err := ioutil.ReadAll(res.Body)
+		slurp, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -5478,7 +5477,7 @@ func TestServerIdleTimeout(t *testing.T) {
 	defer conn.Close()
 	conn.Write([]byte("GET / HTTP/1.1\r\nHost: foo.com\r\n"))
 	time.Sleep(2 * time.Second)
-	if _, err := io.CopyN(ioutil.Discard, conn, 1); err == nil {
+	if _, err := io.CopyN(io.Discard, conn, 1); err == nil {
 		t.Fatal("copy byte succeeded; want err")
 	}
 }
@@ -5489,7 +5488,7 @@ func get(t *testing.T, c *Client, url string) string {
 		t.Fatal(err)
 	}
 	defer res.Body.Close()
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -5739,7 +5738,7 @@ func TestServerCancelsReadTimeoutWhenIdle(t *testing.T) {
 		if err != nil {
 			return fmt.Errorf("Get: %v", err)
 		}
-		slurp, err := ioutil.ReadAll(res.Body)
+		slurp, err := io.ReadAll(res.Body)
 		res.Body.Close()
 		if err != nil {
 			return fmt.Errorf("Body ReadAll: %v", err)
@@ -5802,7 +5801,7 @@ func TestServerDuplicateBackgroundRead(t *testing.T) {
 			wg.Add(1)
 			go func() {
 				defer wg.Done()
-				io.Copy(ioutil.Discard, cn)
+				io.Copy(io.Discard, cn)
 			}()
 
 			for j := 0; j < requests; j++ {
@@ -5902,7 +5901,7 @@ func TestServerHijackGetsBackgroundByte_big(t *testing.T) {
 			return
 		}
 		defer conn.Close()
-		slurp, err := ioutil.ReadAll(buf.Reader)
+		slurp, err := io.ReadAll(buf.Reader)
 		if err != nil {
 			t.Errorf("Copy: %v", err)
 		}
@@ -6436,13 +6435,13 @@ func fetchWireResponse(host string, http1ReqBody []byte) ([]byte, error) {
 	if _, err := conn.Write(http1ReqBody); err != nil {
 		return nil, err
 	}
-	return ioutil.ReadAll(conn)
+	return io.ReadAll(conn)
 }
 
 func BenchmarkResponseStatusLine(b *testing.B) {
 	b.ReportAllocs()
 	b.RunParallel(func(pb *testing.PB) {
-		bw := bufio.NewWriter(ioutil.Discard)
+		bw := bufio.NewWriter(io.Discard)
 		var buf3 [3]byte
 		for pb.Next() {
 			Export_writeStatusLine(bw, true, 200, buf3[:])
diff --git a/src/net/http/server.go b/src/net/http/server.go
index fab229c92af..ba473d14f5b 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -14,7 +14,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"net/textproto"
@@ -1368,7 +1367,7 @@ func (cw *chunkWriter) writeHeader(p []byte) {
 		}
 
 		if discard {
-			_, err := io.CopyN(ioutil.Discard, w.reqBody, maxPostHandlerReadBytes+1)
+			_, err := io.CopyN(io.Discard, w.reqBody, maxPostHandlerReadBytes+1)
 			switch err {
 			case nil:
 				// There must be even more data left over.
@@ -3407,7 +3406,7 @@ func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
 		// (or an attack) and we abort and close the connection,
 		// courtesy of MaxBytesReader's EOF behavior.
 		mb := MaxBytesReader(w, r.Body, 4<<10)
-		io.Copy(ioutil.Discard, mb)
+		io.Copy(io.Discard, mb)
 	}
 }
 
diff --git a/src/net/http/sniff_test.go b/src/net/http/sniff_test.go
index a1157a0823e..8d5350374dd 100644
--- a/src/net/http/sniff_test.go
+++ b/src/net/http/sniff_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	. "net/http"
 	"reflect"
@@ -123,7 +122,7 @@ func testServerContentType(t *testing.T, h2 bool) {
 		if ct := resp.Header.Get("Content-Type"); ct != wantContentType {
 			t.Errorf("%v: Content-Type = %q, want %q", tt.desc, ct, wantContentType)
 		}
-		data, err := ioutil.ReadAll(resp.Body)
+		data, err := io.ReadAll(resp.Body)
 		if err != nil {
 			t.Errorf("%v: reading body: %v", tt.desc, err)
 		} else if !bytes.Equal(data, tt.data) {
@@ -185,7 +184,7 @@ func testContentTypeWithCopy(t *testing.T, h2 bool) {
 	if ct := resp.Header.Get("Content-Type"); ct != expected {
 		t.Errorf("Content-Type = %q, want %q", ct, expected)
 	}
-	data, err := ioutil.ReadAll(resp.Body)
+	data, err := io.ReadAll(resp.Body)
 	if err != nil {
 		t.Errorf("reading body: %v", err)
 	} else if !bytes.Equal(data, []byte(input)) {
@@ -216,7 +215,7 @@ func testSniffWriteSize(t *testing.T, h2 bool) {
 		if err != nil {
 			t.Fatalf("size %d: %v", size, err)
 		}
-		if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+		if _, err := io.Copy(io.Discard, res.Body); err != nil {
 			t.Fatalf("size %d: io.Copy of body = %v", size, err)
 		}
 		if err := res.Body.Close(); err != nil {
diff --git a/src/net/http/transfer.go b/src/net/http/transfer.go
index c3234f30cc3..fbb0c39829d 100644
--- a/src/net/http/transfer.go
+++ b/src/net/http/transfer.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net/http/httptrace"
 	"net/http/internal"
 	"net/textproto"
@@ -156,7 +155,7 @@ func newTransferWriter(r interface{}) (t *transferWriter, err error) {
 // servers. See Issue 18257, as one example.
 //
 // The only reason we'd send such a request is if the user set the Body to a
-// non-nil value (say, ioutil.NopCloser(bytes.NewReader(nil))) and didn't
+// non-nil value (say, io.NopCloser(bytes.NewReader(nil))) and didn't
 // set ContentLength, or NewRequest set it to -1 (unknown), so then we assume
 // there's bytes to send.
 //
@@ -370,7 +369,7 @@ func (t *transferWriter) writeBody(w io.Writer) (err error) {
 				return err
 			}
 			var nextra int64
-			nextra, err = t.doBodyCopy(ioutil.Discard, body)
+			nextra, err = t.doBodyCopy(io.Discard, body)
 			ncopy += nextra
 		}
 		if err != nil {
@@ -992,7 +991,7 @@ func (b *body) Close() error {
 			var n int64
 			// Consume the body, or, which will also lead to us reading
 			// the trailer headers after the body, if present.
-			n, err = io.CopyN(ioutil.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
+			n, err = io.CopyN(io.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
 			if err == io.EOF {
 				err = nil
 			}
@@ -1003,7 +1002,7 @@ func (b *body) Close() error {
 	default:
 		// Fully consume the body, which will also lead to us reading
 		// the trailer headers after the body, if present.
-		_, err = io.Copy(ioutil.Discard, bodyLocked{b})
+		_, err = io.Copy(io.Discard, bodyLocked{b})
 	}
 	b.closed = true
 	return err
@@ -1075,7 +1074,7 @@ func (fr finishAsyncByteRead) Read(p []byte) (n int, err error) {
 	return
 }
 
-var nopCloserType = reflect.TypeOf(ioutil.NopCloser(nil))
+var nopCloserType = reflect.TypeOf(io.NopCloser(nil))
 
 // isKnownInMemoryReader reports whether r is a type known to not
 // block on Read. Its caller uses this as an optional optimization to
diff --git a/src/net/http/transfer_test.go b/src/net/http/transfer_test.go
index 185225fa931..1f3d32526df 100644
--- a/src/net/http/transfer_test.go
+++ b/src/net/http/transfer_test.go
@@ -81,11 +81,11 @@ func TestDetectInMemoryReaders(t *testing.T) {
 		{bytes.NewBuffer(nil), true},
 		{strings.NewReader(""), true},
 
-		{ioutil.NopCloser(pr), false},
+		{io.NopCloser(pr), false},
 
-		{ioutil.NopCloser(bytes.NewReader(nil)), true},
-		{ioutil.NopCloser(bytes.NewBuffer(nil)), true},
-		{ioutil.NopCloser(strings.NewReader("")), true},
+		{io.NopCloser(bytes.NewReader(nil)), true},
+		{io.NopCloser(bytes.NewBuffer(nil)), true},
+		{io.NopCloser(strings.NewReader("")), true},
 	}
 	for i, tt := range tests {
 		got := isKnownInMemoryReader(tt.r)
@@ -104,12 +104,12 @@ var _ io.ReaderFrom = (*mockTransferWriter)(nil)
 
 func (w *mockTransferWriter) ReadFrom(r io.Reader) (int64, error) {
 	w.CalledReader = r
-	return io.Copy(ioutil.Discard, r)
+	return io.Copy(io.Discard, r)
 }
 
 func (w *mockTransferWriter) Write(p []byte) (int, error) {
 	w.WriteCalled = true
-	return ioutil.Discard.Write(p)
+	return io.Discard.Write(p)
 }
 
 func TestTransferWriterWriteBodyReaderTypes(t *testing.T) {
@@ -166,7 +166,7 @@ func TestTransferWriterWriteBodyReaderTypes(t *testing.T) {
 			method: "PUT",
 			bodyFunc: func() (io.Reader, func(), error) {
 				r, cleanup, err := newFileFunc()
-				return ioutil.NopCloser(r), cleanup, err
+				return io.NopCloser(r), cleanup, err
 			},
 			contentLength:  nBytes,
 			limitedReader:  true,
@@ -206,7 +206,7 @@ func TestTransferWriterWriteBodyReaderTypes(t *testing.T) {
 			method: "PUT",
 			bodyFunc: func() (io.Reader, func(), error) {
 				r, cleanup, err := newBufferFunc()
-				return ioutil.NopCloser(r), cleanup, err
+				return io.NopCloser(r), cleanup, err
 			},
 			contentLength:  nBytes,
 			limitedReader:  true,
diff --git a/src/net/http/transport_internal_test.go b/src/net/http/transport_internal_test.go
index 92729e65b26..1097ffd1739 100644
--- a/src/net/http/transport_internal_test.go
+++ b/src/net/http/transport_internal_test.go
@@ -11,7 +11,6 @@ import (
 	"crypto/tls"
 	"errors"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/http/internal"
 	"strings"
@@ -226,7 +225,7 @@ func TestTransportBodyAltRewind(t *testing.T) {
 		TLSNextProto: map[string]func(string, *tls.Conn) RoundTripper{
 			"foo": func(authority string, c *tls.Conn) RoundTripper {
 				return roundTripFunc(func(r *Request) (*Response, error) {
-					n, _ := io.Copy(ioutil.Discard, r.Body)
+					n, _ := io.Copy(io.Discard, r.Body)
 					if n == 0 {
 						t.Error("body length is zero")
 					}
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index b1520072826..58f0d9db989 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -173,7 +173,7 @@ func TestTransportKeepAlives(t *testing.T) {
 			if err != nil {
 				t.Fatalf("error in disableKeepAlive=%v, req #%d, GET: %v", disableKeepAlive, n, err)
 			}
-			body, err := ioutil.ReadAll(res.Body)
+			body, err := io.ReadAll(res.Body)
 			if err != nil {
 				t.Fatalf("error in disableKeepAlive=%v, req #%d, ReadAll: %v", disableKeepAlive, n, err)
 			}
@@ -220,7 +220,7 @@ func TestTransportConnectionCloseOnResponse(t *testing.T) {
 				t.Fatalf("error in connectionClose=%v, req #%d, Do: %v", connectionClose, n, err)
 			}
 			defer res.Body.Close()
-			body, err := ioutil.ReadAll(res.Body)
+			body, err := io.ReadAll(res.Body)
 			if err != nil {
 				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
 			}
@@ -273,7 +273,7 @@ func TestTransportConnectionCloseOnRequest(t *testing.T) {
 				t.Errorf("For connectionClose = %v; handler's X-Saw-Close was %v; want %v",
 					connectionClose, got, !connectionClose)
 			}
-			body, err := ioutil.ReadAll(res.Body)
+			body, err := io.ReadAll(res.Body)
 			if err != nil {
 				t.Fatalf("error in connectionClose=%v, req #%d, ReadAll: %v", connectionClose, n, err)
 			}
@@ -382,7 +382,7 @@ func TestTransportIdleCacheKeys(t *testing.T) {
 	if err != nil {
 		t.Error(err)
 	}
-	ioutil.ReadAll(resp.Body)
+	io.ReadAll(resp.Body)
 
 	keys := tr.IdleConnKeysForTesting()
 	if e, g := 1, len(keys); e != g {
@@ -495,7 +495,7 @@ func TestTransportMaxPerHostIdleConns(t *testing.T) {
 			t.Error(err)
 			return
 		}
-		if _, err := ioutil.ReadAll(resp.Body); err != nil {
+		if _, err := io.ReadAll(resp.Body); err != nil {
 			t.Errorf("ReadAll: %v", err)
 			return
 		}
@@ -575,7 +575,7 @@ func TestTransportMaxConnsPerHostIncludeDialInProgress(t *testing.T) {
 		if err != nil {
 			t.Errorf("unexpected error for request %s: %v", reqId, err)
 		}
-		_, err = ioutil.ReadAll(resp.Body)
+		_, err = io.ReadAll(resp.Body)
 		if err != nil {
 			t.Errorf("unexpected error for request %s: %v", reqId, err)
 		}
@@ -655,7 +655,7 @@ func TestTransportMaxConnsPerHost(t *testing.T) {
 				t.Fatalf("request failed: %v", err)
 			}
 			defer resp.Body.Close()
-			_, err = ioutil.ReadAll(resp.Body)
+			_, err = io.ReadAll(resp.Body)
 			if err != nil {
 				t.Fatalf("read body failed: %v", err)
 			}
@@ -733,7 +733,7 @@ func TestTransportRemovesDeadIdleConnections(t *testing.T) {
 			t.Fatalf("%s: %v", name, res.Status)
 		}
 		defer res.Body.Close()
-		slurp, err := ioutil.ReadAll(res.Body)
+		slurp, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatalf("%s: %v", name, err)
 		}
@@ -783,7 +783,7 @@ func TestTransportServerClosingUnexpectedly(t *testing.T) {
 				condFatalf("error in req #%d, GET: %v", n, err)
 				continue
 			}
-			body, err := ioutil.ReadAll(res.Body)
+			body, err := io.ReadAll(res.Body)
 			if err != nil {
 				condFatalf("error in req #%d, ReadAll: %v", n, err)
 				continue
@@ -903,7 +903,7 @@ func TestTransportHeadResponses(t *testing.T) {
 		if e, g := int64(123), res.ContentLength; e != g {
 			t.Errorf("loop %d: expected res.ContentLength of %v, got %v", i, e, g)
 		}
-		if all, err := ioutil.ReadAll(res.Body); err != nil {
+		if all, err := io.ReadAll(res.Body); err != nil {
 			t.Errorf("loop %d: Body ReadAll: %v", i, err)
 		} else if len(all) != 0 {
 			t.Errorf("Bogus body %q", all)
@@ -1006,10 +1006,10 @@ func TestRoundTripGzip(t *testing.T) {
 				t.Errorf("%d. gzip NewReader: %v", i, err)
 				continue
 			}
-			body, err = ioutil.ReadAll(r)
+			body, err = io.ReadAll(r)
 			res.Body.Close()
 		} else {
-			body, err = ioutil.ReadAll(res.Body)
+			body, err = io.ReadAll(res.Body)
 		}
 		if err != nil {
 			t.Errorf("%d. Error: %q", i, err)
@@ -1090,7 +1090,7 @@ func TestTransportGzip(t *testing.T) {
 		if err != nil {
 			t.Fatal(err)
 		}
-		body, err := ioutil.ReadAll(res.Body)
+		body, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -1133,7 +1133,7 @@ func TestTransportExpect100Continue(t *testing.T) {
 		switch req.URL.Path {
 		case "/100":
 			// This endpoint implicitly responds 100 Continue and reads body.
-			if _, err := io.Copy(ioutil.Discard, req.Body); err != nil {
+			if _, err := io.Copy(io.Discard, req.Body); err != nil {
 				t.Error("Failed to read Body", err)
 			}
 			rw.WriteHeader(StatusOK)
@@ -1159,7 +1159,7 @@ func TestTransportExpect100Continue(t *testing.T) {
 			if err != nil {
 				log.Fatal(err)
 			}
-			if _, err := io.CopyN(ioutil.Discard, bufrw, req.ContentLength); err != nil {
+			if _, err := io.CopyN(io.Discard, bufrw, req.ContentLength); err != nil {
 				t.Error("Failed to read Body", err)
 			}
 			bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n")
@@ -1625,7 +1625,7 @@ func TestTransportGzipRecursive(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -1654,7 +1654,7 @@ func TestTransportGzipShort(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer res.Body.Close()
-	_, err = ioutil.ReadAll(res.Body)
+	_, err = io.ReadAll(res.Body)
 	if err == nil {
 		t.Fatal("Expect an error from reading a body.")
 	}
@@ -1999,7 +1999,7 @@ func TestIssue3644(t *testing.T) {
 		t.Fatal(err)
 	}
 	defer res.Body.Close()
-	bs, err := ioutil.ReadAll(res.Body)
+	bs, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -2024,7 +2024,7 @@ func TestIssue3595(t *testing.T) {
 		t.Errorf("Post: %v", err)
 		return
 	}
-	got, err := ioutil.ReadAll(res.Body)
+	got, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatalf("Body ReadAll: %v", err)
 	}
@@ -2096,7 +2096,7 @@ func TestTransportConcurrency(t *testing.T) {
 					wg.Done()
 					continue
 				}
-				all, err := ioutil.ReadAll(res.Body)
+				all, err := io.ReadAll(res.Body)
 				if err != nil {
 					t.Errorf("read error on req %s: %v", req, err)
 					wg.Done()
@@ -2163,7 +2163,7 @@ func TestIssue4191_InfiniteGetTimeout(t *testing.T) {
 			t.Errorf("Error issuing GET: %v", err)
 			break
 		}
-		_, err = io.Copy(ioutil.Discard, sres.Body)
+		_, err = io.Copy(io.Discard, sres.Body)
 		if err == nil {
 			t.Errorf("Unexpected successful copy")
 			break
@@ -2184,7 +2184,7 @@ func TestIssue4191_InfiniteGetToPutTimeout(t *testing.T) {
 	})
 	mux.HandleFunc("/put", func(w ResponseWriter, r *Request) {
 		defer r.Body.Close()
-		io.Copy(ioutil.Discard, r.Body)
+		io.Copy(io.Discard, r.Body)
 	})
 	ts := httptest.NewServer(mux)
 	timeout := 100 * time.Millisecond
@@ -2338,7 +2338,7 @@ func TestTransportCancelRequest(t *testing.T) {
 		tr.CancelRequest(req)
 	}()
 	t0 := time.Now()
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	d := time.Since(t0)
 
 	if err != ExportErrRequestCanceled {
@@ -2497,7 +2497,7 @@ func TestCancelRequestWithChannel(t *testing.T) {
 		close(ch)
 	}()
 	t0 := time.Now()
-	body, err := ioutil.ReadAll(res.Body)
+	body, err := io.ReadAll(res.Body)
 	d := time.Since(t0)
 
 	if err != ExportErrRequestCanceled {
@@ -2678,7 +2678,7 @@ func (fooProto) RoundTrip(req *Request) (*Response, error) {
 		Status:     "200 OK",
 		StatusCode: 200,
 		Header:     make(Header),
-		Body:       ioutil.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
+		Body:       io.NopCloser(strings.NewReader("You wanted " + req.URL.String())),
 	}
 	return res, nil
 }
@@ -2692,7 +2692,7 @@ func TestTransportAltProto(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	bodyb, err := ioutil.ReadAll(res.Body)
+	bodyb, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -2769,7 +2769,7 @@ func TestTransportSocketLateBinding(t *testing.T) {
 		// let the foo response finish so we can use its
 		// connection for /bar
 		fooGate <- true
-		io.Copy(ioutil.Discard, fooRes.Body)
+		io.Copy(io.Discard, fooRes.Body)
 		fooRes.Body.Close()
 	})
 
@@ -2808,7 +2808,7 @@ func TestTransportReading100Continue(t *testing.T) {
 				t.Error(err)
 				return
 			}
-			slurp, err := ioutil.ReadAll(req.Body)
+			slurp, err := io.ReadAll(req.Body)
 			if err != nil {
 				t.Errorf("Server request body slurp: %v", err)
 				return
@@ -2872,7 +2872,7 @@ Content-Length: %d
 		if id, idBack := req.Header.Get("Request-Id"), res.Header.Get("Echo-Request-Id"); id != "" && id != idBack {
 			t.Errorf("%s: response id %q != request id %q", name, idBack, id)
 		}
-		_, err = ioutil.ReadAll(res.Body)
+		_, err = io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatalf("%s: Slurp error: %v", name, err)
 		}
@@ -3151,7 +3151,7 @@ func TestIdleConnChannelLeak(t *testing.T) {
 func TestTransportClosesRequestBody(t *testing.T) {
 	defer afterTest(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		io.Copy(ioutil.Discard, r.Body)
+		io.Copy(io.Discard, r.Body)
 	}))
 	defer ts.Close()
 
@@ -3258,7 +3258,7 @@ func TestTLSServerClosesConnection(t *testing.T) {
 			t.Fatal(err)
 		}
 		<-closedc
-		slurp, err := ioutil.ReadAll(res.Body)
+		slurp, err := io.ReadAll(res.Body)
 		if err != nil {
 			t.Fatal(err)
 		}
@@ -3273,7 +3273,7 @@ func TestTLSServerClosesConnection(t *testing.T) {
 			errs = append(errs, err)
 			continue
 		}
-		slurp, err = ioutil.ReadAll(res.Body)
+		slurp, err = io.ReadAll(res.Body)
 		if err != nil {
 			errs = append(errs, err)
 			continue
@@ -3344,7 +3344,7 @@ func TestTransportNoReuseAfterEarlyResponse(t *testing.T) {
 		sconn.c = conn
 		sconn.Unlock()
 		conn.Write([]byte("HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nfoo")) // keep-alive
-		go io.Copy(ioutil.Discard, conn)
+		go io.Copy(io.Discard, conn)
 	}))
 	defer ts.Close()
 	c := ts.Client()
@@ -3593,7 +3593,7 @@ func TestTransportClosesBodyOnError(t *testing.T) {
 	defer afterTest(t)
 	readBody := make(chan error, 1)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		_, err := ioutil.ReadAll(r.Body)
+		_, err := io.ReadAll(r.Body)
 		readBody <- err
 	}))
 	defer ts.Close()
@@ -3941,7 +3941,7 @@ func TestTransportResponseCancelRace(t *testing.T) {
 	// If we do an early close, Transport just throws the connection away and
 	// doesn't reuse it. In order to trigger the bug, it has to reuse the connection
 	// so read the body
-	if _, err := io.Copy(ioutil.Discard, res.Body); err != nil {
+	if _, err := io.Copy(io.Discard, res.Body); err != nil {
 		t.Fatal(err)
 	}
 
@@ -3978,7 +3978,7 @@ func TestTransportContentEncodingCaseInsensitive(t *testing.T) {
 				t.Fatal(err)
 			}
 
-			body, err := ioutil.ReadAll(res.Body)
+			body, err := io.ReadAll(res.Body)
 			res.Body.Close()
 			if err != nil {
 				t.Fatal(err)
@@ -4085,7 +4085,7 @@ func TestTransportFlushesBodyChunks(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	io.Copy(ioutil.Discard, req.Body)
+	io.Copy(io.Discard, req.Body)
 
 	// Unblock the transport's roundTrip goroutine.
 	resBody <- strings.NewReader("HTTP/1.1 204 No Content\r\nConnection: close\r\n\r\n")
@@ -4466,7 +4466,7 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
 			// Do nothing for the second request.
 			return
 		}
-		if _, err := ioutil.ReadAll(r.Body); err != nil {
+		if _, err := io.ReadAll(r.Body); err != nil {
 			t.Error(err)
 		}
 		if !noHooks {
@@ -4554,7 +4554,7 @@ func testTransportEventTrace(t *testing.T, h2 bool, noHooks bool) {
 		t.Fatal(err)
 	}
 	logf("got roundtrip.response")
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -5236,7 +5236,7 @@ func wantBody(res *Response, err error, want string) error {
 	if err != nil {
 		return err
 	}
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if err != nil {
 		return fmt.Errorf("error reading body: %v", err)
 	}
@@ -5335,7 +5335,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
 		conn, _ := ln.Accept()
 		if conn != nil {
 			io.WriteString(conn, raw)
-			ioutil.ReadAll(conn)
+			io.ReadAll(conn)
 			conn.Close()
 		}
 	}()
@@ -5353,7 +5353,7 @@ func TestMissingStatusNoPanic(t *testing.T) {
 		t.Error("panicked, expecting an error")
 	}
 	if res != nil && res.Body != nil {
-		io.Copy(ioutil.Discard, res.Body)
+		io.Copy(io.Discard, res.Body)
 		res.Body.Close()
 	}
 
@@ -5539,7 +5539,7 @@ func TestClientTimeoutKillsConn_AfterHeaders(t *testing.T) {
 	}
 
 	close(cancel)
-	got, err := ioutil.ReadAll(res.Body)
+	got, err := io.ReadAll(res.Body)
 	if err == nil {
 		t.Fatalf("unexpected success; read %q, nil", got)
 	}
@@ -5678,7 +5678,7 @@ func TestTransportCONNECTBidi(t *testing.T) {
 }
 
 func TestTransportRequestReplayable(t *testing.T) {
-	someBody := ioutil.NopCloser(strings.NewReader(""))
+	someBody := io.NopCloser(strings.NewReader(""))
 	tests := []struct {
 		name string
 		req  *Request
@@ -5839,7 +5839,7 @@ func TestTransportRequestWriteRoundTrip(t *testing.T) {
 				t,
 				h1Mode,
 				HandlerFunc(func(w ResponseWriter, r *Request) {
-					io.Copy(ioutil.Discard, r.Body)
+					io.Copy(io.Discard, r.Body)
 					r.Body.Close()
 					w.WriteHeader(200)
 				}),
@@ -5975,7 +5975,7 @@ func TestTransportIgnores408(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	slurp, err := ioutil.ReadAll(res.Body)
+	slurp, err := io.ReadAll(res.Body)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -6237,7 +6237,7 @@ func TestTransportDecrementConnWhenIdleConnRemoved(t *testing.T) {
 			return
 		}
 		defer resp.Body.Close()
-		_, err = ioutil.ReadAll(resp.Body)
+		_, err = io.ReadAll(resp.Body)
 		if err != nil {
 			errCh <- fmt.Errorf("read body failed: %v", err)
 		}
@@ -6299,7 +6299,7 @@ func (f roundTripFunc) RoundTrip(r *Request) (*Response, error) { return f(r) }
 func TestIssue32441(t *testing.T) {
 	defer afterTest(t)
 	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
-		if n, _ := io.Copy(ioutil.Discard, r.Body); n == 0 {
+		if n, _ := io.Copy(io.Discard, r.Body); n == 0 {
 			t.Error("body length is zero")
 		}
 	}))
@@ -6307,7 +6307,7 @@ func TestIssue32441(t *testing.T) {
 	c := ts.Client()
 	c.Transport.(*Transport).RegisterProtocol("http", roundTripFunc(func(r *Request) (*Response, error) {
 		// Draining body to trigger failure condition on actual request to server.
-		if n, _ := io.Copy(ioutil.Discard, r.Body); n == 0 {
+		if n, _ := io.Copy(io.Discard, r.Body); n == 0 {
 			t.Error("body length is zero during round trip")
 		}
 		return nil, ErrSkipAltProtocol
@@ -6389,7 +6389,7 @@ func testTransportRace(req *Request) {
 		if err == nil {
 			// Ensure all the body is read; otherwise
 			// we'll get a partial dump.
-			io.Copy(ioutil.Discard, req.Body)
+			io.Copy(io.Discard, req.Body)
 			req.Body.Close()
 		}
 		select {
diff --git a/src/net/mail/example_test.go b/src/net/mail/example_test.go
index c3365642aa4..d325dc791f9 100644
--- a/src/net/mail/example_test.go
+++ b/src/net/mail/example_test.go
@@ -6,7 +6,7 @@ package mail_test
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"log"
 	"net/mail"
 	"strings"
@@ -62,7 +62,7 @@ Message body
 	fmt.Println("To:", header.Get("To"))
 	fmt.Println("Subject:", header.Get("Subject"))
 
-	body, err := ioutil.ReadAll(m.Body)
+	body, err := io.ReadAll(m.Body)
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go
index 67e3643aeb7..188d0bf7663 100644
--- a/src/net/mail/message_test.go
+++ b/src/net/mail/message_test.go
@@ -7,7 +7,6 @@ package mail
 import (
 	"bytes"
 	"io"
-	"io/ioutil"
 	"mime"
 	"reflect"
 	"strings"
@@ -53,7 +52,7 @@ func TestParsing(t *testing.T) {
 			t.Errorf("test #%d: Incorrectly parsed message header.\nGot:\n%+v\nWant:\n%+v",
 				i, msg.Header, test.header)
 		}
-		body, err := ioutil.ReadAll(msg.Body)
+		body, err := io.ReadAll(msg.Body)
 		if err != nil {
 			t.Errorf("test #%d: Failed reading body: %v", i, err)
 			continue
@@ -842,7 +841,7 @@ func TestAddressParser(t *testing.T) {
 
 	ap := AddressParser{WordDecoder: &mime.WordDecoder{
 		CharsetReader: func(charset string, input io.Reader) (io.Reader, error) {
-			in, err := ioutil.ReadAll(input)
+			in, err := io.ReadAll(input)
 			if err != nil {
 				return nil, err
 			}
diff --git a/src/net/rpc/jsonrpc/all_test.go b/src/net/rpc/jsonrpc/all_test.go
index 4e73edc70b1..667f839f580 100644
--- a/src/net/rpc/jsonrpc/all_test.go
+++ b/src/net/rpc/jsonrpc/all_test.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"net"
 	"net/rpc"
 	"reflect"
@@ -249,7 +248,7 @@ func TestMalformedInput(t *testing.T) {
 func TestMalformedOutput(t *testing.T) {
 	cli, srv := net.Pipe()
 	go srv.Write([]byte(`{"id":0,"result":null,"error":null}`))
-	go ioutil.ReadAll(srv)
+	go io.ReadAll(srv)
 
 	client := NewClient(cli)
 	defer client.Close()
@@ -271,7 +270,7 @@ func TestServerErrorHasNullResult(t *testing.T) {
 	}{
 		Reader: strings.NewReader(`{"method": "Arith.Add", "id": "123", "params": []}`),
 		Writer: &out,
-		Closer: ioutil.NopCloser(nil),
+		Closer: io.NopCloser(nil),
 	})
 	r := new(rpc.Request)
 	if err := sc.ReadRequestHeader(r); err != nil {
diff --git a/src/net/sendfile_test.go b/src/net/sendfile_test.go
index 13842a1261f..657a36599f9 100644
--- a/src/net/sendfile_test.go
+++ b/src/net/sendfile_test.go
@@ -12,7 +12,6 @@ import (
 	"encoding/hex"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"os"
 	"runtime"
 	"sync"
@@ -282,7 +281,7 @@ func TestSendfilePipe(t *testing.T) {
 			return
 		}
 		defer conn.Close()
-		io.Copy(ioutil.Discard, conn)
+		io.Copy(io.Discard, conn)
 	}()
 
 	// Wait for the byte to be copied, meaning that sendfile has
diff --git a/src/net/splice_test.go b/src/net/splice_test.go
index 0ba2f164c2e..8a0cda65644 100644
--- a/src/net/splice_test.go
+++ b/src/net/splice_test.go
@@ -8,7 +8,6 @@ package net
 
 import (
 	"io"
-	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -202,7 +201,7 @@ func testSpliceIssue25985(t *testing.T, upNet, downNet string) {
 	}
 	defer fromProxy.Close()
 
-	_, err = ioutil.ReadAll(fromProxy)
+	_, err = io.ReadAll(fromProxy)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/src/net/textproto/reader.go b/src/net/textproto/reader.go
index a00fd2395fb..5c3084f8a7c 100644
--- a/src/net/textproto/reader.go
+++ b/src/net/textproto/reader.go
@@ -9,7 +9,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strconv"
 	"strings"
 	"sync"
@@ -426,7 +425,7 @@ func (r *Reader) closeDot() {
 //
 // See the documentation for the DotReader method for details about dot-encoding.
 func (r *Reader) ReadDotBytes() ([]byte, error) {
-	return ioutil.ReadAll(r.DotReader())
+	return io.ReadAll(r.DotReader())
 }
 
 // ReadDotLines reads a dot-encoding and returns a slice
diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go
index ad14cd79ac4..205aaa430ba 100644
--- a/src/net/timeout_test.go
+++ b/src/net/timeout_test.go
@@ -11,7 +11,6 @@ import (
 	"fmt"
 	"internal/testenv"
 	"io"
-	"io/ioutil"
 	"net/internal/socktest"
 	"os"
 	"runtime"
@@ -874,7 +873,7 @@ func testVariousDeadlines(t *testing.T) {
 				if err := c.SetDeadline(t0.Add(timeout)); err != nil {
 					t.Error(err)
 				}
-				n, err := io.Copy(ioutil.Discard, c)
+				n, err := io.Copy(io.Discard, c)
 				dt := time.Since(t0)
 				c.Close()
 				ch <- result{n, err, dt}
diff --git a/src/net/writev_test.go b/src/net/writev_test.go
index a6b3285e570..d603b7f70a6 100644
--- a/src/net/writev_test.go
+++ b/src/net/writev_test.go
@@ -11,7 +11,6 @@ import (
 	"fmt"
 	"internal/poll"
 	"io"
-	"io/ioutil"
 	"reflect"
 	"runtime"
 	"sync"
@@ -28,7 +27,7 @@ func TestBuffers_read(t *testing.T) {
 		[]byte("in "),
 		[]byte("Gopherland ... "),
 	}
-	got, err := ioutil.ReadAll(&buffers)
+	got, err := io.ReadAll(&buffers)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -141,7 +140,7 @@ func testBuffer_writeTo(t *testing.T, chunks int, useCopy bool) {
 		}
 		return nil
 	}, func(c *TCPConn) error {
-		all, err := ioutil.ReadAll(c)
+		all, err := io.ReadAll(c)
 		if !bytes.Equal(all, want.Bytes()) || err != nil {
 			return fmt.Errorf("client read %q, %v; want %q, nil", all, err, want.Bytes())
 		}
diff --git a/src/os/exec/example_test.go b/src/os/exec/example_test.go
index 62866fa710f..a66890be69f 100644
--- a/src/os/exec/example_test.go
+++ b/src/os/exec/example_test.go
@@ -10,7 +10,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"os"
 	"os/exec"
@@ -128,7 +127,7 @@ func ExampleCmd_StderrPipe() {
 		log.Fatal(err)
 	}
 
-	slurp, _ := ioutil.ReadAll(stderr)
+	slurp, _ := io.ReadAll(stderr)
 	fmt.Printf("%s\n", slurp)
 
 	if err := cmd.Wait(); err != nil {
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 97467229805..cd3d759ebcc 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -637,7 +637,7 @@ func TestExtraFiles(t *testing.T) {
 	// cgo), to make sure none of that potential C code leaks fds.
 	ts := httptest.NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
 	// quiet expected TLS handshake error "remote error: bad certificate"
-	ts.Config.ErrorLog = log.New(ioutil.Discard, "", 0)
+	ts.Config.ErrorLog = log.New(io.Discard, "", 0)
 	ts.StartTLS()
 	defer ts.Close()
 	_, err = http.Get(ts.URL)
@@ -830,7 +830,7 @@ func TestHelperProcess(*testing.T) {
 			}
 		}
 	case "stdinClose":
-		b, err := ioutil.ReadAll(os.Stdin)
+		b, err := io.ReadAll(os.Stdin)
 		if err != nil {
 			fmt.Fprintf(os.Stderr, "Error: %v\n", err)
 			os.Exit(1)
diff --git a/src/os/exec/read3.go b/src/os/exec/read3.go
index 25d732a991d..8852023e77d 100644
--- a/src/os/exec/read3.go
+++ b/src/os/exec/read3.go
@@ -15,7 +15,7 @@ package main
 import (
 	"fmt"
 	"internal/poll"
-	"io/ioutil"
+	"io"
 	"os"
 	"os/exec"
 	"runtime"
@@ -24,7 +24,7 @@ import (
 
 func main() {
 	fd3 := os.NewFile(3, "fd3")
-	bs, err := ioutil.ReadAll(fd3)
+	bs, err := io.ReadAll(fd3)
 	if err != nil {
 		fmt.Printf("ReadAll from fd 3: %v\n", err)
 		os.Exit(1)
diff --git a/src/os/timeout_test.go b/src/os/timeout_test.go
index 99b94c2e4cb..d848e416424 100644
--- a/src/os/timeout_test.go
+++ b/src/os/timeout_test.go
@@ -429,7 +429,7 @@ func testVariousDeadlines(t *testing.T) {
 					if err := r.SetDeadline(t0.Add(timeout)); err != nil {
 						t.Error(err)
 					}
-					n, err := io.Copy(ioutil.Discard, r)
+					n, err := io.Copy(io.Discard, r)
 					dt := time.Since(t0)
 					r.Close()
 					actvch <- result{n, err, dt}
@@ -565,7 +565,7 @@ func TestRacyWrite(t *testing.T) {
 	var wg sync.WaitGroup
 	defer wg.Wait()
 
-	go io.Copy(ioutil.Discard, r)
+	go io.Copy(io.Discard, r)
 
 	w.SetWriteDeadline(time.Now().Add(time.Millisecond))
 	for i := 0; i < 10; i++ {
diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go
index 8ef52aba48f..fc87f374088 100644
--- a/src/runtime/crash_unix_test.go
+++ b/src/runtime/crash_unix_test.go
@@ -241,7 +241,7 @@ func TestPanicSystemstack(t *testing.T) {
 	}
 
 	// Get traceback.
-	tb, err := ioutil.ReadAll(pr)
+	tb, err := io.ReadAll(pr)
 	if err != nil {
 		t.Fatal("reading traceback from pipe: ", err)
 	}
diff --git a/src/runtime/testdata/testprogcgo/eintr.go b/src/runtime/testdata/testprogcgo/eintr.go
index 791ff1bedc0..1722a75eb9a 100644
--- a/src/runtime/testdata/testprogcgo/eintr.go
+++ b/src/runtime/testdata/testprogcgo/eintr.go
@@ -32,7 +32,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"log"
 	"net"
 	"os"
@@ -242,5 +241,5 @@ func testExec(wg *sync.WaitGroup) {
 
 // Block blocks until stdin is closed.
 func Block() {
-	io.Copy(ioutil.Discard, os.Stdin)
+	io.Copy(io.Discard, os.Stdin)
 }
diff --git a/src/strings/reader_test.go b/src/strings/reader_test.go
index a4c211d699f..5adea6f7ab2 100644
--- a/src/strings/reader_test.go
+++ b/src/strings/reader_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"sync"
 	"testing"
@@ -162,7 +161,7 @@ func TestWriteTo(t *testing.T) {
 // tests that Len is affected by reads, but Size is not.
 func TestReaderLenSize(t *testing.T) {
 	r := strings.NewReader("abc")
-	io.CopyN(ioutil.Discard, r, 1)
+	io.CopyN(io.Discard, r, 1)
 	if r.Len() != 2 {
 		t.Errorf("Len = %d; want 2", r.Len())
 	}
@@ -182,7 +181,7 @@ func TestReaderReset(t *testing.T) {
 	if err := r.UnreadRune(); err == nil {
 		t.Errorf("UnreadRune: expected error, got nil")
 	}
-	buf, err := ioutil.ReadAll(r)
+	buf, err := io.ReadAll(r)
 	if err != nil {
 		t.Errorf("ReadAll: unexpected error: %v", err)
 	}
@@ -228,7 +227,7 @@ func TestReaderZero(t *testing.T) {
 		t.Errorf("UnreadRune: got nil, want error")
 	}
 
-	if n, err := (&strings.Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
+	if n, err := (&strings.Reader{}).WriteTo(io.Discard); n != 0 || err != nil {
 		t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
 	}
 }
diff --git a/src/syscall/mkpost.go b/src/syscall/mkpost.go
index d5f5c8d6d62..ef89128310b 100644
--- a/src/syscall/mkpost.go
+++ b/src/syscall/mkpost.go
@@ -14,7 +14,7 @@ package main
 import (
 	"fmt"
 	"go/format"
-	"io/ioutil"
+	"io"
 	"log"
 	"os"
 	"regexp"
@@ -22,7 +22,7 @@ import (
 )
 
 func main() {
-	b, err := ioutil.ReadAll(os.Stdin)
+	b, err := io.ReadAll(os.Stdin)
 	if err != nil {
 		log.Fatal(err)
 	}
diff --git a/src/syscall/syscall_unix_test.go b/src/syscall/syscall_unix_test.go
index d754c075f10..1c34ed2c274 100644
--- a/src/syscall/syscall_unix_test.go
+++ b/src/syscall/syscall_unix_test.go
@@ -225,7 +225,7 @@ func TestPassFD(t *testing.T) {
 	f := os.NewFile(uintptr(gotFds[0]), "fd-from-child")
 	defer f.Close()
 
-	got, err := ioutil.ReadAll(f)
+	got, err := io.ReadAll(f)
 	want := "Hello from child process!\n"
 	if string(got) != want {
 		t.Errorf("child process ReadAll: %q, %v; want %q", got, err, want)
diff --git a/src/testing/iotest/reader.go b/src/testing/iotest/reader.go
index 33b782dcb60..770d87f26b9 100644
--- a/src/testing/iotest/reader.go
+++ b/src/testing/iotest/reader.go
@@ -10,7 +10,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"io/ioutil"
 )
 
 // OneByteReader returns a Reader that implements
@@ -142,7 +141,7 @@ func TestReader(r io.Reader, content []byte) error {
 		}
 	}
 
-	data, err := ioutil.ReadAll(&smallByteReader{r: r})
+	data, err := io.ReadAll(&smallByteReader{r: r})
 	if err != nil {
 		return err
 	}
@@ -181,7 +180,7 @@ func TestReader(r io.Reader, content []byte) error {
 		}
 
 		// Reading forward should return the last part of the file.
-		data, err := ioutil.ReadAll(&smallByteReader{r: r})
+		data, err := io.ReadAll(&smallByteReader{r: r})
 		if err != nil {
 			return fmt.Errorf("ReadAll from offset %d: %v", middle, err)
 		}
@@ -198,7 +197,7 @@ func TestReader(r io.Reader, content []byte) error {
 		}
 
 		// Reading forward should return the last part of the file (again).
-		data, err = ioutil.ReadAll(&smallByteReader{r: r})
+		data, err = io.ReadAll(&smallByteReader{r: r})
 		if err != nil {
 			return fmt.Errorf("ReadAll from offset %d: %v", middle, err)
 		}
@@ -210,7 +209,7 @@ func TestReader(r io.Reader, content []byte) error {
 		if off, err := r.Seek(int64(middle/2), 0); off != int64(middle/2) || err != nil {
 			return fmt.Errorf("Seek(%d, 0) from EOF = %d, %v, want %d, nil", middle/2, off, err, middle/2)
 		}
-		data, err = ioutil.ReadAll(r)
+		data, err = io.ReadAll(r)
 		if err != nil {
 			return fmt.Errorf("ReadAll from offset %d: %v", middle/2, err)
 		}
diff --git a/src/text/tabwriter/tabwriter_test.go b/src/text/tabwriter/tabwriter_test.go
index 6a97d4c4273..a51358dbedd 100644
--- a/src/text/tabwriter/tabwriter_test.go
+++ b/src/text/tabwriter/tabwriter_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"testing"
 	. "text/tabwriter"
 )
@@ -664,7 +663,7 @@ func BenchmarkTable(b *testing.B) {
 				b.Run("new", func(b *testing.B) {
 					b.ReportAllocs()
 					for i := 0; i < b.N; i++ {
-						w := NewWriter(ioutil.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
+						w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
 						// Write the line h times.
 						for j := 0; j < h; j++ {
 							w.Write(line)
@@ -675,7 +674,7 @@ func BenchmarkTable(b *testing.B) {
 
 				b.Run("reuse", func(b *testing.B) {
 					b.ReportAllocs()
-					w := NewWriter(ioutil.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
+					w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
 					for i := 0; i < b.N; i++ {
 						// Write the line h times.
 						for j := 0; j < h; j++ {
@@ -696,7 +695,7 @@ func BenchmarkPyramid(b *testing.B) {
 		b.Run(fmt.Sprintf("%d", x), func(b *testing.B) {
 			b.ReportAllocs()
 			for i := 0; i < b.N; i++ {
-				w := NewWriter(ioutil.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
+				w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
 				// Write increasing prefixes of that line.
 				for j := 0; j < x; j++ {
 					w.Write(line[:j*2])
@@ -718,7 +717,7 @@ func BenchmarkRagged(b *testing.B) {
 		b.Run(fmt.Sprintf("%d", h), func(b *testing.B) {
 			b.ReportAllocs()
 			for i := 0; i < b.N; i++ {
-				w := NewWriter(ioutil.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
+				w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
 				// Write the lines in turn h times.
 				for j := 0; j < h; j++ {
 					w.Write(lines[j%len(lines)])
@@ -746,7 +745,7 @@ lines
 func BenchmarkCode(b *testing.B) {
 	b.ReportAllocs()
 	for i := 0; i < b.N; i++ {
-		w := NewWriter(ioutil.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
+		w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
 		// The code is small, so it's reasonable for the tabwriter user
 		// to write it all at once, or buffer the writes.
 		w.Write([]byte(codeSnippet))
diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go
index 3309b33e3eb..1611ee054fc 100644
--- a/src/text/template/exec_test.go
+++ b/src/text/template/exec_test.go
@@ -9,7 +9,7 @@ import (
 	"errors"
 	"flag"
 	"fmt"
-	"io/ioutil"
+	"io"
 	"reflect"
 	"strings"
 	"testing"
@@ -1328,7 +1328,7 @@ func TestExecuteGivesExecError(t *testing.T) {
 	if err != nil {
 		t.Fatal(err)
 	}
-	err = tmpl.Execute(ioutil.Discard, 0)
+	err = tmpl.Execute(io.Discard, 0)
 	if err == nil {
 		t.Fatal("expected error; got none")
 	}
@@ -1474,7 +1474,7 @@ func TestEvalFieldErrors(t *testing.T) {
 	for _, tc := range tests {
 		t.Run(tc.name, func(t *testing.T) {
 			tmpl := Must(New("tmpl").Parse(tc.src))
-			err := tmpl.Execute(ioutil.Discard, tc.value)
+			err := tmpl.Execute(io.Discard, tc.value)
 			got := ""
 			if err != nil {
 				got = err.Error()
@@ -1491,7 +1491,7 @@ func TestMaxExecDepth(t *testing.T) {
 		t.Skip("skipping in -short mode")
 	}
 	tmpl := Must(New("tmpl").Parse(`{{template "tmpl" .}}`))
-	err := tmpl.Execute(ioutil.Discard, nil)
+	err := tmpl.Execute(io.Discard, nil)
 	got := ""
 	if err != nil {
 		got = err.Error()
diff --git a/src/time/genzabbrs.go b/src/time/genzabbrs.go
index 38397f91b71..1d59ba73ceb 100644
--- a/src/time/genzabbrs.go
+++ b/src/time/genzabbrs.go
@@ -17,6 +17,7 @@ import (
 	"encoding/xml"
 	"flag"
 	"go/format"
+	"io"
 	"io/ioutil"
 	"log"
 	"net/http"
@@ -71,7 +72,7 @@ func readWindowsZones() ([]*zone, error) {
 	}
 	defer r.Body.Close()
 
-	data, err := ioutil.ReadAll(r.Body)
+	data, err := io.ReadAll(r.Body)
 	if err != nil {
 		return nil, err
 	}

From e2c420591cbbd684594a111fa5cdeb40c68964a5 Mon Sep 17 00:00:00 2001
From: Jay Conrod 
Date: Mon, 19 Oct 2020 14:02:14 -0400
Subject: [PATCH 044/403] cmd/go/internal/modload: remove printStackInDie
 functionality

Previously, when running cmd/go tests, if the module root directory is
requested when modules are explicitly disabled, we printed a stack
trace in addition to the error message that's normally printed. The
stack trace isn't that useful, and it makes the actual error hard to
find.

Change-Id: I8230d668f3f16659f08d0d685124c41b4055c5b9
Reviewed-on: https://go-review.googlesource.com/c/go/+/263659
Trust: Jay Conrod 
Run-TryBot: Jay Conrod 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
---
 src/cmd/go/internal/modload/build.go  |  4 ----
 src/cmd/go/internal/modload/init.go   | 10 ----------
 src/cmd/go/internal/modload/testgo.go | 11 -----------
 3 files changed, 25 deletions(-)
 delete mode 100644 src/cmd/go/internal/modload/testgo.go

diff --git a/src/cmd/go/internal/modload/build.go b/src/cmd/go/internal/modload/build.go
index f49b52df566..b9abb0b93c1 100644
--- a/src/cmd/go/internal/modload/build.go
+++ b/src/cmd/go/internal/modload/build.go
@@ -13,7 +13,6 @@ import (
 	"internal/goroot"
 	"os"
 	"path/filepath"
-	"runtime/debug"
 	"strings"
 
 	"cmd/go/internal/base"
@@ -312,9 +311,6 @@ func mustFindModule(target, path string) module.Version {
 		return Target
 	}
 
-	if printStackInDie {
-		debug.PrintStack()
-	}
 	base.Fatalf("build %v: cannot find module for path %v", target, path)
 	panic("unreachable")
 }
diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go
index e1b784860b8..1fcc53735c4 100644
--- a/src/cmd/go/internal/modload/init.go
+++ b/src/cmd/go/internal/modload/init.go
@@ -16,7 +16,6 @@ import (
 	"os"
 	"path"
 	"path/filepath"
-	"runtime/debug"
 	"strconv"
 	"strings"
 
@@ -330,16 +329,7 @@ func ModFilePath() string {
 	return filepath.Join(modRoot, "go.mod")
 }
 
-// printStackInDie causes die to print a stack trace.
-//
-// It is enabled by the testgo tag, and helps to diagnose paths that
-// unexpectedly require a main module.
-var printStackInDie = false
-
 func die() {
-	if printStackInDie {
-		debug.PrintStack()
-	}
 	if cfg.Getenv("GO111MODULE") == "off" {
 		base.Fatalf("go: modules disabled by GO111MODULE=off; see 'go help modules'")
 	}
diff --git a/src/cmd/go/internal/modload/testgo.go b/src/cmd/go/internal/modload/testgo.go
deleted file mode 100644
index 6b34f5be393..00000000000
--- a/src/cmd/go/internal/modload/testgo.go
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2018 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.
-
-// +build testgo
-
-package modload
-
-func init() {
-	printStackInDie = true
-}

From c9c64886ef041b096d7f93c4e7d2ef5faf87ad43 Mon Sep 17 00:00:00 2001
From: Cherry Zhang 
Date: Mon, 19 Oct 2020 10:40:24 -0400
Subject: [PATCH 045/403] cmd/internal/obj: reject too large symbols

We never supported symbol larger than 2GB (issue #9862), so the
object file uses 32-bit for symbol sizes. Check and reject too
large symbol before truncating its size.

Fixes #42054.

Change-Id: I0d1d585ebdba9556f2fd3a97043bd4296d5cc9e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/263641
Trust: Cherry Zhang 
Trust: Cuong Manh Le 
Run-TryBot: Cherry Zhang 
Reviewed-by: Cuong Manh Le 
TryBot-Result: Go Bot 
---
 src/cmd/internal/obj/objfile.go      |  7 ++++++
 src/cmd/internal/obj/objfile_test.go | 36 ++++++++++++++++++++++++++++
 test/fixedbugs/issue4348.go          |  4 +++-
 3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index a08de891d31..a24a7b878f9 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -261,6 +261,10 @@ func (w *writer) StringTable() {
 	}
 }
 
+// cutoff is the maximum data section size permitted by the linker
+// (see issue #9862).
+const cutoff = int64(2e9) // 2 GB (or so; looks better in errors than 2^31)
+
 func (w *writer) Sym(s *LSym) {
 	abi := uint16(s.ABI())
 	if s.Static() {
@@ -325,6 +329,9 @@ func (w *writer) Sym(s *LSym) {
 			// don't bother setting align to 1.
 		}
 	}
+	if s.Size > cutoff {
+		w.ctxt.Diag("%s: symbol too large (%d bytes > %d bytes)", s.Name, s.Size, cutoff)
+	}
 	var o goobj.Sym
 	o.SetName(name, w.Writer)
 	o.SetABI(abi)
diff --git a/src/cmd/internal/obj/objfile_test.go b/src/cmd/internal/obj/objfile_test.go
index 155701fa4e0..146627b62b9 100644
--- a/src/cmd/internal/obj/objfile_test.go
+++ b/src/cmd/internal/obj/objfile_test.go
@@ -5,9 +5,16 @@
 package obj
 
 import (
+	"bytes"
 	"cmd/internal/goobj"
 	"cmd/internal/sys"
+	"internal/testenv"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
 	"testing"
+	"unsafe"
 )
 
 var dummyArch = LinkArch{Arch: sys.ArchAMD64}
@@ -85,3 +92,32 @@ func TestContentHash(t *testing.T) {
 		}
 	}
 }
+
+func TestSymbolTooLarge(t *testing.T) { // Issue 42054
+	testenv.MustHaveGoBuild(t)
+	if unsafe.Sizeof(uintptr(0)) < 8 {
+		t.Skip("skip on 32-bit architectures")
+	}
+
+	tmpdir, err := ioutil.TempDir("", "TestSymbolTooLarge")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(tmpdir)
+
+	src := filepath.Join(tmpdir, "p.go")
+	err = ioutil.WriteFile(src, []byte("package p; var x [1<<32]byte"), 0666)
+	if err != nil {
+		t.Fatalf("failed to write source file: %v\n", err)
+	}
+	obj := filepath.Join(tmpdir, "p.o")
+	cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", obj, src)
+	out, err := cmd.CombinedOutput()
+	if err == nil {
+		t.Fatalf("did not fail\noutput: %s", out)
+	}
+	const want = "symbol too large"
+	if !bytes.Contains(out, []byte(want)) {
+		t.Errorf("unexpected error message: want: %q, got: %s", want, out)
+	}
+}
diff --git a/test/fixedbugs/issue4348.go b/test/fixedbugs/issue4348.go
index c59b6b8caab..8b1a56c1d51 100644
--- a/test/fixedbugs/issue4348.go
+++ b/test/fixedbugs/issue4348.go
@@ -1,4 +1,4 @@
-// compile
+// skip
 
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
@@ -7,6 +7,8 @@
 // Issue 4348. After switch to 64-bit ints the compiler generates
 // illegal instructions when using large array bounds or indexes.
 
+// Skip. We reject symbols larger that 2GB (Issue #9862).
+
 package main
 
 // 1<<32 on a 64-bit machine, 1 otherwise.

From 5e9582e3f0d10523d32a25a338cbade21266dca3 Mon Sep 17 00:00:00 2001
From: Michael Matloob 
Date: Thu, 15 Oct 2020 11:45:32 -0400
Subject: [PATCH 046/403] cmd/go: support overlays for synthesized packages.

The main missing piece here was supporting Stat in the overlay
filesystem, in the parts of the package code that determines whether
an command line argument is a file on disk or a directory.  so this
change adds a Stat function to the fsys package. It's implemented the
same way as the already existing fsys.lstat function, but instead of
os.Lstat, it calls os.Stat on disk files.

Then, the change changes parts of the package code to use the overlay
Stat instead of the os package's Stat.

For #39958

Change-Id: I8e478ae386f05b48d7dd71bd7e47584f090623df
Reviewed-on: https://go-review.googlesource.com/c/go/+/262617
Trust: Michael Matloob 
Run-TryBot: Michael Matloob 
TryBot-Result: Go Bot 
Reviewed-by: Bryan C. Mills 
Reviewed-by: Jay Conrod 
---
 src/cmd/go/internal/fsys/fsys.go             |  20 ++-
 src/cmd/go/internal/fsys/fsys_test.go        | 155 ++++++++++++++++++-
 src/cmd/go/internal/load/pkg.go              |   7 +-
 src/cmd/go/testdata/script/build_overlay.txt |  21 ++-
 4 files changed, 190 insertions(+), 13 deletions(-)

diff --git a/src/cmd/go/internal/fsys/fsys.go b/src/cmd/go/internal/fsys/fsys.go
index 67359ffb6da..814e3237011 100644
--- a/src/cmd/go/internal/fsys/fsys.go
+++ b/src/cmd/go/internal/fsys/fsys.go
@@ -434,29 +434,39 @@ func Walk(root string, walkFn filepath.WalkFunc) error {
 
 // lstat implements a version of os.Lstat that operates on the overlay filesystem.
 func lstat(path string) (fs.FileInfo, error) {
+	return overlayStat(path, os.Lstat, "lstat")
+}
+
+// Stat implements a version of os.Stat that operates on the overlay filesystem.
+func Stat(path string) (fs.FileInfo, error) {
+	return overlayStat(path, os.Stat, "stat")
+}
+
+// overlayStat implements lstat or Stat (depending on whether os.Lstat or os.Stat is passed in).
+func overlayStat(path string, osStat func(string) (fs.FileInfo, error), opName string) (fs.FileInfo, error) {
 	cpath := canonicalize(path)
 
 	if _, ok := parentIsOverlayFile(filepath.Dir(cpath)); ok {
-		return nil, &fs.PathError{Op: "lstat", Path: cpath, Err: fs.ErrNotExist}
+		return nil, &fs.PathError{Op: opName, Path: cpath, Err: fs.ErrNotExist}
 	}
 
 	node, ok := overlay[cpath]
 	if !ok {
 		// The file or directory is not overlaid.
-		return os.Lstat(cpath)
+		return osStat(path)
 	}
 
 	switch {
 	case node.isDeleted():
 		return nil, &fs.PathError{Op: "lstat", Path: cpath, Err: fs.ErrNotExist}
 	case node.isDir():
-		return fakeDir(filepath.Base(cpath)), nil
+		return fakeDir(filepath.Base(path)), nil
 	default:
-		fi, err := os.Lstat(node.actualFilePath)
+		fi, err := osStat(node.actualFilePath)
 		if err != nil {
 			return nil, err
 		}
-		return fakeFile{name: filepath.Base(cpath), real: fi}, nil
+		return fakeFile{name: filepath.Base(path), real: fi}, nil
 	}
 }
 
diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go
index 28c3f08cb97..19bf2821909 100644
--- a/src/cmd/go/internal/fsys/fsys_test.go
+++ b/src/cmd/go/internal/fsys/fsys_test.go
@@ -506,7 +506,7 @@ func TestWalk(t *testing.T) {
 `,
 			".",
 			[]file{
-				{".", "root", 0, fs.ModeDir | 0700, true},
+				{".", ".", 0, fs.ModeDir | 0700, true},
 				{"file.txt", "file.txt", 0, 0600, false},
 			},
 		},
@@ -522,7 +522,7 @@ contents of other file
 `,
 			".",
 			[]file{
-				{".", "root", 0, fs.ModeDir | 0500, true},
+				{".", ".", 0, fs.ModeDir | 0500, true},
 				{"file.txt", "file.txt", 23, 0600, false},
 				{"other.txt", "other.txt", 23, 0600, false},
 			},
@@ -538,7 +538,7 @@ contents of other file
 `,
 			".",
 			[]file{
-				{".", "root", 0, fs.ModeDir | 0500, true},
+				{".", ".", 0, fs.ModeDir | 0500, true},
 				{"file.txt", "file.txt", 23, 0600, false},
 				{"other.txt", "other.txt", 23, 0600, false},
 			},
@@ -554,7 +554,7 @@ contents of other file
 `,
 			".",
 			[]file{
-				{".", "root", 0, fs.ModeDir | 0500, true},
+				{".", ".", 0, fs.ModeDir | 0500, true},
 				{"dir", "dir", 0, fs.ModeDir | 0500, true},
 				{"dir" + string(filepath.Separator) + "file.txt", "file.txt", 23, 0600, false},
 				{"other.txt", "other.txt", 23, 0600, false},
@@ -818,3 +818,150 @@ contents`,
 		})
 	}
 }
+
+func TestStat(t *testing.T) {
+	testenv.MustHaveSymlink(t)
+
+	type file struct {
+		name  string
+		size  int64
+		mode  os.FileMode // mode & (os.ModeDir|0x700): only check 'user' permissions
+		isDir bool
+	}
+
+	testCases := []struct {
+		name    string
+		overlay string
+		path    string
+
+		want    file
+		wantErr bool
+	}{
+		{
+			"regular_file",
+			`{}
+-- file.txt --
+contents`,
+			"file.txt",
+			file{"file.txt", 9, 0600, false},
+			false,
+		},
+		{
+			"new_file_in_overlay",
+			`{"Replace": {"file.txt": "dummy.txt"}}
+-- dummy.txt --
+contents`,
+			"file.txt",
+			file{"file.txt", 9, 0600, false},
+			false,
+		},
+		{
+			"file_replaced_in_overlay",
+			`{"Replace": {"file.txt": "dummy.txt"}}
+-- file.txt --
+-- dummy.txt --
+contents`,
+			"file.txt",
+			file{"file.txt", 9, 0600, false},
+			false,
+		},
+		{
+			"file_cant_exist",
+			`{"Replace": {"deleted": "dummy.txt"}}
+-- deleted/file.txt --
+-- dummy.txt --
+`,
+			"deleted/file.txt",
+			file{},
+			true,
+		},
+		{
+			"deleted",
+			`{"Replace": {"deleted": ""}}
+-- deleted --
+`,
+			"deleted",
+			file{},
+			true,
+		},
+		{
+			"dir_on_disk",
+			`{}
+-- dir/foo.txt --
+`,
+			"dir",
+			file{"dir", 0, 0700 | os.ModeDir, true},
+			false,
+		},
+		{
+			"dir_in_overlay",
+			`{"Replace": {"dir/file.txt": "dummy.txt"}}
+-- dummy.txt --
+`,
+			"dir",
+			file{"dir", 0, 0500 | os.ModeDir, true},
+			false,
+		},
+	}
+
+	for _, tc := range testCases {
+		t.Run(tc.name, func(t *testing.T) {
+			initOverlay(t, tc.overlay)
+			got, err := Stat(tc.path)
+			if tc.wantErr {
+				if err == nil {
+					t.Errorf("Stat(%q): got no error, want error", tc.path)
+				}
+				return
+			}
+			if err != nil {
+				t.Fatalf("Stat(%q): got error %v, want no error", tc.path, err)
+			}
+			if got.Name() != tc.want.name {
+				t.Errorf("Stat(%q).Name(): got %q, want %q", tc.path, got.Name(), tc.want.name)
+			}
+			if got.Mode()&(os.ModeDir|0700) != tc.want.mode {
+				t.Errorf("Stat(%q).Mode()&(os.ModeDir|0700): got %v, want %v", tc.path, got.Mode()&(os.ModeDir|0700), tc.want.mode)
+			}
+			if got.IsDir() != tc.want.isDir {
+				t.Errorf("Stat(%q).IsDir(): got %v, want %v", tc.path, got.IsDir(), tc.want.isDir)
+			}
+			if tc.want.isDir {
+				return // don't check size for directories
+			}
+			if got.Size() != tc.want.size {
+				t.Errorf("Stat(%q).Size(): got %v, want %v", tc.path, got.Size(), tc.want.size)
+			}
+		})
+	}
+}
+
+func TestStat_Symlink(t *testing.T) {
+	testenv.MustHaveSymlink(t)
+
+	initOverlay(t, `{
+	"Replace": {"file.go": "symlink"}
+}
+-- to.go --
+0123456789
+`)
+
+	// Create symlink
+	if err := os.Symlink("to.go", "symlink"); err != nil {
+		t.Error(err)
+	}
+
+	f := "file.go"
+	fi, err := Stat(f)
+	if err != nil {
+		t.Errorf("Stat(%q): got error %q, want nil error", f, err)
+	}
+
+	if !fi.Mode().IsRegular() {
+		t.Errorf("Stat(%q).Mode(): got %v, want regular mode", f, fi.Mode())
+	}
+
+	if fi.Size() != 11 {
+		t.Errorf("Stat(%q).Size(): got %v, want 11", f, fi.Size())
+	}
+}
diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go
index 913b3b94d76..2bdc08ba365 100644
--- a/src/cmd/go/internal/load/pkg.go
+++ b/src/cmd/go/internal/load/pkg.go
@@ -28,6 +28,7 @@ import (
 
 	"cmd/go/internal/base"
 	"cmd/go/internal/cfg"
+	"cmd/go/internal/fsys"
 	"cmd/go/internal/modinfo"
 	"cmd/go/internal/modload"
 	"cmd/go/internal/par"
@@ -977,7 +978,7 @@ var isDirCache par.Cache
 
 func isDir(path string) bool {
 	return isDirCache.Do(path, func() interface{} {
-		fi, err := os.Stat(path)
+		fi, err := fsys.Stat(path)
 		return err == nil && fi.IsDir()
 	}).(bool)
 }
@@ -2145,7 +2146,7 @@ func PackagesAndErrors(ctx context.Context, patterns []string) []*Package {
 		if strings.HasSuffix(p, ".go") {
 			// We need to test whether the path is an actual Go file and not a
 			// package path or pattern ending in '.go' (see golang.org/issue/34653).
-			if fi, err := os.Stat(p); err == nil && !fi.IsDir() {
+			if fi, err := fsys.Stat(p); err == nil && !fi.IsDir() {
 				return []*Package{GoFilesPackage(ctx, patterns)}
 			}
 		}
@@ -2305,7 +2306,7 @@ func GoFilesPackage(ctx context.Context, gofiles []string) *Package {
 	var dirent []fs.FileInfo
 	var dir string
 	for _, file := range gofiles {
-		fi, err := os.Stat(file)
+		fi, err := fsys.Stat(file)
 		if err != nil {
 			base.Fatalf("%s", err)
 		}
diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt
index 3c14e0b558e..0602e706e9e 100644
--- a/src/cmd/go/testdata/script/build_overlay.txt
+++ b/src/cmd/go/testdata/script/build_overlay.txt
@@ -24,6 +24,11 @@ go build -overlay overlay.json -o print_trimpath$GOEXE -trimpath ./printpath
 exec ./print_trimpath$GOEXE
 stdout ^m[/\\]printpath[/\\]main.go
 
+go build -overlay overlay.json -o print_trimpath_two_files$GOEXE printpath/main.go printpath/other.go
+exec ./print_trimpath_two_files$GOEXE
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go
+stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go
+
 # Run same tests but with gccgo.
 env GO111MODULE=off
 [!exec:gccgo] stop
@@ -65,7 +70,8 @@ the actual code is in the overlay
 		"f.go": "overlay/f.go",
 		"dir/g.go": "overlay/dir_g.go",
 		"dir2/i.go": "overlay/dir2_i.go",
-		"printpath/main.go": "overlay/printpath.go"
+		"printpath/main.go": "overlay/printpath.go",
+		"printpath/other.go": "overlay2/printpath2.go"
 	}
 }
 -- m/overlay/f.go --
@@ -101,6 +107,19 @@ func main() {
 	// paths.
 	fmt.Println(filepath.FromSlash(file))
 }
+-- m/overlay2/printpath2.go --
+package main
+
+import (
+	"fmt"
+	"path/filepath"
+	"runtime"
+)
+
+func init() {
+	_, file, _, _ := runtime.Caller(0)
+	fmt.Println(filepath.FromSlash(file))
+}
 -- m/overlay/dir2_i.go --
 package dir2
 

From 7f736694fe9b254efa7155a0a5da87c2c18e6078 Mon Sep 17 00:00:00 2001
From: Ian Lance Taylor 
Date: Tue, 20 Oct 2020 12:54:20 -0700
Subject: [PATCH 047/403] runtime: use GOTRACEBACK=system for
 TestCgoExecSignalMask

Try to get a bit more information to understand #42093.

For #42093

Change-Id: I818feb08d7561151d52eba3e88c418b55b9f9c1e
Reviewed-on: https://go-review.googlesource.com/c/go/+/264018
Trust: Ian Lance Taylor 
Run-TryBot: Ian Lance Taylor 
Reviewed-by: Bryan C. Mills 
TryBot-Result: Go Bot 
---
 src/runtime/crash_cgo_test.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index 4872189f16b..b2009840502 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -154,7 +154,7 @@ func TestCgoExecSignalMask(t *testing.T) {
 	case "windows", "plan9":
 		t.Skipf("skipping signal mask test on %s", runtime.GOOS)
 	}
-	got := runTestProg(t, "testprogcgo", "CgoExecSignalMask")
+	got := runTestProg(t, "testprogcgo", "CgoExecSignalMask", "GOTRACEBACK=system")
 	want := "OK\n"
 	if got != want {
 		t.Errorf("expected %q, got %v", want, got)

From 80182d45b5d2ff86da7b6587a2a09d8924dd0a95 Mon Sep 17 00:00:00 2001
From: Russ Cox 
Date: Sun, 18 Oct 2020 20:26:46 -0400
Subject: [PATCH 048/403] go/build: refactor per-file info & reader

Make code cleaner and a bit more adaptable:
instead of an ever-growing list of arguments and results for readImports,
put everything in a fileInfo struct, and rename function to readGoInfo.
(Not a goInfo struct because it gets used for non-Go source files as well,
but that processing is much simpler.)

The refactoring simplifies the embed work in the next CL,
but this CL makes no semantic changes.

For #41191.

Change-Id: Id2de2a3b8d351adc1c919dcf79dfbe79fc3d5301
Reviewed-on: https://go-review.googlesource.com/c/go/+/243940
Trust: Russ Cox 
Run-TryBot: Russ Cox 
TryBot-Result: Go Bot 
Reviewed-by: Jay Conrod 
---
 src/go/build/build.go     | 123 ++++++++++++++++++--------------------
 src/go/build/deps_test.go |  17 +++---
 src/go/build/read.go      |  81 ++++++++++++++++++-------
 src/go/build/read_test.go |  35 ++++++-----
 4 files changed, 145 insertions(+), 111 deletions(-)

diff --git a/src/go/build/build.go b/src/go/build/build.go
index 6141f4a90e4..4e784a6c983 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -10,7 +10,6 @@ import (
 	"fmt"
 	"go/ast"
 	"go/doc"
-	"go/parser"
 	"go/token"
 	"internal/goroot"
 	"internal/goversion"
@@ -812,12 +811,12 @@ Found:
 			p.InvalidGoFiles = append(p.InvalidGoFiles, name)
 		}
 
-		match, data, filename, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly)
+		info, err := ctxt.matchFile(p.Dir, name, allTags, &p.BinaryOnly, fset)
 		if err != nil {
 			badFile(err)
 			continue
 		}
-		if !match {
+		if info == nil {
 			if strings.HasPrefix(name, "_") || strings.HasPrefix(name, ".") {
 				// not due to build constraints - don't report
 			} else if ext == ".go" {
@@ -827,6 +826,7 @@ Found:
 			}
 			continue
 		}
+		data, filename := info.header, info.name
 
 		// Going to save the file. For non-Go files, can stop here.
 		switch ext {
@@ -843,11 +843,11 @@ Found:
 			continue
 		}
 
-		pf, err := parser.ParseFile(fset, filename, data, parser.ImportsOnly|parser.ParseComments)
-		if err != nil {
-			badFile(err)
+		if info.parseErr != nil {
+			badFile(info.parseErr)
 			continue
 		}
+		pf := info.parsed
 
 		pkg := pf.Name.Name
 		if pkg == "documentation" {
@@ -894,42 +894,17 @@ Found:
 		}
 
 		// Record imports and information about cgo.
-		type importPos struct {
-			path string
-			pos  token.Pos
-		}
-		var fileImports []importPos
 		isCgo := false
-		for _, decl := range pf.Decls {
-			d, ok := decl.(*ast.GenDecl)
-			if !ok {
-				continue
-			}
-			for _, dspec := range d.Specs {
-				spec, ok := dspec.(*ast.ImportSpec)
-				if !ok {
+		for _, imp := range info.imports {
+			if imp.path == "C" {
+				if isTest {
+					badFile(fmt.Errorf("use of cgo in test %s not supported", filename))
 					continue
 				}
-				quoted := spec.Path.Value
-				path, err := strconv.Unquote(quoted)
-				if err != nil {
-					panic(fmt.Sprintf("%s: parser returned invalid quoted string: <%s>", filename, quoted))
-				}
-				fileImports = append(fileImports, importPos{path, spec.Pos()})
-				if path == "C" {
-					if isTest {
-						badFile(fmt.Errorf("use of cgo in test %s not supported", filename))
-					} else {
-						cg := spec.Doc
-						if cg == nil && len(d.Specs) == 1 {
-							cg = d.Doc
-						}
-						if cg != nil {
-							if err := ctxt.saveCgo(filename, p, cg); err != nil {
-								badFile(err)
-							}
-						}
-						isCgo = true
+				isCgo = true
+				if imp.doc != nil {
+					if err := ctxt.saveCgo(filename, p, imp.doc); err != nil {
+						badFile(err)
 					}
 				}
 			}
@@ -959,7 +934,7 @@ Found:
 		}
 		*fileList = append(*fileList, name)
 		if importMap != nil {
-			for _, imp := range fileImports {
+			for _, imp := range info.imports {
 				importMap[imp.path] = append(importMap[imp.path], fset.Position(imp.pos))
 			}
 		}
@@ -1309,24 +1284,44 @@ func parseWord(data []byte) (word, rest []byte) {
 // MatchFile considers the name of the file and may use ctxt.OpenFile to
 // read some or all of the file's content.
 func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) {
-	match, _, _, err = ctxt.matchFile(dir, name, nil, nil)
-	return
+	info, err := ctxt.matchFile(dir, name, nil, nil, nil)
+	return info != nil, err
 }
 
 var dummyPkg Package
 
+// fileInfo records information learned about a file included in a build.
+type fileInfo struct {
+	name     string // full name including dir
+	header   []byte
+	fset     *token.FileSet
+	parsed   *ast.File
+	parseErr error
+	imports  []fileImport
+}
+
+type fileImport struct {
+	path string
+	pos  token.Pos
+	doc  *ast.CommentGroup
+}
+
 // matchFile determines whether the file with the given name in the given directory
 // should be included in the package being constructed.
-// It returns the data read from the file.
+// If the file should be included, matchFile returns a non-nil *fileInfo (and a nil error).
+// Non-nil errors are reserved for unexpected problems.
+//
 // If name denotes a Go program, matchFile reads until the end of the
-// imports (and returns that data) even though it only considers text
-// until the first non-comment.
+// imports and returns that section of the file in the fileInfo's header field,
+// even though it only considers text until the first non-comment
+// for +build lines.
+//
 // If allTags is non-nil, matchFile records any encountered build tag
 // by setting allTags[tag] = true.
-func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool) (match bool, data []byte, filename string, err error) {
+func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool, fset *token.FileSet) (*fileInfo, error) {
 	if strings.HasPrefix(name, "_") ||
 		strings.HasPrefix(name, ".") {
-		return
+		return nil, nil
 	}
 
 	i := strings.LastIndex(name, ".")
@@ -1336,55 +1331,53 @@ func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binary
 	ext := name[i:]
 
 	if !ctxt.goodOSArchFile(name, allTags) && !ctxt.UseAllFiles {
-		return
+		return nil, nil
 	}
 
 	if ext != ".go" && fileListForExt(&dummyPkg, ext) == nil {
 		// skip
-		return
+		return nil, nil
 	}
 
+	info := &fileInfo{name: ctxt.joinPath(dir, name), fset: fset}
 	if ext == ".syso" {
 		// binary, no reading
-		match = true
-		return
+		return info, nil
 	}
 
-	filename = ctxt.joinPath(dir, name)
-	f, err := ctxt.openFile(filename)
+	f, err := ctxt.openFile(info.name)
 	if err != nil {
-		return
+		return nil, err
 	}
 
-	if strings.HasSuffix(filename, ".go") {
-		data, err = readImports(f, false, nil)
-		if strings.HasSuffix(filename, "_test.go") {
+	if strings.HasSuffix(name, ".go") {
+		err = readGoInfo(f, info)
+		if strings.HasSuffix(name, "_test.go") {
 			binaryOnly = nil // ignore //go:binary-only-package comments in _test.go files
 		}
 	} else {
 		binaryOnly = nil // ignore //go:binary-only-package comments in non-Go sources
-		data, err = readComments(f)
+		info.header, err = readComments(f)
 	}
 	f.Close()
 	if err != nil {
-		err = fmt.Errorf("read %s: %v", filename, err)
-		return
+		return nil, fmt.Errorf("read %s: %v", info.name, err)
 	}
 
 	// Look for +build comments to accept or reject the file.
-	ok, sawBinaryOnly, err := ctxt.shouldBuild(data, allTags)
+	ok, sawBinaryOnly, err := ctxt.shouldBuild(info.header, allTags)
 	if err != nil {
-		return // non-nil err
+		return nil, err
 	}
 	if !ok && !ctxt.UseAllFiles {
-		return // nil err
+		return nil, nil
 	}
 
 	if binaryOnly != nil && sawBinaryOnly {
 		*binaryOnly = true
 	}
-	match = true
-	return
+
+	return info, nil
 }
 
 func cleanImports(m map[string][]token.Position) ([]string, map[string][]token.Position) {
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 16a67791cf1..4d866c87b62 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -17,7 +17,6 @@ import (
 	"path/filepath"
 	"runtime"
 	"sort"
-	"strconv"
 	"strings"
 	"testing"
 )
@@ -606,24 +605,22 @@ func findImports(pkg string) ([]string, error) {
 		if !strings.HasSuffix(name, ".go") || strings.HasSuffix(name, "_test.go") {
 			continue
 		}
-		f, err := os.Open(filepath.Join(dir, name))
+		var info fileInfo
+		info.name = filepath.Join(dir, name)
+		f, err := os.Open(info.name)
 		if err != nil {
 			return nil, err
 		}
-		var imp []string
-		data, err := readImports(f, false, &imp)
+		err = readGoInfo(f, &info)
 		f.Close()
 		if err != nil {
 			return nil, fmt.Errorf("reading %v: %v", name, err)
 		}
-		if bytes.Contains(data, buildIgnore) {
+		if bytes.Contains(info.header, buildIgnore) {
 			continue
 		}
-		for _, quoted := range imp {
-			path, err := strconv.Unquote(quoted)
-			if err != nil {
-				continue
-			}
+		for _, imp := range info.imports {
+			path := imp.path
 			if !haveImport[path] {
 				haveImport[path] = true
 				imports = append(imports, path)
diff --git a/src/go/build/read.go b/src/go/build/read.go
index 29b8cdc7867..7c81097c332 100644
--- a/src/go/build/read.go
+++ b/src/go/build/read.go
@@ -7,7 +7,11 @@ package build
 import (
 	"bufio"
 	"errors"
+	"fmt"
+	"go/ast"
+	"go/parser"
 	"io"
+	"strconv"
 	"unicode/utf8"
 )
 
@@ -147,15 +151,11 @@ func (r *importReader) readIdent() {
 
 // readString reads a quoted string literal from the input.
 // If an identifier is not present, readString records a syntax error.
-func (r *importReader) readString(save *[]string) {
+func (r *importReader) readString() {
 	switch r.nextByte(true) {
 	case '`':
-		start := len(r.buf) - 1
 		for r.err == nil {
 			if r.nextByte(false) == '`' {
-				if save != nil {
-					*save = append(*save, string(r.buf[start:]))
-				}
 				break
 			}
 			if r.eof {
@@ -163,13 +163,9 @@ func (r *importReader) readString(save *[]string) {
 			}
 		}
 	case '"':
-		start := len(r.buf) - 1
 		for r.err == nil {
 			c := r.nextByte(false)
 			if c == '"' {
-				if save != nil {
-					*save = append(*save, string(r.buf[start:]))
-				}
 				break
 			}
 			if r.eof || c == '\n' {
@@ -186,17 +182,17 @@ func (r *importReader) readString(save *[]string) {
 
 // readImport reads an import clause - optional identifier followed by quoted string -
 // from the input.
-func (r *importReader) readImport(imports *[]string) {
+func (r *importReader) readImport() {
 	c := r.peekByte(true)
 	if c == '.' {
 		r.peek = 0
 	} else if isIdent(c) {
 		r.readIdent()
 	}
-	r.readString(imports)
+	r.readString()
 }
 
-// readComments is like ioutil.ReadAll, except that it only reads the leading
+// readComments is like io.ReadAll, except that it only reads the leading
 // block of comments in the file.
 func readComments(f io.Reader) ([]byte, error) {
 	r := &importReader{b: bufio.NewReader(f)}
@@ -208,9 +204,14 @@ func readComments(f io.Reader) ([]byte, error) {
 	return r.buf, r.err
 }
 
-// readImports is like ioutil.ReadAll, except that it expects a Go file as input
-// and stops reading the input once the imports have completed.
-func readImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
+// readGoInfo expects a Go file as input and reads the file up to and including the import section.
+// It records what it learned in *info.
+// If info.fset is non-nil, readGoInfo parses the file and sets info.parsed, info.parseErr,
+// and info.imports.
+//
+// It only returns an error if there are problems reading the file,
+// not for syntax errors in the file itself.
+func readGoInfo(f io.Reader, info *fileInfo) error {
 	r := &importReader{b: bufio.NewReader(f)}
 
 	r.readKeyword("package")
@@ -220,28 +221,68 @@ func readImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte
 		if r.peekByte(true) == '(' {
 			r.nextByte(false)
 			for r.peekByte(true) != ')' && r.err == nil {
-				r.readImport(imports)
+				r.readImport()
 			}
 			r.nextByte(false)
 		} else {
-			r.readImport(imports)
+			r.readImport()
 		}
 	}
 
+	info.header = r.buf
+
 	// If we stopped successfully before EOF, we read a byte that told us we were done.
 	// Return all but that last byte, which would cause a syntax error if we let it through.
 	if r.err == nil && !r.eof {
-		return r.buf[:len(r.buf)-1], nil
+		info.header = r.buf[:len(r.buf)-1]
 	}
 
 	// If we stopped for a syntax error, consume the whole file so that
 	// we are sure we don't change the errors that go/parser returns.
-	if r.err == errSyntax && !reportSyntaxError {
+	if r.err == errSyntax {
 		r.err = nil
 		for r.err == nil && !r.eof {
 			r.readByte()
 		}
+		info.header = r.buf
+	}
+	if r.err != nil {
+		return r.err
 	}
 
-	return r.buf, r.err
+	if info.fset == nil {
+		return nil
+	}
+
+	// Parse file header & record imports.
+	info.parsed, info.parseErr = parser.ParseFile(info.fset, info.name, info.header, parser.ImportsOnly|parser.ParseComments)
+	if info.parseErr != nil {
+		return nil
+	}
+
+	for _, decl := range info.parsed.Decls {
+		d, ok := decl.(*ast.GenDecl)
+		if !ok {
+			continue
+		}
+		for _, dspec := range d.Specs {
+			spec, ok := dspec.(*ast.ImportSpec)
+			if !ok {
+				continue
+			}
+			quoted := spec.Path.Value
+			path, err := strconv.Unquote(quoted)
+			if err != nil {
+				return fmt.Errorf("parser returned invalid quoted string: <%s>", quoted)
+			}
+
+			doc := spec.Doc
+			if doc == nil && len(d.Specs) == 1 {
+				doc = d.Doc
+			}
+			info.imports = append(info.imports, fileImport{path, spec.Pos(), doc})
+		}
+	}
+
+	return nil
 }
diff --git a/src/go/build/read_test.go b/src/go/build/read_test.go
index 8636533f697..b0898912e98 100644
--- a/src/go/build/read_test.go
+++ b/src/go/build/read_test.go
@@ -13,12 +13,12 @@ import (
 const quote = "`"
 
 type readTest struct {
-	// Test input contains ℙ where readImports should stop.
+	// Test input contains ℙ where readGoInfo should stop.
 	in  string
 	err string
 }
 
-var readImportsTests = []readTest{
+var readGoInfoTests = []readTest{
 	{
 		`package p`,
 		"",
@@ -37,15 +37,15 @@ var readImportsTests = []readTest{
 	},
 	{
 		`package p
-		
+
 		// comment
-		
+
 		import "x"
 		import _ "x"
 		import a "x"
-		
+
 		/* comment */
-		
+
 		import (
 			"x" /* comment */
 			_ "x"
@@ -59,7 +59,7 @@ var readImportsTests = []readTest{
 		import ()
 		import()import()import()
 		import();import();import()
-		
+
 		ℙvar x = 1
 		`,
 		"",
@@ -85,7 +85,7 @@ var readCommentsTests = []readTest{
 		/* bar */
 
 		/* quux */ // baz
-		
+
 		/*/ zot */
 
 		// asdf
@@ -127,8 +127,12 @@ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, erro
 	}
 }
 
-func TestReadImports(t *testing.T) {
-	testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
+func TestReadGoInfo(t *testing.T) {
+	testRead(t, readGoInfoTests, func(r io.Reader) ([]byte, error) {
+		var info fileInfo
+		err := readGoInfo(r, &info)
+		return info.header, err
+	})
 }
 
 func TestReadComments(t *testing.T) {
@@ -202,11 +206,6 @@ var readFailuresTests = []readTest{
 	},
 }
 
-func TestReadFailures(t *testing.T) {
-	// Errors should be reported (true arg to readImports).
-	testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return readImports(r, true, nil) })
-}
-
 func TestReadFailuresIgnored(t *testing.T) {
 	// Syntax errors should not be reported (false arg to readImports).
 	// Instead, entire file should be the output and no error.
@@ -219,5 +218,9 @@ func TestReadFailuresIgnored(t *testing.T) {
 			tt.err = ""
 		}
 	}
-	testRead(t, tests, func(r io.Reader) ([]byte, error) { return readImports(r, false, nil) })
+	testRead(t, tests, func(r io.Reader) ([]byte, error) {
+		var info fileInfo
+		err := readGoInfo(r, &info)
+		return info.header, err
+	})
 }

From b7a2d413a3f710f14accedf185c93bfb63d24fd0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= 
Date: Tue, 20 Oct 2020 09:56:14 +0200
Subject: [PATCH 049/403] testing: print cpu type as label for benchmarks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Supports 386 and amd64 architectures on all operating systems.

Example output:
$ go test -bench=.*
goos: darwin
goarch: amd64
pkg: strconv
cpu: Intel(R) Core(TM) i7-3520M CPU @ 2.90GHz
BenchmarkAtof64Decimal-4        	24431032	        46.8 ns/op
...

As the displayed CPU information is only used for information
purposes it is lazily initialized when needed using the new
internal/sysinfo package.

This allows internal/cpu to stay without dependencies and avoid
initialization costs when the CPU information is not needed as
the new code to query the CPU name in internal/cpu can be
dead code eliminated if not used.

Fixes #39214

Change-Id: I77ae5c5d2fed6b28fa78dd45075f9f0a6a7f1bfd
Reviewed-on: https://go-review.googlesource.com/c/go/+/263804
Trust: Martin Möhrmann 
Reviewed-by: Keith Randall 
---
 src/go/build/deps_test.go       |  6 +++-
 src/internal/cpu/cpu_no_name.go | 19 +++++++++++++
 src/internal/cpu/cpu_x86.go     | 49 +++++++++++++++++++++++++++++++++
 src/internal/sysinfo/sysinfo.go | 31 +++++++++++++++++++++
 src/testing/benchmark.go        |  7 +++++
 5 files changed, 111 insertions(+), 1 deletion(-)
 create mode 100644 src/internal/cpu/cpu_no_name.go
 create mode 100644 src/internal/sysinfo/sysinfo.go

diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index 4d866c87b62..ba7a76318fc 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -467,6 +467,10 @@ var depsRules = `
 	< net/rpc
 	< net/rpc/jsonrpc;
 
+	# System Information
+	internal/cpu, sync
+	< internal/sysinfo;
+
 	# Test-only
 	log
 	< testing/iotest
@@ -475,7 +479,7 @@ var depsRules = `
 	FMT, flag, math/rand
 	< testing/quick;
 
-	FMT, flag, runtime/debug, runtime/trace
+	FMT, flag, runtime/debug, runtime/trace, internal/sysinfo
 	< testing;
 
 	internal/testlog, runtime/pprof, regexp
diff --git a/src/internal/cpu/cpu_no_name.go b/src/internal/cpu/cpu_no_name.go
new file mode 100644
index 00000000000..ce1c37a3c7c
--- /dev/null
+++ b/src/internal/cpu/cpu_no_name.go
@@ -0,0 +1,19 @@
+// Copyright 2020 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.
+
+// +build !386
+// +build !amd64
+
+package cpu
+
+// Name returns the CPU name given by the vendor
+// if it can be read directly from memory or by CPU instructions.
+// If the CPU name can not be determined an empty string is returned.
+//
+// Implementations that use the Operating System (e.g. sysctl or /sys/)
+// to gather CPU information for display should be placed in internal/sysinfo.
+func Name() string {
+	// "A CPU has no name".
+	return ""
+}
diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go
index da6cf672581..fb414adaf84 100644
--- a/src/internal/cpu/cpu_x86.go
+++ b/src/internal/cpu/cpu_x86.go
@@ -38,6 +38,8 @@ const (
 	cpuid_ADX  = 1 << 19
 )
 
+var maxExtendedFunctionInformation uint32
+
 func doinit() {
 	options = []option{
 		{Name: "adx", Feature: &X86.HasADX},
@@ -65,6 +67,8 @@ func doinit() {
 		return
 	}
 
+	maxExtendedFunctionInformation, _, _, _ = cpuid(0x80000000, 0)
+
 	_, _, ecx1, edx1 := cpuid(1, 0)
 	X86.HasSSE2 = isSet(edx1, cpuid_SSE2)
 
@@ -103,3 +107,48 @@ func doinit() {
 func isSet(hwc uint32, value uint32) bool {
 	return hwc&value != 0
 }
+
+// Name returns the CPU name given by the vendor.
+// If the CPU name can not be determined an
+// empty string is returned.
+func Name() string {
+	if maxExtendedFunctionInformation < 0x80000004 {
+		return ""
+	}
+
+	data := make([]byte, 0, 3*4*4)
+
+	var eax, ebx, ecx, edx uint32
+	eax, ebx, ecx, edx = cpuid(0x80000002, 0)
+	data = appendBytes(data, eax, ebx, ecx, edx)
+	eax, ebx, ecx, edx = cpuid(0x80000003, 0)
+	data = appendBytes(data, eax, ebx, ecx, edx)
+	eax, ebx, ecx, edx = cpuid(0x80000004, 0)
+	data = appendBytes(data, eax, ebx, ecx, edx)
+
+	// Trim leading spaces.
+	for len(data) > 0 && data[0] == ' ' {
+		data = data[1:]
+	}
+
+	// Trim tail after and including the first null byte.
+	for i, c := range data {
+		if c == '\x00' {
+			data = data[:i]
+			break
+		}
+	}
+
+	return string(data)
+}
+
+func appendBytes(b []byte, args ...uint32) []byte {
+	for _, arg := range args {
+		b = append(b,
+			byte((arg >> 0)),
+			byte((arg >> 8)),
+			byte((arg >> 16)),
+			byte((arg >> 24)))
+	}
+	return b
+}
diff --git a/src/internal/sysinfo/sysinfo.go b/src/internal/sysinfo/sysinfo.go
new file mode 100644
index 00000000000..961be7abaee
--- /dev/null
+++ b/src/internal/sysinfo/sysinfo.go
@@ -0,0 +1,31 @@
+// Copyright 2020 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 sysinfo implements high level hardware information gathering
+// that can be used for debugging or information purposes.
+package sysinfo
+
+import (
+	internalcpu "internal/cpu"
+	"sync"
+)
+
+type cpuInfo struct {
+	once sync.Once
+	name string
+}
+
+var CPU cpuInfo
+
+func (cpu *cpuInfo) Name() string {
+	cpu.once.Do(func() {
+		// Try to get the information from internal/cpu.
+		if name := internalcpu.Name(); name != "" {
+			cpu.name = name
+			return
+		}
+		// TODO(martisch): use /proc/cpuinfo and /sys/devices/system/cpu/ on Linux as fallback.
+	})
+	return cpu.name
+}
diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go
index e9687bf26de..1b81ec3a2d6 100644
--- a/src/testing/benchmark.go
+++ b/src/testing/benchmark.go
@@ -8,6 +8,7 @@ import (
 	"flag"
 	"fmt"
 	"internal/race"
+	"internal/sysinfo"
 	"io"
 	"math"
 	"os"
@@ -262,6 +263,9 @@ func (b *B) run() {
 		if b.importPath != "" {
 			fmt.Fprintf(b.w, "pkg: %s\n", b.importPath)
 		}
+		if cpu := sysinfo.CPU.Name(); cpu != "" {
+			fmt.Fprintf(b.w, "cpu: %s\n", cpu)
+		}
 	})
 	if b.context != nil {
 		// Running go test --test.bench
@@ -648,6 +652,9 @@ func (b *B) Run(name string, f func(b *B)) bool {
 			if b.importPath != "" {
 				fmt.Printf("pkg: %s\n", b.importPath)
 			}
+			if cpu := sysinfo.CPU.Name(); cpu != "" {
+				fmt.Printf("cpu: %s\n", cpu)
+			}
 		})
 
 		fmt.Println(benchName)

From 3ca3ca51d70aac890fb023786db1fcbbeea139f1 Mon Sep 17 00:00:00 2001
From: Constantin Konstantinidis 
Date: Thu, 24 Sep 2020 21:44:32 +0200
Subject: [PATCH 050/403] cmd/compile: enforce strongly typed rules for ARM
 (to32)

Type casting changed to 32 from 64.
L1055-L1056
L1193-L1194, L1197-L1198

toolstash-check successful.

Change-Id: Icdb9985673292294bc4549afaaa6cf4fcf92ffa8
Reviewed-on: https://go-review.googlesource.com/c/go/+/257640
Trust: Josh Bleecher Snyder 
Reviewed-by: Keith Randall 
---
 src/cmd/compile/internal/ssa/gen/ARM.rules | 12 +++---
 src/cmd/compile/internal/ssa/rewriteARM.go | 48 +++++++++++-----------
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules
index aad7236d598..cfedde5d5e8 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM.rules
@@ -1052,8 +1052,8 @@
 (BICshiftRL x (MOVWconst [c]) [d]) => (BICconst x [int32(uint32(c)>>uint64(d))])
 (BICshiftRA x (MOVWconst [c]) [d]) => (BICconst x [c>>uint64(d)])
 (MVNshiftLL (MOVWconst [c]) [d]) => (MOVWconst [^(c< (MOVWconst [^int64(uint32(c)>>uint64(d))])
-(MVNshiftRA (MOVWconst [c]) [d]) -> (MOVWconst [^int64(int32(c)>>uint64(d))])
+(MVNshiftRL (MOVWconst [c]) [d]) => (MOVWconst [^int32(uint32(c)>>uint64(d))])
+(MVNshiftRA (MOVWconst [c]) [d]) => (MOVWconst [int32(c)>>uint64(d)])
 (CMPshiftLL x (MOVWconst [c]) [d]) => (CMPconst x [c< (CMPconst x [int32(uint32(c)>>uint64(d))])
 (CMPshiftRA x (MOVWconst [c]) [d]) => (CMPconst x [c>>uint64(d)])
@@ -1190,12 +1190,12 @@
 (MOVWstoreidx ptr (SRAconst idx [c]) val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
 (MOVWstoreidx (SRAconst idx [c]) ptr val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
 
-(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)< (MOVWload [int64(uint32(c)>>uint64(d))] ptr mem)
+(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) => (MOVWload [int32(uint32(c)< (MOVWload [int32(uint32(c)>>uint64(d))] ptr mem)
 (MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem) => (MOVWload [c>>uint64(d)] ptr mem)
 
-(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)< (MOVWstore [int64(uint32(c)>>uint64(d))] ptr val mem)
+(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [int32(uint32(c)< (MOVWstore [int32(uint32(c)>>uint64(d))] ptr val mem)
 (MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [c>>uint64(d)] ptr val mem)
 
 // generic simplifications
diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go
index 435da688b77..eff01927dfc 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM.go
@@ -6412,17 +6412,17 @@ func rewriteValueARM_OpARMMOVWloadshiftLL(v *Value) bool {
 		return true
 	}
 	// match: (MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem)
-	// result: (MOVWload [int64(uint32(c)<>uint64(d))] ptr mem)
+	// result: (MOVWload [int32(uint32(c)>>uint64(d))] ptr mem)
 	for {
-		d := v.AuxInt
+		d := auxIntToInt32(v.AuxInt)
 		ptr := v_0
 		if v_1.Op != OpARMMOVWconst {
 			break
 		}
-		c := v_1.AuxInt
+		c := auxIntToInt32(v_1.AuxInt)
 		mem := v_2
 		v.reset(OpARMMOVWload)
-		v.AuxInt = int64(uint32(c) >> uint64(d))
+		v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
 		v.AddArg2(ptr, mem)
 		return true
 	}
@@ -6833,18 +6833,18 @@ func rewriteValueARM_OpARMMOVWstoreshiftLL(v *Value) bool {
 	v_1 := v.Args[1]
 	v_0 := v.Args[0]
 	// match: (MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem)
-	// result: (MOVWstore [int64(uint32(c)<>uint64(d))] ptr val mem)
+	// result: (MOVWstore [int32(uint32(c)>>uint64(d))] ptr val mem)
 	for {
-		d := v.AuxInt
+		d := auxIntToInt32(v.AuxInt)
 		ptr := v_0
 		if v_1.Op != OpARMMOVWconst {
 			break
 		}
-		c := v_1.AuxInt
+		c := auxIntToInt32(v_1.AuxInt)
 		val := v_2
 		mem := v_3
 		v.reset(OpARMMOVWstore)
-		v.AuxInt = int64(uint32(c) >> uint64(d))
+		v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
 		v.AddArg3(ptr, val, mem)
 		return true
 	}
@@ -8105,15 +8105,15 @@ func rewriteValueARM_OpARMMVNshiftLLreg(v *Value) bool {
 func rewriteValueARM_OpARMMVNshiftRA(v *Value) bool {
 	v_0 := v.Args[0]
 	// match: (MVNshiftRA (MOVWconst [c]) [d])
-	// result: (MOVWconst [^int64(int32(c)>>uint64(d))])
+	// result: (MOVWconst [int32(c)>>uint64(d)])
 	for {
-		d := v.AuxInt
+		d := auxIntToInt32(v.AuxInt)
 		if v_0.Op != OpARMMOVWconst {
 			break
 		}
-		c := v_0.AuxInt
+		c := auxIntToInt32(v_0.AuxInt)
 		v.reset(OpARMMOVWconst)
-		v.AuxInt = ^int64(int32(c) >> uint64(d))
+		v.AuxInt = int32ToAuxInt(int32(c) >> uint64(d))
 		return true
 	}
 	return false
@@ -8139,15 +8139,15 @@ func rewriteValueARM_OpARMMVNshiftRAreg(v *Value) bool {
 func rewriteValueARM_OpARMMVNshiftRL(v *Value) bool {
 	v_0 := v.Args[0]
 	// match: (MVNshiftRL (MOVWconst [c]) [d])
-	// result: (MOVWconst [^int64(uint32(c)>>uint64(d))])
+	// result: (MOVWconst [^int32(uint32(c)>>uint64(d))])
 	for {
-		d := v.AuxInt
+		d := auxIntToInt32(v.AuxInt)
 		if v_0.Op != OpARMMOVWconst {
 			break
 		}
-		c := v_0.AuxInt
+		c := auxIntToInt32(v_0.AuxInt)
 		v.reset(OpARMMOVWconst)
-		v.AuxInt = ^int64(uint32(c) >> uint64(d))
+		v.AuxInt = int32ToAuxInt(^int32(uint32(c) >> uint64(d)))
 		return true
 	}
 	return false

From f121e0eddd64aa0084b916e94c9a540edf859539 Mon Sep 17 00:00:00 2001
From: Dan Scales 
Date: Tue, 20 Oct 2020 15:03:33 -0700
Subject: [PATCH 051/403] cmd/compile: fix nodedump output for types of nodes

The Dbg dumping of complex types was broken, because (I think) of a
recent change to handle recursive types correctly. Before this fix,
the Dump output of a closure node (where the last thing on the line is
the type of the node) was:

.   .   CLOSURE l(8) esc(h) tc(1) FUNC-@0

after this change it is:

.   .   CLOSURE l(8) esc(h) tc(1) FUNC-func(int) int

The problem is that that the 'mode == Fdbg' code was immediately
aborting the descent into tconv2, since it was calling down with the
same node that was just entered into the hash table.

Change-Id: Iee106b967cea1856dd92d4350681401dd34a23b3
Reviewed-on: https://go-review.googlesource.com/c/go/+/264025
Trust: Dan Scales 
Reviewed-by: Keith Randall 
---
 src/cmd/compile/internal/gc/fmt.go | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index 9ba1789633c..d7ed1d2ff09 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -792,6 +792,13 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited
 		return
 	}
 
+	if mode == FDbg {
+		b.WriteString(t.Etype.String())
+		b.WriteByte('-')
+		tconv2(b, t, flag, FErr, visited)
+		return
+	}
+
 	// At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
 	// try to print it recursively.
 	// We record the offset in the result buffer where the type's text starts. This offset serves as a reference
@@ -805,12 +812,6 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited
 	visited[t] = b.Len()
 	defer delete(visited, t)
 
-	if mode == FDbg {
-		b.WriteString(t.Etype.String())
-		b.WriteByte('-')
-		tconv2(b, t, flag, FErr, visited)
-		return
-	}
 	switch t.Etype {
 	case TPTR:
 		b.WriteByte('*')

From cfb087c68324e0af4217ffe75a962ca8383d12c5 Mon Sep 17 00:00:00 2001
From: Jay Conrod 
Date: Tue, 20 Oct 2020 18:18:21 -0400
Subject: [PATCH 052/403] cmd/go: fix TestScript/test_cache_inputs

Small fix for a new failure in CL 263142

For #41190

Change-Id: I733bc1998d87b505b52d429916c45afe2968a709
Reviewed-on: https://go-review.googlesource.com/c/go/+/264057
Run-TryBot: Jay Conrod 
TryBot-Result: Go Bot 
Trust: Jay Conrod 
Reviewed-by: Bryan C. Mills 
---
 src/cmd/go/testdata/script/test_cache_inputs.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/cmd/go/testdata/script/test_cache_inputs.txt b/src/cmd/go/testdata/script/test_cache_inputs.txt
index 97ae4af51f0..50486e19090 100644
--- a/src/cmd/go/testdata/script/test_cache_inputs.txt
+++ b/src/cmd/go/testdata/script/test_cache_inputs.txt
@@ -137,7 +137,7 @@ exit 0
 package testcache
 
 import (
-	"io/ioutil"
+	"io"
 	"os"
 	"testing"
 )

From 62f18d07ba8a7ee8e480cb723fb9b969ca17f822 Mon Sep 17 00:00:00 2001
From: Cuong Manh Le 
Date: Tue, 20 Oct 2020 09:51:23 +0700
Subject: [PATCH 053/403] doc/go1.16: document net TCP listener's backlog size
 update

Updates #41470

Change-Id: Iebd3a339504aa7f8834853d6a740557fb3bce3ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/262938
Trust: Cuong Manh Le 
Trust: Emmanuel Odeke 
Run-TryBot: Cuong Manh Le 
TryBot-Result: Go Bot 
Reviewed-by: Ian Lance Taylor 
Reviewed-by: Emmanuel Odeke 
---
 doc/go1.16.html | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/doc/go1.16.html b/doc/go1.16.html
index 43bcc779e5f..2f2e395729e 100644
--- a/doc/go1.16.html
+++ b/doc/go1.16.html
@@ -228,6 +228,12 @@ Do not send CLs removing the interior tags from such phrases.
   with "use of closed network connection".
 

+

+ In previous Go releases the default TCP listener backlog size on Linux systems, + set by /proc/sys/net/core/somaxconn, was limited to a maximum of 65535. + On Linux kernel version 4.1 and above, the maximum is now 4294967295. +

+

reflect

From 491fe1b959bf6a0657cba2e3db831ffd4bdf7674 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Tue, 20 Oct 2020 10:44:07 +0200 Subject: [PATCH 054/403] cmd/go: enable link syso test on linux/riscv64 Now that external linking is supported on linux/riscv64 (CL 243517), re-enable the test previously disabled by CL 216259. Updates #36739 Change-Id: I611548c587ca50f8bfab72c903ab0432e2b54198 Reviewed-on: https://go-review.googlesource.com/c/go/+/263797 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Joel Sing --- src/cmd/go/testdata/script/link_syso_issue33139.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/cmd/go/testdata/script/link_syso_issue33139.txt b/src/cmd/go/testdata/script/link_syso_issue33139.txt index d4f0b87537c..26034c96266 100644 --- a/src/cmd/go/testdata/script/link_syso_issue33139.txt +++ b/src/cmd/go/testdata/script/link_syso_issue33139.txt @@ -8,10 +8,6 @@ # See: https://github.com/golang/go/issues/8912 [linux] [ppc64] skip -# External linking is not supported on linux/riscv64. -# See: https://github.com/golang/go/issues/36739 -[linux] [riscv64] skip - cc -c -o syso/objTestImpl.syso syso/src/objTestImpl.c go build -ldflags='-linkmode=external' ./cmd/main.go From 9848e93cb76f068b97e8ea342c33cc09b553790f Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Sun, 11 Oct 2020 13:33:53 +0200 Subject: [PATCH 055/403] misc/wasm: make sure sp is unsigned An i32 passed from WebAssembly to JavaScript is always read as a signed integer. Use the bitshift operator to turn it into an unsigned integer. Fixes #40923 Change-Id: Ia91ed2145dd2fc3071e2fc22b86ebfcb3c1e9f4f Reviewed-on: https://go-review.googlesource.com/c/go/+/261358 Trust: Richard Musiol Run-TryBot: Richard Musiol TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- misc/wasm/wasm_exec.js | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index ef97c4e311d..06b6062a2e0 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -255,6 +255,7 @@ // func wasmExit(code int32) "runtime.wasmExit": (sp) => { + sp >>>= 0; const code = this.mem.getInt32(sp + 8, true); this.exited = true; delete this._inst; @@ -267,6 +268,7 @@ // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) "runtime.wasmWrite": (sp) => { + sp >>>= 0; const fd = getInt64(sp + 8); const p = getInt64(sp + 16); const n = this.mem.getInt32(sp + 24, true); @@ -275,16 +277,19 @@ // func resetMemoryDataView() "runtime.resetMemoryDataView": (sp) => { + sp >>>= 0; this.mem = new DataView(this._inst.exports.mem.buffer); }, // func nanotime1() int64 "runtime.nanotime1": (sp) => { + sp >>>= 0; setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); }, // func walltime1() (sec int64, nsec int32) "runtime.walltime1": (sp) => { + sp >>>= 0; const msec = (new Date).getTime(); setInt64(sp + 8, msec / 1000); this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); @@ -292,6 +297,7 @@ // func scheduleTimeoutEvent(delay int64) int32 "runtime.scheduleTimeoutEvent": (sp) => { + sp >>>= 0; const id = this._nextCallbackTimeoutID; this._nextCallbackTimeoutID++; this._scheduledTimeouts.set(id, setTimeout( @@ -311,6 +317,7 @@ // func clearTimeoutEvent(id int32) "runtime.clearTimeoutEvent": (sp) => { + sp >>>= 0; const id = this.mem.getInt32(sp + 8, true); clearTimeout(this._scheduledTimeouts.get(id)); this._scheduledTimeouts.delete(id); @@ -318,11 +325,13 @@ // func getRandomData(r []byte) "runtime.getRandomData": (sp) => { + sp >>>= 0; crypto.getRandomValues(loadSlice(sp + 8)); }, // func finalizeRef(v ref) "syscall/js.finalizeRef": (sp) => { + sp >>>= 0; const id = this.mem.getUint32(sp + 8, true); this._goRefCounts[id]--; if (this._goRefCounts[id] === 0) { @@ -335,44 +344,51 @@ // func stringVal(value string) ref "syscall/js.stringVal": (sp) => { + sp >>>= 0; storeValue(sp + 24, loadString(sp + 8)); }, // func valueGet(v ref, p string) ref "syscall/js.valueGet": (sp) => { + sp >>>= 0; const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); - sp = this._inst.exports.getsp(); // see comment above + sp = this._inst.exports.getsp() >>> 0; // see comment above storeValue(sp + 32, result); }, // func valueSet(v ref, p string, x ref) "syscall/js.valueSet": (sp) => { + sp >>>= 0; Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); }, // func valueDelete(v ref, p string) "syscall/js.valueDelete": (sp) => { + sp >>>= 0; Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); }, // func valueIndex(v ref, i int) ref "syscall/js.valueIndex": (sp) => { + sp >>>= 0; storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); }, // valueSetIndex(v ref, i int, x ref) "syscall/js.valueSetIndex": (sp) => { + sp >>>= 0; Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); }, // func valueCall(v ref, m string, args []ref) (ref, bool) "syscall/js.valueCall": (sp) => { + sp >>>= 0; try { const v = loadValue(sp + 8); const m = Reflect.get(v, loadString(sp + 16)); const args = loadSliceOfValues(sp + 32); const result = Reflect.apply(m, v, args); - sp = this._inst.exports.getsp(); // see comment above + sp = this._inst.exports.getsp() >>> 0; // see comment above storeValue(sp + 56, result); this.mem.setUint8(sp + 64, 1); } catch (err) { @@ -383,11 +399,12 @@ // func valueInvoke(v ref, args []ref) (ref, bool) "syscall/js.valueInvoke": (sp) => { + sp >>>= 0; try { const v = loadValue(sp + 8); const args = loadSliceOfValues(sp + 16); const result = Reflect.apply(v, undefined, args); - sp = this._inst.exports.getsp(); // see comment above + sp = this._inst.exports.getsp() >>> 0; // see comment above storeValue(sp + 40, result); this.mem.setUint8(sp + 48, 1); } catch (err) { @@ -398,11 +415,12 @@ // func valueNew(v ref, args []ref) (ref, bool) "syscall/js.valueNew": (sp) => { + sp >>>= 0; try { const v = loadValue(sp + 8); const args = loadSliceOfValues(sp + 16); const result = Reflect.construct(v, args); - sp = this._inst.exports.getsp(); // see comment above + sp = this._inst.exports.getsp() >>> 0; // see comment above storeValue(sp + 40, result); this.mem.setUint8(sp + 48, 1); } catch (err) { @@ -413,11 +431,13 @@ // func valueLength(v ref) int "syscall/js.valueLength": (sp) => { + sp >>>= 0; setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); }, // valuePrepareString(v ref) (ref, int) "syscall/js.valuePrepareString": (sp) => { + sp >>>= 0; const str = encoder.encode(String(loadValue(sp + 8))); storeValue(sp + 16, str); setInt64(sp + 24, str.length); @@ -425,17 +445,20 @@ // valueLoadString(v ref, b []byte) "syscall/js.valueLoadString": (sp) => { + sp >>>= 0; const str = loadValue(sp + 8); loadSlice(sp + 16).set(str); }, // func valueInstanceOf(v ref, t ref) bool "syscall/js.valueInstanceOf": (sp) => { + sp >>>= 0; this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0); }, // func copyBytesToGo(dst []byte, src ref) (int, bool) "syscall/js.copyBytesToGo": (sp) => { + sp >>>= 0; const dst = loadSlice(sp + 8); const src = loadValue(sp + 32); if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { @@ -450,6 +473,7 @@ // func copyBytesToJS(dst ref, src []byte) (int, bool) "syscall/js.copyBytesToJS": (sp) => { + sp >>>= 0; const dst = loadValue(sp + 8); const src = loadSlice(sp + 16); if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { From 54c0237346adfc2cac7bbebba80d652227ab6ea5 Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Sun, 11 Oct 2020 10:23:45 +0200 Subject: [PATCH 056/403] misc/wasm: improve error message if javascript polyfills are required wasm_exec.js expects that either "require" is available or that the globals "crypto", "TextEncoder" and "TextDecoder" are already defined. Report a better error message if this is not the case, suggesting the use of a polyfill. Updates #41482 Change-Id: I5473cae15c98ae42e39f5928245b7762e7a5a8bf Reviewed-on: https://go-review.googlesource.com/c/go/+/261357 Trust: Richard Musiol Run-TryBot: Richard Musiol TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- misc/wasm/wasm_exec.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index 06b6062a2e0..3ea03c45b7e 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -102,7 +102,7 @@ } } - if (!global.crypto) { + if (!global.crypto && global.require) { const nodeCrypto = require("crypto"); global.crypto = { getRandomValues(b) { @@ -110,6 +110,9 @@ }, }; } + if (!global.crypto) { + throw new Error("global.crypto is not available, polyfill required (getRandomValues only)"); + } if (!global.performance) { global.performance = { @@ -120,13 +123,19 @@ }; } - if (!global.TextEncoder) { + if (!global.TextEncoder && global.require) { global.TextEncoder = require("util").TextEncoder; } + if (!global.TextEncoder) { + throw new Error("global.TextEncoder is not available, polyfill required"); + } - if (!global.TextDecoder) { + if (!global.TextDecoder && global.require) { global.TextDecoder = require("util").TextDecoder; } + if (!global.TextDecoder) { + throw new Error("global.TextDecoder is not available, polyfill required"); + } // End of polyfills for common API. From 15ead857dbc638b9d83a7686acf0dc746fc45918 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Wed, 9 Sep 2020 17:24:23 -0500 Subject: [PATCH 057/403] cmd/compiler,cmd/go,sync: add internal {LoadAcq,StoreRel}64 on ppc64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an internal atomic intrinsic for load with acquire semantics (extending LoadAcq to 64b) and add LoadAcquintptr for internal use within the sync package. For other arches, this remaps to the appropriate atomic.Load{,64} intrinsic which should not alter code generation. Similarly, add StoreRel{uintptr,64} for consistency, and inline. Finally, add an exception to allow sync to directly use the runtime/internal/atomic package which avoids more convoluted workarounds (contributed by Lynn Boger). In an extreme example, sync.(*Pool).pin consumes 20% of wall time during fmt tests. This is reduced to 5% on ppc64le/power9. From the fmt benchmarks on ppc64le: name old time/op new time/op delta SprintfPadding 468ns ± 0% 451ns ± 0% -3.63% SprintfEmpty 73.3ns ± 0% 51.9ns ± 0% -29.20% SprintfString 135ns ± 0% 122ns ± 0% -9.63% SprintfTruncateString 232ns ± 0% 214ns ± 0% -7.76% SprintfTruncateBytes 216ns ± 0% 202ns ± 0% -6.48% SprintfSlowParsingPath 162ns ± 0% 142ns ± 0% -12.35% SprintfQuoteString 1.00µs ± 0% 0.99µs ± 0% -1.39% SprintfInt 117ns ± 0% 104ns ± 0% -11.11% SprintfIntInt 190ns ± 0% 175ns ± 0% -7.89% SprintfPrefixedInt 232ns ± 0% 212ns ± 0% -8.62% SprintfFloat 270ns ± 0% 255ns ± 0% -5.56% SprintfComplex 1.01µs ± 0% 0.99µs ± 0% -1.68% SprintfBoolean 127ns ± 0% 111ns ± 0% -12.60% SprintfHexString 220ns ± 0% 198ns ± 0% -10.00% SprintfHexBytes 261ns ± 0% 252ns ± 0% -3.45% SprintfBytes 600ns ± 0% 590ns ± 0% -1.67% SprintfStringer 684ns ± 0% 658ns ± 0% -3.80% SprintfStructure 2.57µs ± 0% 2.57µs ± 0% -0.12% ManyArgs 669ns ± 0% 646ns ± 0% -3.44% FprintInt 140ns ± 0% 136ns ± 0% -2.86% FprintfBytes 184ns ± 0% 181ns ± 0% -1.63% FprintIntNoAlloc 140ns ± 0% 136ns ± 0% -2.86% ScanInts 929µs ± 0% 921µs ± 0% -0.79% ScanRecursiveInt 122ms ± 0% 121ms ± 0% -0.11% ScanRecursiveIntReaderWrapper 122ms ± 0% 122ms ± 0% -0.18% Change-Id: I4d66780261b57b06ef600229e475462e7313f0d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/253748 Run-TryBot: Lynn Boger Reviewed-by: Lynn Boger Reviewed-by: Keith Randall Trust: Lynn Boger TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/ssa.go | 19 +++++++++++ src/cmd/compile/internal/ssa/branchelim.go | 2 +- src/cmd/compile/internal/ssa/gen/PPC64.rules | 4 +-- .../compile/internal/ssa/gen/genericOps.go | 2 ++ src/cmd/compile/internal/ssa/opGen.go | 13 +++++++ src/cmd/compile/internal/ssa/rewritePPC64.go | 34 +++++++++++++++++++ src/cmd/go/internal/load/pkg.go | 5 +++ src/runtime/internal/atomic/asm_386.s | 3 ++ src/runtime/internal/atomic/asm_amd64.s | 6 ++++ src/runtime/internal/atomic/asm_arm.s | 6 ++++ src/runtime/internal/atomic/asm_mips64x.s | 6 ++++ src/runtime/internal/atomic/asm_mipsx.s | 3 ++ src/runtime/internal/atomic/asm_ppc64x.s | 13 +++++++ src/runtime/internal/atomic/atomic_386.go | 9 +++++ src/runtime/internal/atomic/atomic_amd64.go | 18 ++++++++++ src/runtime/internal/atomic/atomic_arm.go | 6 ++++ src/runtime/internal/atomic/atomic_arm64.go | 12 +++++++ src/runtime/internal/atomic/atomic_arm64.s | 14 ++++++++ src/runtime/internal/atomic/atomic_mips64x.go | 12 +++++++ src/runtime/internal/atomic/atomic_mips64x.s | 8 +++++ src/runtime/internal/atomic/atomic_mipsx.go | 6 ++++ src/runtime/internal/atomic/atomic_ppc64x.go | 12 +++++++ src/runtime/internal/atomic/atomic_ppc64x.s | 20 +++++++++++ src/runtime/internal/atomic/atomic_riscv64.go | 12 +++++++ src/runtime/internal/atomic/atomic_riscv64.s | 12 +++++++ src/runtime/internal/atomic/atomic_s390x.go | 24 +++++++++++++ src/runtime/internal/atomic/atomic_wasm.go | 24 +++++++++++++ src/sync/pool.go | 15 ++++---- 28 files changed, 310 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index d8f627c2136..e1455d2c3f0 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3389,6 +3389,13 @@ func init() { return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v) }, sys.PPC64, sys.S390X) + addF("runtime/internal/atomic", "LoadAcq64", + func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + v := s.newValue2(ssa.OpAtomicLoadAcq64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], s.mem()) + s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) + return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v) + }, + sys.PPC64) addF("runtime/internal/atomic", "Loadp", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { v := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(s.f.Config.Types.BytePtr, types.TypeMem), args[0], s.mem()) @@ -3427,6 +3434,12 @@ func init() { return nil }, sys.PPC64, sys.S390X) + addF("runtime/internal/atomic", "StoreRel64", + func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + s.vars[&memVar] = s.newValue3(ssa.OpAtomicStoreRel64, types.TypeMem, args[0], args[1], s.mem()) + return nil + }, + sys.PPC64) addF("runtime/internal/atomic", "Xchg", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { @@ -3542,9 +3555,15 @@ func init() { alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load", p4...) alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load64", p8...) alias("runtime/internal/atomic", "LoadAcq", "runtime/internal/atomic", "Load", lwatomics...) + alias("runtime/internal/atomic", "LoadAcq64", "runtime/internal/atomic", "Load64", lwatomics...) + alias("runtime/internal/atomic", "LoadAcquintptr", "runtime/internal/atomic", "LoadAcq", p4...) + alias("runtime/internal/atomic", "LoadAcquintptr", "runtime/internal/atomic", "LoadAcq64", p8...) alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store", p4...) alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store64", p8...) alias("runtime/internal/atomic", "StoreRel", "runtime/internal/atomic", "Store", lwatomics...) + alias("runtime/internal/atomic", "StoreRel64", "runtime/internal/atomic", "Store64", lwatomics...) + alias("runtime/internal/atomic", "StoreReluintptr", "runtime/internal/atomic", "StoreRel", p4...) + alias("runtime/internal/atomic", "StoreReluintptr", "runtime/internal/atomic", "StoreRel64", p8...) alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg", p4...) alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg64", p8...) alias("runtime/internal/atomic", "Xadduintptr", "runtime/internal/atomic", "Xadd", p4...) diff --git a/src/cmd/compile/internal/ssa/branchelim.go b/src/cmd/compile/internal/ssa/branchelim.go index 4f9fd8e22e1..1d34f8160b1 100644 --- a/src/cmd/compile/internal/ssa/branchelim.go +++ b/src/cmd/compile/internal/ssa/branchelim.go @@ -35,7 +35,7 @@ func branchelim(f *Func) { for _, b := range f.Blocks { for _, v := range b.Values { switch v.Op { - case OpLoad, OpAtomicLoad8, OpAtomicLoad32, OpAtomicLoad64, OpAtomicLoadPtr, OpAtomicLoadAcq32: + case OpLoad, OpAtomicLoad8, OpAtomicLoad32, OpAtomicLoad64, OpAtomicLoadPtr, OpAtomicLoadAcq32, OpAtomicLoadAcq64: loadAddr.add(v.Args[0].ID) case OpMove: loadAddr.add(v.Args[1].ID) diff --git a/src/cmd/compile/internal/ssa/gen/PPC64.rules b/src/cmd/compile/internal/ssa/gen/PPC64.rules index a05cfee6541..11b1a318fe0 100644 --- a/src/cmd/compile/internal/ssa/gen/PPC64.rules +++ b/src/cmd/compile/internal/ssa/gen/PPC64.rules @@ -967,10 +967,10 @@ // atomic intrinsics (AtomicLoad(8|32|64|Ptr) ptr mem) => (LoweredAtomicLoad(8|32|64|Ptr) [1] ptr mem) -(AtomicLoadAcq32 ptr mem) => (LoweredAtomicLoad32 [0] ptr mem) +(AtomicLoadAcq(32|64) ptr mem) => (LoweredAtomicLoad(32|64) [0] ptr mem) (AtomicStore(8|32|64) ptr val mem) => (LoweredAtomicStore(8|32|64) [1] ptr val mem) -(AtomicStoreRel32 ptr val mem) => (LoweredAtomicStore32 [0] ptr val mem) +(AtomicStoreRel(32|64) ptr val mem) => (LoweredAtomicStore(32|64) [0] ptr val mem) //(AtomicStorePtrNoWB ptr val mem) => (STLR ptr val mem) (AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 85839303c59..12ba9f1fc9f 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -550,11 +550,13 @@ var genericOps = []opData{ {name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory. {name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory. {name: "AtomicLoadAcq32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory. + {name: "AtomicLoadAcq64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory. {name: "AtomicStore8", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory. {name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory. {name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory. {name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory. {name: "AtomicStoreRel32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory. + {name: "AtomicStoreRel64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory. {name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory. {name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory. {name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory. diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 051550fb171..eae30c79bab 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2839,11 +2839,13 @@ const ( OpAtomicLoad64 OpAtomicLoadPtr OpAtomicLoadAcq32 + OpAtomicLoadAcq64 OpAtomicStore8 OpAtomicStore32 OpAtomicStore64 OpAtomicStorePtrNoWB OpAtomicStoreRel32 + OpAtomicStoreRel64 OpAtomicExchange32 OpAtomicExchange64 OpAtomicAdd32 @@ -35429,6 +35431,11 @@ var opcodeTable = [...]opInfo{ argLen: 2, generic: true, }, + { + name: "AtomicLoadAcq64", + argLen: 2, + generic: true, + }, { name: "AtomicStore8", argLen: 3, @@ -35459,6 +35466,12 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, generic: true, }, + { + name: "AtomicStoreRel64", + argLen: 3, + hasSideEffects: true, + generic: true, + }, { name: "AtomicExchange32", argLen: 3, diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go index 1b8a5a78ca2..a820bc0c4e2 100644 --- a/src/cmd/compile/internal/ssa/rewritePPC64.go +++ b/src/cmd/compile/internal/ssa/rewritePPC64.go @@ -82,6 +82,8 @@ func rewriteValuePPC64(v *Value) bool { return rewriteValuePPC64_OpAtomicLoad8(v) case OpAtomicLoadAcq32: return rewriteValuePPC64_OpAtomicLoadAcq32(v) + case OpAtomicLoadAcq64: + return rewriteValuePPC64_OpAtomicLoadAcq64(v) case OpAtomicLoadPtr: return rewriteValuePPC64_OpAtomicLoadPtr(v) case OpAtomicOr8: @@ -95,6 +97,8 @@ func rewriteValuePPC64(v *Value) bool { return rewriteValuePPC64_OpAtomicStore8(v) case OpAtomicStoreRel32: return rewriteValuePPC64_OpAtomicStoreRel32(v) + case OpAtomicStoreRel64: + return rewriteValuePPC64_OpAtomicStoreRel64(v) case OpAvg64u: return rewriteValuePPC64_OpAvg64u(v) case OpBitLen32: @@ -930,6 +934,20 @@ func rewriteValuePPC64_OpAtomicLoadAcq32(v *Value) bool { return true } } +func rewriteValuePPC64_OpAtomicLoadAcq64(v *Value) bool { + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (AtomicLoadAcq64 ptr mem) + // result: (LoweredAtomicLoad64 [0] ptr mem) + for { + ptr := v_0 + mem := v_1 + v.reset(OpPPC64LoweredAtomicLoad64) + v.AuxInt = int64ToAuxInt(0) + v.AddArg2(ptr, mem) + return true + } +} func rewriteValuePPC64_OpAtomicLoadPtr(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -1008,6 +1026,22 @@ func rewriteValuePPC64_OpAtomicStoreRel32(v *Value) bool { return true } } +func rewriteValuePPC64_OpAtomicStoreRel64(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + // match: (AtomicStoreRel64 ptr val mem) + // result: (LoweredAtomicStore64 [0] ptr val mem) + for { + ptr := v_0 + val := v_1 + mem := v_2 + v.reset(OpPPC64LoweredAtomicStore64) + v.AuxInt = int64ToAuxInt(0) + v.AddArg3(ptr, val, mem) + return true + } +} func rewriteValuePPC64_OpAvg64u(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 2bdc08ba365..c9665265e94 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -1337,6 +1337,11 @@ func disallowInternal(srcDir string, importer *Package, importerPath string, p * return p } + // Allow sync package to access lightweight atomic functions limited to the runtime. + if p.Standard && strings.HasPrefix(importerPath, "sync") && p.ImportPath == "runtime/internal/atomic" { + return p + } + // Internal is present. // Map import path back to directory corresponding to parent of internal. if i > 0 { diff --git a/src/runtime/internal/atomic/asm_386.s b/src/runtime/internal/atomic/asm_386.s index bcefff373fc..7ebf675ac5f 100644 --- a/src/runtime/internal/atomic/asm_386.s +++ b/src/runtime/internal/atomic/asm_386.s @@ -189,6 +189,9 @@ TEXT ·Store(SB), NOSPLIT, $0-8 TEXT ·StoreRel(SB), NOSPLIT, $0-8 JMP ·Store(SB) +TEXT runtime∕internal∕atomic·StoreReluintptr(SB), NOSPLIT, $0-8 + JMP runtime∕internal∕atomic·Store(SB) + // uint64 atomicload64(uint64 volatile* addr); TEXT ·Load64(SB), NOSPLIT, $0-12 NO_LOCAL_POINTERS diff --git a/src/runtime/internal/atomic/asm_amd64.s b/src/runtime/internal/atomic/asm_amd64.s index 90c56424c97..80fb31285de 100644 --- a/src/runtime/internal/atomic/asm_amd64.s +++ b/src/runtime/internal/atomic/asm_amd64.s @@ -136,6 +136,12 @@ TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12 TEXT runtime∕internal∕atomic·StoreRel(SB), NOSPLIT, $0-12 JMP runtime∕internal∕atomic·Store(SB) +TEXT runtime∕internal∕atomic·StoreRel64(SB), NOSPLIT, $0-16 + JMP runtime∕internal∕atomic·Store64(SB) + +TEXT runtime∕internal∕atomic·StoreReluintptr(SB), NOSPLIT, $0-16 + JMP runtime∕internal∕atomic·Store64(SB) + TEXT runtime∕internal∕atomic·Store8(SB), NOSPLIT, $0-9 MOVQ ptr+0(FP), BX MOVB val+8(FP), AX diff --git a/src/runtime/internal/atomic/asm_arm.s b/src/runtime/internal/atomic/asm_arm.s index c3d1d9025df..274925ed608 100644 --- a/src/runtime/internal/atomic/asm_arm.s +++ b/src/runtime/internal/atomic/asm_arm.s @@ -57,6 +57,9 @@ TEXT ·Loadp(SB),NOSPLIT|NOFRAME,$0-8 TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$0-8 B ·Load(SB) +TEXT ·LoadAcquintptr(SB),NOSPLIT|NOFRAME,$0-8 + B ·Load(SB) + TEXT ·Casuintptr(SB),NOSPLIT,$0-13 B ·Cas(SB) @@ -81,6 +84,9 @@ TEXT ·StorepNoWB(SB),NOSPLIT,$0-8 TEXT ·StoreRel(SB),NOSPLIT,$0-8 B ·Store(SB) +TEXT ·StoreReluintptr(SB),NOSPLIT,$0-8 + B ·Store(SB) + TEXT ·Xadduintptr(SB),NOSPLIT,$0-12 B ·Xadd(SB) diff --git a/src/runtime/internal/atomic/asm_mips64x.s b/src/runtime/internal/atomic/asm_mips64x.s index 3290fb726a9..03fb8229294 100644 --- a/src/runtime/internal/atomic/asm_mips64x.s +++ b/src/runtime/internal/atomic/asm_mips64x.s @@ -158,6 +158,12 @@ TEXT ·StorepNoWB(SB), NOSPLIT, $0-16 TEXT ·StoreRel(SB), NOSPLIT, $0-12 JMP ·Store(SB) +TEXT ·StoreRel64(SB), NOSPLIT, $0-16 + JMP ·Store64(SB) + +TEXT ·StoreReluintptr(SB), NOSPLIT, $0-16 + JMP ·Store64(SB) + TEXT ·Store(SB), NOSPLIT, $0-12 MOVV ptr+0(FP), R1 MOVW val+8(FP), R2 diff --git a/src/runtime/internal/atomic/asm_mipsx.s b/src/runtime/internal/atomic/asm_mipsx.s index 62811a6599e..63bb5488256 100644 --- a/src/runtime/internal/atomic/asm_mipsx.s +++ b/src/runtime/internal/atomic/asm_mipsx.s @@ -122,6 +122,9 @@ TEXT ·StorepNoWB(SB),NOSPLIT,$0-8 TEXT ·StoreRel(SB),NOSPLIT,$0-8 JMP ·Store(SB) +TEXT ·StoreReluintptr(SB),NOSPLIT,$0-8 + JMP ·Store(SB) + // void Or8(byte volatile*, byte); TEXT ·Or8(SB),NOSPLIT,$0-5 MOVW ptr+0(FP), R1 diff --git a/src/runtime/internal/atomic/asm_ppc64x.s b/src/runtime/internal/atomic/asm_ppc64x.s index 06dc931bf43..c0237de4d05 100644 --- a/src/runtime/internal/atomic/asm_ppc64x.s +++ b/src/runtime/internal/atomic/asm_ppc64x.s @@ -83,12 +83,18 @@ TEXT runtime∕internal∕atomic·Casuintptr(SB), NOSPLIT, $0-25 TEXT runtime∕internal∕atomic·Loaduintptr(SB), NOSPLIT|NOFRAME, $0-16 BR runtime∕internal∕atomic·Load64(SB) +TEXT runtime∕internal∕atomic·LoadAcquintptr(SB), NOSPLIT|NOFRAME, $0-16 + BR runtime∕internal∕atomic·LoadAcq64(SB) + TEXT runtime∕internal∕atomic·Loaduint(SB), NOSPLIT|NOFRAME, $0-16 BR runtime∕internal∕atomic·Load64(SB) TEXT runtime∕internal∕atomic·Storeuintptr(SB), NOSPLIT, $0-16 BR runtime∕internal∕atomic·Store64(SB) +TEXT runtime∕internal∕atomic·StoreReluintptr(SB), NOSPLIT, $0-16 + BR runtime∕internal∕atomic·StoreRel64(SB) + TEXT runtime∕internal∕atomic·Xadduintptr(SB), NOSPLIT, $0-24 BR runtime∕internal∕atomic·Xadd64(SB) @@ -191,6 +197,13 @@ TEXT runtime∕internal∕atomic·StoreRel(SB), NOSPLIT, $0-12 MOVW R4, 0(R3) RET +TEXT runtime∕internal∕atomic·StoreRel64(SB), NOSPLIT, $0-16 + MOVD ptr+0(FP), R3 + MOVD val+8(FP), R4 + LWSYNC + MOVD R4, 0(R3) + RET + // void runtime∕internal∕atomic·Or8(byte volatile*, byte); TEXT runtime∕internal∕atomic·Or8(SB), NOSPLIT, $0-9 MOVD ptr+0(FP), R3 diff --git a/src/runtime/internal/atomic/atomic_386.go b/src/runtime/internal/atomic/atomic_386.go index 8d002ebfe37..06ce6a5356f 100644 --- a/src/runtime/internal/atomic/atomic_386.go +++ b/src/runtime/internal/atomic/atomic_386.go @@ -30,6 +30,12 @@ func LoadAcq(ptr *uint32) uint32 { return *ptr } +//go:nosplit +//go:noinline +func LoadAcquintptr(ptr *uintptr) uintptr { + return *ptr +} + //go:noescape func Xadd64(ptr *uint64, delta int64) uint64 @@ -83,5 +89,8 @@ func Store64(ptr *uint64, val uint64) //go:noescape func StoreRel(ptr *uint32, val uint32) +//go:noescape +func StoreReluintptr(ptr *uintptr, val uintptr) + // NO go:noescape annotation; see atomic_pointer.go. func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) diff --git a/src/runtime/internal/atomic/atomic_amd64.go b/src/runtime/internal/atomic/atomic_amd64.go index 14b81017204..1b71a16d948 100644 --- a/src/runtime/internal/atomic/atomic_amd64.go +++ b/src/runtime/internal/atomic/atomic_amd64.go @@ -35,6 +35,18 @@ func LoadAcq(ptr *uint32) uint32 { return *ptr } +//go:nosplit +//go:noinline +func LoadAcq64(ptr *uint64) uint64 { + return *ptr +} + +//go:nosplit +//go:noinline +func LoadAcquintptr(ptr *uintptr) uintptr { + return *ptr +} + //go:noescape func Xadd(ptr *uint32, delta int32) uint32 @@ -85,6 +97,12 @@ func Store64(ptr *uint64, val uint64) //go:noescape func StoreRel(ptr *uint32, val uint32) +//go:noescape +func StoreRel64(ptr *uint64, val uint64) + +//go:noescape +func StoreReluintptr(ptr *uintptr, val uintptr) + // StorepNoWB performs *ptr = val atomically and without a write // barrier. // diff --git a/src/runtime/internal/atomic/atomic_arm.go b/src/runtime/internal/atomic/atomic_arm.go index 95713afcc17..67d529c1cb3 100644 --- a/src/runtime/internal/atomic/atomic_arm.go +++ b/src/runtime/internal/atomic/atomic_arm.go @@ -81,6 +81,9 @@ func Store(addr *uint32, v uint32) //go:noescape func StoreRel(addr *uint32, v uint32) +//go:noescape +func StoreReluintptr(addr *uintptr, v uintptr) + //go:nosplit func goCas64(addr *uint64, old, new uint64) bool { if uintptr(unsafe.Pointer(addr))&7 != 0 { @@ -194,6 +197,9 @@ func Load8(addr *uint8) uint8 //go:noescape func LoadAcq(addr *uint32) uint32 +//go:noescape +func LoadAcquintptr(ptr *uintptr) uintptr + //go:noescape func Cas64(addr *uint64, old, new uint64) bool diff --git a/src/runtime/internal/atomic/atomic_arm64.go b/src/runtime/internal/atomic/atomic_arm64.go index 26ca94d54cc..c9b4322fe93 100644 --- a/src/runtime/internal/atomic/atomic_arm64.go +++ b/src/runtime/internal/atomic/atomic_arm64.go @@ -41,6 +41,12 @@ func Loadp(ptr unsafe.Pointer) unsafe.Pointer //go:noescape func LoadAcq(addr *uint32) uint32 +//go:noescape +func LoadAcq64(ptr *uint64) uint64 + +//go:noescape +func LoadAcquintptr(ptr *uintptr) uintptr + //go:noescape func Or8(ptr *uint8, val uint8) @@ -67,3 +73,9 @@ func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) //go:noescape func StoreRel(ptr *uint32, val uint32) + +//go:noescape +func StoreRel64(ptr *uint64, val uint64) + +//go:noescape +func StoreReluintptr(ptr *uintptr, val uintptr) diff --git a/src/runtime/internal/atomic/atomic_arm64.s b/src/runtime/internal/atomic/atomic_arm64.s index a2eb7568d26..36c7698b189 100644 --- a/src/runtime/internal/atomic/atomic_arm64.s +++ b/src/runtime/internal/atomic/atomic_arm64.s @@ -36,12 +36,26 @@ TEXT ·Loadp(SB),NOSPLIT,$0-16 TEXT ·LoadAcq(SB),NOSPLIT,$0-12 B ·Load(SB) +// uint64 runtime∕internal∕atomic·LoadAcquintptr(uint64 volatile* addr) +TEXT ·LoadAcq64(SB),NOSPLIT,$0-16 + B ·Load64(SB) + +// uintptr runtime∕internal∕atomic·LoadAcq64(uintptr volatile* addr) +TEXT ·LoadAcquintptr(SB),NOSPLIT,$0-16 + B ·Load64(SB) + TEXT runtime∕internal∕atomic·StorepNoWB(SB), NOSPLIT, $0-16 B runtime∕internal∕atomic·Store64(SB) TEXT runtime∕internal∕atomic·StoreRel(SB), NOSPLIT, $0-12 B runtime∕internal∕atomic·Store(SB) +TEXT runtime∕internal∕atomic·StoreRel64(SB), NOSPLIT, $0-16 + B runtime∕internal∕atomic·Store64(SB) + +TEXT runtime∕internal∕atomic·StoreReluintptr(SB), NOSPLIT, $0-16 + B runtime∕internal∕atomic·Store64(SB) + TEXT runtime∕internal∕atomic·Store(SB), NOSPLIT, $0-12 MOVD ptr+0(FP), R0 MOVW val+8(FP), R1 diff --git a/src/runtime/internal/atomic/atomic_mips64x.go b/src/runtime/internal/atomic/atomic_mips64x.go index 1d9977850b5..fca22425146 100644 --- a/src/runtime/internal/atomic/atomic_mips64x.go +++ b/src/runtime/internal/atomic/atomic_mips64x.go @@ -41,6 +41,12 @@ func Loadp(ptr unsafe.Pointer) unsafe.Pointer //go:noescape func LoadAcq(ptr *uint32) uint32 +//go:noescape +func LoadAcq64(ptr *uint64) uint64 + +//go:noescape +func LoadAcquintptr(ptr *uintptr) uintptr + //go:noescape func And8(ptr *uint8, val uint8) @@ -69,3 +75,9 @@ func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) //go:noescape func StoreRel(ptr *uint32, val uint32) + +//go:noescape +func StoreRel64(ptr *uint64, val uint64) + +//go:noescape +func StoreReluintptr(ptr *uintptr, val uintptr) diff --git a/src/runtime/internal/atomic/atomic_mips64x.s b/src/runtime/internal/atomic/atomic_mips64x.s index 1ed90937c96..125c0c221c4 100644 --- a/src/runtime/internal/atomic/atomic_mips64x.s +++ b/src/runtime/internal/atomic/atomic_mips64x.s @@ -47,3 +47,11 @@ TEXT ·Loadp(SB),NOSPLIT|NOFRAME,$0-16 // uint32 runtime∕internal∕atomic·LoadAcq(uint32 volatile* ptr) TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$0-12 JMP atomic·Load(SB) + +// uint64 runtime∕internal∕atomic·LoadAcq64(uint64 volatile* ptr) +TEXT ·LoadAcq64(SB),NOSPLIT|NOFRAME,$0-16 + JMP atomic·Load64(SB) + +// uintptr runtime∕internal∕atomic·LoadAcquintptr(uintptr volatile* ptr) +TEXT ·LoadAcquintptr(SB),NOSPLIT|NOFRAME,$0-16 + JMP atomic·Load64(SB) diff --git a/src/runtime/internal/atomic/atomic_mipsx.go b/src/runtime/internal/atomic/atomic_mipsx.go index b99bfe7dbf4..be1e6a038b1 100644 --- a/src/runtime/internal/atomic/atomic_mipsx.go +++ b/src/runtime/internal/atomic/atomic_mipsx.go @@ -132,6 +132,9 @@ func Loadp(ptr unsafe.Pointer) unsafe.Pointer //go:noescape func LoadAcq(ptr *uint32) uint32 +//go:noescape +func LoadAcquintptr(ptr *uintptr) uintptr + //go:noescape func And8(ptr *uint8, val uint8) @@ -150,5 +153,8 @@ func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) //go:noescape func StoreRel(ptr *uint32, val uint32) +//go:noescape +func StoreReluintptr(ptr *uintptr, val uintptr) + //go:noescape func CasRel(addr *uint32, old, new uint32) bool diff --git a/src/runtime/internal/atomic/atomic_ppc64x.go b/src/runtime/internal/atomic/atomic_ppc64x.go index a48ecf5ee8a..e759bb27a29 100644 --- a/src/runtime/internal/atomic/atomic_ppc64x.go +++ b/src/runtime/internal/atomic/atomic_ppc64x.go @@ -41,6 +41,12 @@ func Loadp(ptr unsafe.Pointer) unsafe.Pointer //go:noescape func LoadAcq(ptr *uint32) uint32 +//go:noescape +func LoadAcq64(ptr *uint64) uint64 + +//go:noescape +func LoadAcquintptr(ptr *uintptr) uintptr + //go:noescape func And8(ptr *uint8, val uint8) @@ -67,5 +73,11 @@ func Store64(ptr *uint64, val uint64) //go:noescape func StoreRel(ptr *uint32, val uint32) +//go:noescape +func StoreRel64(ptr *uint64, val uint64) + +//go:noescape +func StoreReluintptr(ptr *uintptr, val uintptr) + // NO go:noescape annotation; see atomic_pointer.go. func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) diff --git a/src/runtime/internal/atomic/atomic_ppc64x.s b/src/runtime/internal/atomic/atomic_ppc64x.s index c2f696fb347..b79cdbca342 100644 --- a/src/runtime/internal/atomic/atomic_ppc64x.s +++ b/src/runtime/internal/atomic/atomic_ppc64x.s @@ -6,6 +6,15 @@ #include "textflag.h" + +// For more details about how various memory models are +// enforced on POWER, the following paper provides more +// details about how they enforce C/C++ like models. This +// gives context about why the strange looking code +// sequences below work. +// +// http://www.rdrop.com/users/paulmck/scalability/paper/N2745r.2011.03.04a.html + // uint32 runtime∕internal∕atomic·Load(uint32 volatile* ptr) TEXT ·Load(SB),NOSPLIT|NOFRAME,$-8-12 MOVD ptr+0(FP), R3 @@ -56,5 +65,16 @@ TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$-8-12 MOVWZ 0(R3), R3 CMPW R3, R3, CR7 BC 4, 30, 1(PC) // bne- cr7, 0x4 + ISYNC MOVW R3, ret+8(FP) RET + +// uint64 runtime∕internal∕atomic·LoadAcq64(uint64 volatile* ptr) +TEXT ·LoadAcq64(SB),NOSPLIT|NOFRAME,$-8-16 + MOVD ptr+0(FP), R3 + MOVD 0(R3), R3 + CMP R3, R3, CR7 + BC 4, 30, 1(PC) // bne- cr7, 0x4 + ISYNC + MOVD R3, ret+8(FP) + RET diff --git a/src/runtime/internal/atomic/atomic_riscv64.go b/src/runtime/internal/atomic/atomic_riscv64.go index d52512369e7..617bc1a3eb2 100644 --- a/src/runtime/internal/atomic/atomic_riscv64.go +++ b/src/runtime/internal/atomic/atomic_riscv64.go @@ -39,6 +39,12 @@ func Loadp(ptr unsafe.Pointer) unsafe.Pointer //go:noescape func LoadAcq(ptr *uint32) uint32 +//go:noescape +func LoadAcq64(ptr *uint64) uint64 + +//go:noescape +func LoadAcquintptr(ptr *uintptr) uintptr + //go:noescape func Or8(ptr *uint8, val uint8) @@ -65,3 +71,9 @@ func StorepNoWB(ptr unsafe.Pointer, val unsafe.Pointer) //go:noescape func StoreRel(ptr *uint32, val uint32) + +//go:noescape +func StoreRel64(ptr *uint64, val uint64) + +//go:noescape +func StoreReluintptr(ptr *uintptr, val uintptr) diff --git a/src/runtime/internal/atomic/atomic_riscv64.s b/src/runtime/internal/atomic/atomic_riscv64.s index d005325ca3a..db139d690ae 100644 --- a/src/runtime/internal/atomic/atomic_riscv64.s +++ b/src/runtime/internal/atomic/atomic_riscv64.s @@ -150,6 +150,12 @@ TEXT ·Xaddint64(SB),NOSPLIT,$0-24 TEXT ·LoadAcq(SB),NOSPLIT|NOFRAME,$0-12 JMP ·Load(SB) +TEXT ·LoadAcq64(SB),NOSPLIT|NOFRAME,$0-16 + JMP ·Load64(SB) + +TEXT ·LoadAcquintptr(SB),NOSPLIT|NOFRAME,$0-16 + JMP ·Load64(SB) + // func Loadp(ptr unsafe.Pointer) unsafe.Pointer TEXT ·Loadp(SB),NOSPLIT,$0-16 JMP ·Load64(SB) @@ -161,6 +167,12 @@ TEXT ·StorepNoWB(SB), NOSPLIT, $0-16 TEXT ·StoreRel(SB), NOSPLIT, $0-12 JMP ·Store(SB) +TEXT ·StoreRel64(SB), NOSPLIT, $0-16 + JMP ·Store64(SB) + +TEXT ·StoreReluintptr(SB), NOSPLIT, $0-16 + JMP ·Store64(SB) + // func Xchg(ptr *uint32, new uint32) uint32 TEXT ·Xchg(SB), NOSPLIT, $0-20 MOV ptr+0(FP), A0 diff --git a/src/runtime/internal/atomic/atomic_s390x.go b/src/runtime/internal/atomic/atomic_s390x.go index 4d73b39baf0..b649caa39f2 100644 --- a/src/runtime/internal/atomic/atomic_s390x.go +++ b/src/runtime/internal/atomic/atomic_s390x.go @@ -41,6 +41,18 @@ func LoadAcq(ptr *uint32) uint32 { return *ptr } +//go:nosplit +//go:noinline +func LoadAcq64(ptr *uint64) uint64 { + return *ptr +} + +//go:nosplit +//go:noinline +func LoadAcquintptr(ptr *uintptr) uintptr { + return *ptr +} + //go:noescape func Store(ptr *uint32, val uint32) @@ -59,6 +71,18 @@ func StoreRel(ptr *uint32, val uint32) { *ptr = val } +//go:nosplit +//go:noinline +func StoreRel64(ptr *uint64, val uint64) { + *ptr = val +} + +//go:nosplit +//go:noinline +func StoreReluintptr(ptr *uintptr, val uintptr) { + *ptr = val +} + //go:noescape func And8(ptr *uint8, val uint8) diff --git a/src/runtime/internal/atomic/atomic_wasm.go b/src/runtime/internal/atomic/atomic_wasm.go index 2c0c3a81740..60a4942884f 100644 --- a/src/runtime/internal/atomic/atomic_wasm.go +++ b/src/runtime/internal/atomic/atomic_wasm.go @@ -45,6 +45,18 @@ func LoadAcq(ptr *uint32) uint32 { return *ptr } +//go:nosplit +//go:noinline +func LoadAcq64(ptr *uint64) uint64 { + return *ptr +} + +//go:nosplit +//go:noinline +func LoadAcquintptr(ptr *uintptr) uintptr { + return *ptr +} + //go:nosplit //go:noinline func Load8(ptr *uint8) uint8 { @@ -141,6 +153,18 @@ func StoreRel(ptr *uint32, val uint32) { *ptr = val } +//go:nosplit +//go:noinline +func StoreRel64(ptr *uint64, val uint64) { + *ptr = val +} + +//go:nosplit +//go:noinline +func StoreReluintptr(ptr *uintptr, val uintptr) { + *ptr = val +} + //go:nosplit //go:noinline func Store8(ptr *uint8, val uint8) { diff --git a/src/sync/pool.go b/src/sync/pool.go index ca7afdb12ff..137413fdc4f 100644 --- a/src/sync/pool.go +++ b/src/sync/pool.go @@ -7,6 +7,7 @@ package sync import ( "internal/race" "runtime" + runtimeatomic "runtime/internal/atomic" "sync/atomic" "unsafe" ) @@ -152,8 +153,8 @@ func (p *Pool) Get() interface{} { func (p *Pool) getSlow(pid int) interface{} { // See the comment in pin regarding ordering of the loads. - size := atomic.LoadUintptr(&p.localSize) // load-acquire - locals := p.local // load-consume + size := runtimeatomic.LoadAcquintptr(&p.localSize) // load-acquire + locals := p.local // load-consume // Try to steal one element from other procs. for i := 0; i < int(size); i++ { l := indexLocal(locals, (pid+i+1)%int(size)) @@ -165,7 +166,7 @@ func (p *Pool) getSlow(pid int) interface{} { // Try the victim cache. We do this after attempting to steal // from all primary caches because we want objects in the // victim cache to age out if at all possible. - size = atomic.LoadUintptr(&p.victimSize) + size = runtimeatomic.Loaduintptr(&p.victimSize) if uintptr(pid) >= size { return nil } @@ -198,8 +199,8 @@ func (p *Pool) pin() (*poolLocal, int) { // Since we've disabled preemption, GC cannot happen in between. // Thus here we must observe local at least as large localSize. // We can observe a newer/larger local, it is fine (we must observe its zero-initialized-ness). - s := atomic.LoadUintptr(&p.localSize) // load-acquire - l := p.local // load-consume + s := runtimeatomic.LoadAcquintptr(&p.localSize) // load-acquire + l := p.local // load-consume if uintptr(pid) < s { return indexLocal(l, pid), pid } @@ -225,8 +226,8 @@ func (p *Pool) pinSlow() (*poolLocal, int) { // If GOMAXPROCS changes between GCs, we re-allocate the array and lose the old one. size := runtime.GOMAXPROCS(0) local := make([]poolLocal, size) - atomic.StorePointer(&p.local, unsafe.Pointer(&local[0])) // store-release - atomic.StoreUintptr(&p.localSize, uintptr(size)) // store-release + atomic.StorePointer(&p.local, unsafe.Pointer(&local[0])) // store-release + runtimeatomic.StoreReluintptr(&p.localSize, uintptr(size)) // store-release return &local[pid], pid } From bcc333348769efed7c38acfa013e5475c53e8f5f Mon Sep 17 00:00:00 2001 From: Obeyda Djeffal Date: Fri, 16 Oct 2020 16:34:15 +0100 Subject: [PATCH 058/403] cmd/go: ignore GOFLAGS values without name in go env/bug This happens with 'go env' and 'go bug'. If GOFLAGS variable is set to something like '=value', running `go env` panics with this error message: goroutine 1 [running]: cmd/go/internal/base.SetFromGOFLAGS(0xd96838) cmd/go/internal/base/goflags.go:101 +0x9a7 main.main() cmd/go/main.go:188 +0x755 This happens when the 'name' of the flag is not specified ('=' or '=value'), with any combination of other flags. Other commands show this error message: go: parsing $GOFLAGS: non-flag This happens only with 'env' and 'bug' because we have this: https://go.googlesource.com/go/+/refs/heads/master/src/cmd/go/internal/base/goflags.go#40 New behaviour: ignore the bad flag, since we don't want to report that with `go env` or `go bug`. Fixes: #42013 Change-Id: I72602840ca00293d2a92ea28451b75b9799e3d6c Reviewed-on: https://go-review.googlesource.com/c/go/+/263098 Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Michael Matloob --- src/cmd/go/internal/base/goflags.go | 6 +++++- src/cmd/go/testdata/script/env_write.txt | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/internal/base/goflags.go b/src/cmd/go/internal/base/goflags.go index 4da27550fd3..267006be7a2 100644 --- a/src/cmd/go/internal/base/goflags.go +++ b/src/cmd/go/internal/base/goflags.go @@ -92,7 +92,11 @@ func SetFromGOFLAGS(flags *flag.FlagSet) { } for _, goflag := range goflags { name, value, hasValue := goflag, "", false - if i := strings.Index(goflag, "="); i >= 0 { + // Ignore invalid flags like '=' or '=value'. + // If it is not reported in InitGOFlags it means we don't want to report it. + if i := strings.Index(goflag, "="); i == 0 { + continue + } else if i > 0 { name, value, hasValue = goflag[:i], goflag[i+1:], true } if strings.HasPrefix(name, "--") { diff --git a/src/cmd/go/testdata/script/env_write.txt b/src/cmd/go/testdata/script/env_write.txt index 24bb6f8f59d..0af22ed421c 100644 --- a/src/cmd/go/testdata/script/env_write.txt +++ b/src/cmd/go/testdata/script/env_write.txt @@ -24,6 +24,10 @@ stdout GOARCH= stdout GOOS= stdout GOROOT= +# go env ignores invalid flag in GOFLAGS environment variable +env GOFLAGS='=true' +go env + # checking errors ! go env -w stderr 'go env -w: no KEY=VALUE arguments given' From 214136b7412d56151d5443741feb0ed873facf2e Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 21 Oct 2020 10:07:02 -0400 Subject: [PATCH 059/403] cmd/go/internal/fsys: use a root other than "." in Walk tests Fixes #42115 Change-Id: Icf4c9eac5ed3295acbc8377c7a06f82c6bddc747 Reviewed-on: https://go-review.googlesource.com/c/go/+/264177 Trust: Bryan C. Mills Trust: Jay Conrod Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod Reviewed-by: David du Colombier <0intro@gmail.com> TryBot-Result: Go Bot --- src/cmd/go/internal/fsys/fsys_test.go | 74 +++++++++++++++------------ 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/src/cmd/go/internal/fsys/fsys_test.go b/src/cmd/go/internal/fsys/fsys_test.go index 19bf2821909..fd98d13f3d0 100644 --- a/src/cmd/go/internal/fsys/fsys_test.go +++ b/src/cmd/go/internal/fsys/fsys_test.go @@ -487,6 +487,11 @@ contents don't matter for this test } func TestWalk(t *testing.T) { + // The root of the walk must be a name with an actual basename, not just ".". + // Walk uses Lstat to obtain the name of the root, and Lstat on platforms + // other than Plan 9 reports the name "." instead of the actual base name of + // the directory. (See https://golang.org/issue/42115.) + type file struct { path string name string @@ -502,62 +507,62 @@ func TestWalk(t *testing.T) { }{ {"no overlay", ` {} --- file.txt -- +-- dir/file.txt -- `, - ".", + "dir", []file{ - {".", ".", 0, fs.ModeDir | 0700, true}, - {"file.txt", "file.txt", 0, 0600, false}, + {"dir", "dir", 0, fs.ModeDir | 0700, true}, + {"dir/file.txt", "file.txt", 0, 0600, false}, }, }, {"overlay with different file", ` { "Replace": { - "file.txt": "other.txt" + "dir/file.txt": "dir/other.txt" } } --- file.txt -- --- other.txt -- +-- dir/file.txt -- +-- dir/other.txt -- contents of other file `, - ".", + "dir", []file{ - {".", ".", 0, fs.ModeDir | 0500, true}, - {"file.txt", "file.txt", 23, 0600, false}, - {"other.txt", "other.txt", 23, 0600, false}, + {"dir", "dir", 0, fs.ModeDir | 0500, true}, + {"dir/file.txt", "file.txt", 23, 0600, false}, + {"dir/other.txt", "other.txt", 23, 0600, false}, }, }, {"overlay with new file", ` { "Replace": { - "file.txt": "other.txt" + "dir/file.txt": "dir/other.txt" } } --- other.txt -- +-- dir/other.txt -- contents of other file `, - ".", + "dir", []file{ - {".", ".", 0, fs.ModeDir | 0500, true}, - {"file.txt", "file.txt", 23, 0600, false}, - {"other.txt", "other.txt", 23, 0600, false}, + {"dir", "dir", 0, fs.ModeDir | 0500, true}, + {"dir/file.txt", "file.txt", 23, 0600, false}, + {"dir/other.txt", "other.txt", 23, 0600, false}, }, }, {"overlay with new directory", ` { "Replace": { - "dir/file.txt": "other.txt" + "dir/subdir/file.txt": "dir/other.txt" } } --- other.txt -- +-- dir/other.txt -- contents of other file `, - ".", + "dir", []file{ - {".", ".", 0, fs.ModeDir | 0500, true}, {"dir", "dir", 0, fs.ModeDir | 0500, true}, - {"dir" + string(filepath.Separator) + "file.txt", "file.txt", 23, 0600, false}, - {"other.txt", "other.txt", 23, 0600, false}, + {"dir/other.txt", "other.txt", 23, 0600, false}, + {"dir/subdir", "subdir", 0, fs.ModeDir | 0500, true}, + {"dir/subdir/file.txt", "file.txt", 23, 0600, false}, }, }, } @@ -576,8 +581,9 @@ contents of other file t.Errorf("Walk: saw %#v in walk; want %#v", got, tc.wantFiles) } for i := 0; i < len(got) && i < len(tc.wantFiles); i++ { - if got[i].path != tc.wantFiles[i].path { - t.Errorf("path of file #%v in walk, got %q, want %q", i, got[i].path, tc.wantFiles[i].path) + wantPath := filepath.FromSlash(tc.wantFiles[i].path) + if got[i].path != wantPath { + t.Errorf("path of file #%v in walk, got %q, want %q", i, got[i].path, wantPath) } if got[i].name != tc.wantFiles[i].name { t.Errorf("name of file #%v in walk, got %q, want %q", i, got[i].name, tc.wantFiles[i].name) @@ -603,24 +609,24 @@ func TestWalk_SkipDir(t *testing.T) { initOverlay(t, ` { "Replace": { - "skipthisdir/file.go": "dummy.txt", - "dontskip/file.go": "dummy.txt", - "dontskip/skip/file.go": "dummy.txt" + "dir/skip/file.go": "dummy.txt", + "dir/dontskip/file.go": "dummy.txt", + "dir/dontskip/skip/file.go": "dummy.txt" } } -- dummy.txt -- `) var seen []string - Walk(".", func(path string, info fs.FileInfo, err error) error { - seen = append(seen, path) - if path == "skipthisdir" || path == filepath.Join("dontskip", "skip") { + Walk("dir", func(path string, info fs.FileInfo, err error) error { + seen = append(seen, filepath.ToSlash(path)) + if info.Name() == "skip" { return filepath.SkipDir } return nil }) - wantSeen := []string{".", "dontskip", filepath.Join("dontskip", "file.go"), filepath.Join("dontskip", "skip"), "dummy.txt", "skipthisdir"} + wantSeen := []string{"dir", "dir/dontskip", "dir/dontskip/file.go", "dir/dontskip/skip", "dir/skip"} if len(seen) != len(wantSeen) { t.Errorf("paths seen in walk: got %v entries; want %v entries", len(seen), len(wantSeen)) @@ -675,8 +681,8 @@ func TestWalk_Symlink(t *testing.T) { wantFiles []string }{ {"control", "dir", []string{"dir", "dir" + string(filepath.Separator) + "file"}}, - // ensure Walk doesn't wolk into the directory pointed to by the symlink - // (because it's supposed to use Lstat instead of Stat. + // ensure Walk doesn't walk into the directory pointed to by the symlink + // (because it's supposed to use Lstat instead of Stat). {"symlink_to_dir", "symlink", []string{"symlink"}}, {"overlay_to_symlink_to_dir", "overlay_symlink", []string{"overlay_symlink"}}, } From 6f45b39e4dbabf0b179a60ffacf434e55b2d5eab Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 19 May 2020 18:55:31 +1000 Subject: [PATCH 060/403] cmd/compile,cmd/internal/obj/riscv: move g register on riscv64 The original riscv64 port used the thread pointer (TP aka X4) register for the g pointer, however this register is also used when TLS support is required, resulting in a conflict (for example, when a signal is received we have no way of readily knowing if X4 contains a pointer to the TCB or a pointer to a g). In order to support cgo, free up the X4 register by moving g to X27. This unfortunately means that the X4 register is unused in non-cgo mode, however the alternative is to not support cgo on this platform. Update #36641 Change-Id: Idcaf3e8ccbe42972a1b8943aeefde7149d9c960a Reviewed-on: https://go-review.googlesource.com/c/go/+/263477 Trust: Joel Sing Reviewed-by: Cherry Zhang --- .../compile/internal/ssa/gen/RISCV64Ops.go | 7 +- src/cmd/compile/internal/ssa/opGen.go | 406 +++++++++--------- src/cmd/internal/obj/riscv/cpu.go | 12 +- src/runtime/asm_riscv64.s | 12 +- 4 files changed, 219 insertions(+), 218 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go index b06b86075ea..fb944f31328 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/RISCV64Ops.go @@ -24,10 +24,11 @@ import ( // L = 64 bit int, used when the opcode starts with F const ( - riscv64REG_G = 4 + riscv64REG_G = 27 riscv64REG_CTXT = 20 riscv64REG_LR = 1 riscv64REG_SP = 2 + riscv64REG_TP = 4 riscv64REG_TMP = 31 riscv64REG_ZERO = 0 ) @@ -78,8 +79,8 @@ func init() { // Add general purpose registers to gpMask. switch r { - // ZERO, and TMP are not in any gp mask. - case riscv64REG_ZERO, riscv64REG_TMP: + // ZERO, TP and TMP are not in any gp mask. + case riscv64REG_ZERO, riscv64REG_TP, riscv64REG_TMP: case riscv64REG_G: gpgMask |= mask gpspsbgMask |= mask diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index eae30c79bab..e9c63cdddfe 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -27039,11 +27039,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADD, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27054,10 +27054,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADDI, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27068,10 +27068,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AADDIW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27081,10 +27081,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANEG, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27094,10 +27094,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANEGW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27107,11 +27107,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASUB, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27121,11 +27121,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASUBW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27136,11 +27136,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMUL, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27151,11 +27151,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27166,11 +27166,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULH, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27181,11 +27181,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMULHU, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27195,11 +27195,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIV, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27209,11 +27209,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVU, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27223,11 +27223,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27237,11 +27237,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ADIVUW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27251,11 +27251,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREM, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27265,11 +27265,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMU, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27279,11 +27279,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27293,11 +27293,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AREMUW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27310,10 +27310,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27325,7 +27325,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27337,7 +27337,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27349,7 +27349,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27361,7 +27361,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27374,10 +27374,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27390,10 +27390,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27406,10 +27406,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27422,10 +27422,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27438,10 +27438,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVBU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27454,10 +27454,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVHU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27470,10 +27470,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVWU, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27486,8 +27486,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27500,8 +27500,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27514,8 +27514,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27528,8 +27528,8 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27542,7 +27542,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVB, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27555,7 +27555,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVH, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27568,7 +27568,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVW, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27581,7 +27581,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27591,11 +27591,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLL, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27605,11 +27605,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRA, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27619,11 +27619,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRL, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27634,10 +27634,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLLI, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27648,10 +27648,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRAI, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27662,10 +27662,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASRLI, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27676,11 +27676,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AXOR, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27691,10 +27691,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AXORI, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27705,11 +27705,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AOR, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27720,10 +27720,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AORI, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27734,11 +27734,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.AAND, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27749,10 +27749,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AANDI, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27762,10 +27762,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ANOT, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27775,10 +27775,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASEQZ, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27788,10 +27788,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASNEZ, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27801,11 +27801,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLT, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27816,10 +27816,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTI, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27829,11 +27829,11 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTU, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27844,10 +27844,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.ASLTIU, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27857,10 +27857,10 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOV, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27870,7 +27870,7 @@ var opcodeTable = [...]opInfo{ argLen: 1, call: true, reg: regInfo{ - clobbers: 9223372035781033980, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -27881,9 +27881,9 @@ var opcodeTable = [...]opInfo{ reg: regInfo{ inputs: []inputInfo{ {1, 524288}, // X20 - {0, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, - clobbers: 9223372035781033980, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -27893,9 +27893,9 @@ var opcodeTable = [...]opInfo{ call: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, - clobbers: 9223372035781033980, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + clobbers: 9223372035781033972, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, { @@ -27906,7 +27906,7 @@ var opcodeTable = [...]opInfo{ reg: regInfo{ inputs: []inputInfo{ {0, 16}, // X5 - {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {1, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, clobbers: 16, // X5 }, @@ -27921,7 +27921,7 @@ var opcodeTable = [...]opInfo{ inputs: []inputInfo{ {0, 16}, // X5 {1, 32}, // X6 - {2, 1073741748}, // X3 X5 X6 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {2, 1006632884}, // X3 X5 X6 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, clobbers: 112, // X5 X6 X7 }, @@ -27932,10 +27932,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27945,10 +27945,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27958,10 +27958,10 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -27972,8 +27972,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27984,8 +27984,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -27996,8 +27996,8 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, }, }, @@ -28009,11 +28009,11 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517630}, // SP X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28025,11 +28025,11 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517630}, // SP X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28042,11 +28042,11 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517630}, // SP X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28059,11 +28059,11 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517630}, // SP X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28076,12 +28076,12 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {2, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517630}, // SP X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28094,12 +28094,12 @@ var opcodeTable = [...]opInfo{ unsafePoint: true, reg: regInfo{ inputs: []inputInfo{ - {1, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {2, 1073741820}, // X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 - {0, 9223372037928517630}, // SP X3 g X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {1, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {2, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 + {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 g X28 X29 X30 SB }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28110,7 +28110,7 @@ var opcodeTable = [...]opInfo{ faultOnNilArg0: true, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741814}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632950}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28129,7 +28129,7 @@ var opcodeTable = [...]opInfo{ rematerializeable: true, reg: regInfo{ outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28139,7 +28139,7 @@ var opcodeTable = [...]opInfo{ rematerializeable: true, reg: regInfo{ outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28283,7 +28283,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFMVSX, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28296,7 +28296,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTSW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28309,7 +28309,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTSL, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28325,7 +28325,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28338,7 +28338,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28351,7 +28351,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVF, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28367,7 +28367,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVF, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, @@ -28383,7 +28383,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28398,7 +28398,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28412,7 +28412,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28426,7 +28426,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28520,7 +28520,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFMVDX, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28533,7 +28533,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTDW, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28546,7 +28546,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AFCVTDL, reg: regInfo{ inputs: []inputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28562,7 +28562,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28575,7 +28575,7 @@ var opcodeTable = [...]opInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28614,7 +28614,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVD, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB }, outputs: []outputInfo{ {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 @@ -28630,7 +28630,7 @@ var opcodeTable = [...]opInfo{ asm: riscv.AMOVD, reg: regInfo{ inputs: []inputInfo{ - {0, 9223372037928517622}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 SB + {0, 9223372037861408758}, // SP X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 SB {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, }, @@ -28646,7 +28646,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28661,7 +28661,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28675,7 +28675,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -28689,7 +28689,7 @@ var opcodeTable = [...]opInfo{ {1, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 }, outputs: []outputInfo{ - {0, 1073741812}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 + {0, 1006632948}, // X3 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30 }, }, }, @@ -35931,7 +35931,7 @@ var registersRISCV64 = [...]Register{ {0, riscv.REG_X0, -1, "X0"}, {1, riscv.REGSP, -1, "SP"}, {2, riscv.REG_X3, 0, "X3"}, - {3, riscv.REGG, -1, "g"}, + {3, riscv.REG_X4, -1, "X4"}, {4, riscv.REG_X5, 1, "X5"}, {5, riscv.REG_X6, 2, "X6"}, {6, riscv.REG_X7, 3, "X7"}, @@ -35954,10 +35954,10 @@ var registersRISCV64 = [...]Register{ {23, riscv.REG_X24, 20, "X24"}, {24, riscv.REG_X25, 21, "X25"}, {25, riscv.REG_X26, 22, "X26"}, - {26, riscv.REG_X27, 23, "X27"}, - {27, riscv.REG_X28, 24, "X28"}, - {28, riscv.REG_X29, 25, "X29"}, - {29, riscv.REG_X30, 26, "X30"}, + {26, riscv.REGG, -1, "g"}, + {27, riscv.REG_X28, 23, "X28"}, + {28, riscv.REG_X29, 24, "X29"}, + {29, riscv.REG_X30, 25, "X30"}, {30, riscv.REG_X31, -1, "X31"}, {31, riscv.REG_F0, -1, "F0"}, {32, riscv.REG_F1, -1, "F1"}, @@ -35993,7 +35993,7 @@ var registersRISCV64 = [...]Register{ {62, riscv.REG_F31, -1, "F31"}, {63, 0, -1, "SB"}, } -var gpRegMaskRISCV64 = regMask(1073741812) +var gpRegMaskRISCV64 = regMask(1006632948) var fpRegMaskRISCV64 = regMask(9223372034707292160) var specialRegMaskRISCV64 = regMask(0) var framepointerRegRISCV64 = int8(-1) diff --git a/src/cmd/internal/obj/riscv/cpu.go b/src/cmd/internal/obj/riscv/cpu.go index 482f9e0b6da..b1324b62a03 100644 --- a/src/cmd/internal/obj/riscv/cpu.go +++ b/src/cmd/internal/obj/riscv/cpu.go @@ -109,7 +109,7 @@ const ( REG_RA = REG_X1 // aka REG_LR REG_SP = REG_X2 REG_GP = REG_X3 // aka REG_SB - REG_TP = REG_X4 // aka REG_G + REG_TP = REG_X4 REG_T0 = REG_X5 REG_T1 = REG_X6 REG_T2 = REG_X7 @@ -132,17 +132,17 @@ const ( REG_S8 = REG_X24 REG_S9 = REG_X25 REG_S10 = REG_X26 - REG_S11 = REG_X27 + REG_S11 = REG_X27 // aka REG_G REG_T3 = REG_X28 REG_T4 = REG_X29 REG_T5 = REG_X30 REG_T6 = REG_X31 // aka REG_TMP // Go runtime register names. - REG_G = REG_TP // G pointer. - REG_CTXT = REG_S4 // Context for closures. - REG_LR = REG_RA // Link register. - REG_TMP = REG_T6 // Reserved for assembler use. + REG_G = REG_S11 // G pointer. + REG_CTXT = REG_S4 // Context for closures. + REG_LR = REG_RA // Link register. + REG_TMP = REG_T6 // Reserved for assembler use. // ABI names for floating point registers. REG_FT0 = REG_F0 diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index 4084ced7f8b..a1360850841 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -519,12 +519,12 @@ flush: MOV T1, 16(X2) // Also second argument to wbBufFlush // TODO: Optimise - // R3 is g. - // R4 already saved (T0) - // R5 already saved (T1) - // R9 already saved (A0) - // R10 already saved (A1) - // R30 is tmp register. + // X5 already saved (T0) + // X6 already saved (T1) + // X10 already saved (A0) + // X11 already saved (A1) + // X27 is g. + // X31 is tmp register. MOV X0, 24(X2) MOV X1, 32(X2) MOV X2, 40(X2) From b04eb73a6891e81e2e611ee93b3aa8c4769d5967 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Tue, 20 Oct 2020 13:50:52 -0700 Subject: [PATCH 061/403] crypto/x509: bypass signature verification in CreateCertificate when using MD5WithRSA Bypasses the signature verification check we previously added if the signature algorithm is MD5WithRSA, as we only support this algorithm for signing and not verification. Change-Id: Idba6dbba8b365d6199d467526746b88a5f734af1 Reviewed-on: https://go-review.googlesource.com/c/go/+/264019 Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda Trust: Roland Shoemaker --- src/crypto/x509/x509.go | 8 ++++++-- src/crypto/x509/x509_test.go | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index bcef54ddb4f..b421d759732 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -2156,8 +2156,12 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv } // Check the signature to ensure the crypto.Signer behaved correctly. - if err := checkSignature(getSignatureAlgorithmFromAI(signatureAlgorithm), c.Raw, signature, key.Public()); err != nil { - return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err) + // We skip this check if the signature algorithm is MD5WithRSA as we + // only support this algorithm for signing, and not verification. + if sigAlg := getSignatureAlgorithmFromAI(signatureAlgorithm); sigAlg != MD5WithRSA { + if err := checkSignature(sigAlg, c.Raw, signature, key.Public()); err != nil { + return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err) + } } return signedCert, nil diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 5a39e61b3c2..47d78cf02af 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -2896,3 +2896,19 @@ func TestCreateCertificateBrokenSigner(t *testing.T) { t.Fatalf("CreateCertificate returned an unexpected error: got %q, want %q", err, expectedErr) } } + +func TestCreateCertificateMD5(t *testing.T) { + template := &Certificate{ + SerialNumber: big.NewInt(10), + DNSNames: []string{"example.com"}, + SignatureAlgorithm: MD5WithRSA, + } + k, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + t.Fatalf("failed to generate test key: %s", err) + } + _, err = CreateCertificate(rand.Reader, template, template, k.Public(), &brokenSigner{k.Public()}) + if err != nil { + t.Fatalf("CreateCertificate failed when SignatureAlgorithm = MD5WithRSA: %s", err) + } +} From 612a363bef9ae29d190f6daa2a5a1623f78c874b Mon Sep 17 00:00:00 2001 From: hk Date: Wed, 21 Oct 2020 16:18:34 +0000 Subject: [PATCH 062/403] cmd/compile/internal/gc: fix comments Change-Id: Id7b0ead39e961a16a85da3e308db10dd4f9b55c3 GitHub-Last-Rev: e640c4a61ade361ac17b7eb95d0ce8913d0b4d6f GitHub-Pull-Request: golang/go#42120 Reviewed-on: https://go-review.googlesource.com/c/go/+/264080 Reviewed-by: Keith Randall Trust: Cuong Manh Le --- src/cmd/compile/internal/gc/dcl.go | 2 +- src/cmd/compile/internal/gc/subr.go | 2 +- src/cmd/compile/internal/gc/syntax.go | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index a362d1a643b..b8ca0d2e033 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -283,7 +283,7 @@ func oldname(s *types.Sym) *Node { c.Name.Defn = n // Link into list of active closure variables. - // Popped from list in func closurebody. + // Popped from list in func funcLit. c.Name.Param.Outer = n.Name.Param.Innermost n.Name.Param.Innermost = c diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index f4b0c0fae04..b6e6f3a6da5 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -348,7 +348,7 @@ func newname(s *types.Sym) *Node { return n } -// newname returns a new ONAME Node associated with symbol s at position pos. +// newnamel returns a new ONAME Node associated with symbol s at position pos. // The caller is responsible for setting n.Name.Curfn. func newnamel(pos src.XPos, s *types.Sym) *Node { if s == nil { diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 4aa2e230ce2..a2ab0fa661e 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -460,14 +460,14 @@ type Param struct { // x1 := xN.Defn // x1.Innermost = xN.Outer // - // We leave xN.Innermost set so that we can still get to the original + // We leave x1.Innermost set so that we can still get to the original // variable quickly. Not shown here, but once we're // done parsing a function and no longer need xN.Outer for the - // lexical x reference links as described above, closurebody + // lexical x reference links as described above, funcLit // recomputes xN.Outer as the semantic x reference link tree, // even filling in x in intermediate closures that might not // have mentioned it along the way to inner closures that did. - // See closurebody for details. + // See funcLit for details. // // During the eventual compilation, then, for closure variables we have: // From 6af088bfc66c13143c9ef46b4cf0805df77a8fbe Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Mon, 19 Oct 2020 13:29:40 -0700 Subject: [PATCH 063/403] encoding/json: add "json: " prefix to SyntaxError messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The other named errors - UnmarshalTypeError, etc - in this package do the same, so we should prepend the package prefix to error messages for consistency. Add a note to the release docs in case this is interpreted as a breaking change. Fixes #36221. Change-Id: Ie24b532bbf9812e108c259fa377e2a6b64319ed4 Reviewed-on: https://go-review.googlesource.com/c/go/+/263619 Run-TryBot: Kevin Burke TryBot-Result: Go Bot Trust: Kevin Burke Trust: Daniel Martí Reviewed-by: Daniel Martí --- doc/go1.16.html | 8 ++++++++ src/cmd/go/testdata/script/mod_proxy_invalid.txt | 4 ++-- src/cmd/go/testdata/script/mod_query_empty.txt | 2 +- src/encoding/json/scanner.go | 2 +- src/html/template/escape_test.go | 2 +- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 2f2e395729e..b6df0487ca9 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -216,6 +216,14 @@ Do not send CLs removing the interior tags from such phrases. of a malformed certificate.

+

encoding/json

+ +

+ The error message for + SyntaxError + now begins with "json: ", matching the other errors in the package. +

+

net

diff --git a/src/cmd/go/testdata/script/mod_proxy_invalid.txt b/src/cmd/go/testdata/script/mod_proxy_invalid.txt index 6427cc1527a..b9418b4df12 100644 --- a/src/cmd/go/testdata/script/mod_proxy_invalid.txt +++ b/src/cmd/go/testdata/script/mod_proxy_invalid.txt @@ -2,7 +2,7 @@ env GO111MODULE=on env GOPROXY=$GOPROXY/invalid ! go list -m rsc.io/quote@latest -stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' +stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": json: invalid character ''i'' looking for beginning of value$' ! go list -m rsc.io/quote@1.5.2 -stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": invalid character ''i'' looking for beginning of value$' +stderr '^go list -m: rsc.io/quote@1.5.2: invalid version: invalid response from proxy "'$GOPROXY'": json: invalid character ''i'' looking for beginning of value$' diff --git a/src/cmd/go/testdata/script/mod_query_empty.txt b/src/cmd/go/testdata/script/mod_query_empty.txt index b3ea3e3de0a..a07a07c4bcc 100644 --- a/src/cmd/go/testdata/script/mod_query_empty.txt +++ b/src/cmd/go/testdata/script/mod_query_empty.txt @@ -40,7 +40,7 @@ env GOPROXY=file:///$WORK/gatekeeper chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest cp go.mod.orig go.mod ! go get -d example.com/join/subpkg -stderr 'go get example.com/join/subpkg: module example.com/join/subpkg: (invalid response from proxy ".+": invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' +stderr 'go get example.com/join/subpkg: module example.com/join/subpkg: (invalid response from proxy ".+": json: invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' -- go.mod.orig -- module example.com/othermodule diff --git a/src/encoding/json/scanner.go b/src/encoding/json/scanner.go index 9dc1903e2db..c3f5f6372db 100644 --- a/src/encoding/json/scanner.go +++ b/src/encoding/json/scanner.go @@ -47,7 +47,7 @@ type SyntaxError struct { Offset int64 // error occurred after reading Offset bytes } -func (e *SyntaxError) Error() string { return e.msg } +func (e *SyntaxError) Error() string { return "json: " + e.msg } // A scanner is a JSON scanning state machine. // Callers call scan.reset and then pass bytes in one at a time diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go index fbc84a75928..b6031ea60ac 100644 --- a/src/html/template/escape_test.go +++ b/src/html/template/escape_test.go @@ -243,7 +243,7 @@ func TestEscape(t *testing.T) { { "badMarshaler", `

Operator precedence

From 676ad56095c819751ae9f61354cf0fa356e71cb6 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 30 Oct 2020 11:35:48 -0400 Subject: [PATCH 283/403] go/types: reorganize error codes into categories In CL 264179, some reorganization of error codes was deferred in order to minimize diffs between patch-sets. This CL reorganizes the error codes as discussed. It is a pure reordering, with no material changes other than the changing of internal const values. For #42290 Change-Id: I0e9b421a92e96b19e53039652f8de898c5255290 Reviewed-on: https://go-review.googlesource.com/c/go/+/266637 Run-TryBot: Robert Findley Trust: Robert Findley Trust: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/errorcodes.go | 1726 ++++++++++++++++++------------------ 1 file changed, 859 insertions(+), 867 deletions(-) diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index 56c2995cff2..ba6e2f908bd 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -46,14 +46,42 @@ const ( // package name already established by other files. _MismatchedPkgName - /* initialization */ - - // _DuplicateDecl occurs when an identifier is declared multiple times. + // _InvalidPkgUse occurs when a package identifier is used outside of a + // selector expression. // // Example: - // var x = 1 - // var x = 2 - _DuplicateDecl + // import "fmt" + // + // var _ = fmt + _InvalidPkgUse + + /* imports */ + + // _BadImportPath occurs when an import path is not valid. + _BadImportPath + + // _BrokenImport occurs when importing a package fails. + // + // Example: + // import "amissingpackage" + _BrokenImport + + // _ImportCRenamed occurs when the special import "C" is renamed. "C" is a + // pseudo-package, and must not be renamed. + // + // Example: + // import _ "C" + _ImportCRenamed + + // _UnusedImport occurs when an import is unused. + // + // Example: + // import "fmt" + // + // func main() {} + _UnusedImport + + /* initialization */ // _InvalidInitCycle occurs when an invalid cycle is detected within the // initialization graph. @@ -64,6 +92,15 @@ const ( // func f() int { return x } _InvalidInitCycle + /* decls */ + + // _DuplicateDecl occurs when an identifier is declared multiple times. + // + // Example: + // var x = 1 + // var x = 2 + _DuplicateDecl + // _InvalidDeclCycle occurs when a declaration cycle is not valid. // // Example: @@ -76,20 +113,16 @@ const ( // var n = unsafe.Sizeof(T{}) _InvalidDeclCycle - /* consts */ - - // _TruncatedFloat occurs when a float constant is truncated to an integer - // value. + // _InvalidTypeCycle occurs when a cycle in type definitions results in a + // type that is not well-defined. // // Example: - // var _ int = 98.6 - _TruncatedFloat - - // _NumericOverflow occurs when a numeric constant overflows its target type. + // import "unsafe" // - // Example: - // var x int8 = 1000 - _NumericOverflow + // type T [unsafe.Sizeof(T{})]int + _InvalidTypeCycle + + /* decls > const */ // _InvalidConstInit occurs when a const declaration has a non-constant // initializer. @@ -113,508 +146,14 @@ const ( // const c *int = 4 _InvalidConstType - /* operators */ + /* decls > var (+ other variable assignment codes) */ - /* operators > general */ - - // _UndefinedOp occurs when an operator is not defined for the type(s) used - // in an operation. + // _UntypedNil occurs when the predeclared (untyped) value nil is used to + // initialize a variable declared without an explicit type. // // Example: - // var c = "a" - "b" - _UndefinedOp - - // _MismatchedTypes occurs when operand types are incompatible in a binary - // operation. - // - // Example: - // var a = "hello" - // var b = 1 - // var c = a - b - _MismatchedTypes - - /* operators > shift */ - - // _InvalidShiftCount occurs when the right-hand side of a shift operation is - // either non-integer, negative, or too large. - // - // Example: - // var ( - // x string - // y int = 1 << x - // ) - _InvalidShiftCount - - // _InvalidShiftOperand occurs when the shifted operand is not an integer. - // - // Example: - // var s = "hello" - // var x = s << 2 - _InvalidShiftOperand - - /* operators > chan */ - - // _InvalidReceive occurs when there is a channel receive from a value that - // is either not a channel, or is a send-only channel. - // - // Example: - // func f() { - // var x = 1 - // <-x - // } - _InvalidReceive - - // _InvalidSend occurs when there is a channel send to a value that is not a - // channel, or is a receive-only channel. - // - // Example: - // func f() { - // var x = 1 - // x <- "hello!" - // } - _InvalidSend - - /* operators > & */ - - // _UnaddressableOperand occurs when the & operator is applied to an - // unaddressable expression. - // - // Example: - // var x = &1 - _UnaddressableOperand - - /* operators > * */ - - // _InvalidIndirection occurs when a non-pointer value is indirected via the - // '*' operator. - // - // Example: - // var x int - // var y = *x - _InvalidIndirection - - /* operators > index */ - - // _NonIndexableOperand occurs when an index operation is applied to a value - // that cannot be indexed. - // - // Example: - // var x = 1 - // var y = x[1] - _NonIndexableOperand - - // _InvalidIndex occurs when an index argument is not of integer type, - // negative, or out-of-bounds. - // - // Example: - // var s = [...]int{1,2,3} - // var x = s[5] - // - // Example: - // var s = []int{1,2,3} - // var _ = s[-1] - // - // Example: - // var s = []int{1,2,3} - // var i string - // var _ = s[i] - _InvalidIndex - - // _InvalidSliceExpr occurs when a three-index slice expression (a[x:y:z]) is - // applied to a string. - // - // Example: - // var s = "hello" - // var x = s[1:2:3] - _InvalidSliceExpr - - // _SwappedSliceIndices occurs when constant indices in a slice expression - // are decreasing in value. - // - // Example: - // var _ = []int{1,2,3}[2:1] - _SwappedSliceIndices - - /* operators > slice */ - - // _NonSliceableOperand occurs when a slice operation is applied to a value - // whose type is not sliceable, or is unaddressable. - // - // Example: - // var x = [...]int{1, 2, 3}[:1] - // - // Example: - // var x = 1 - // var y = 1[:1] - _NonSliceableOperand - - /* operators > division */ - - // _DivByZero occurs when a division operation is provable at compile - // time to be a division by zero. - // - // Example: - // const divisor = 0 - // var x int = 1/divisor - _DivByZero - - /* operators > inc/dec */ - - // _NonNumericIncDec occurs when an increment or decrement operator is - // applied to a non-numeric value. - // - // Example: - // func f() { - // var c = "c" - // c++ - // } - _NonNumericIncDec - - /* offsetof */ - - // _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument - // that is not a selector expression. - // - // Example: - // import "unsafe" - // - // var x int - // var _ = unsafe.Offsetof(x) - _BadOffsetofSyntax - - // _InvalidOffsetof occurs when unsafe.Offsetof is called with a method - // selector, rather than a field selector, or when the field is embedded via - // a pointer. - // - // Per the spec: - // - // "If f is an embedded field, it must be reachable without pointer - // indirections through fields of the struct. " - // - // Example: - // import "unsafe" - // - // type T struct { f int } - // type S struct { *T } - // var s S - // var _ = unsafe.Offsetof(s.f) - // - // Example: - // import "unsafe" - // - // type S struct{} - // - // func (S) m() {} - // - // var s S - // var _ = unsafe.Offsetof(s.m) - _InvalidOffsetof - - // _UnaddressableFieldAssign occurs when trying to assign to a struct field - // in a map value. - // - // Example: - // func f() { - // m := make(map[string]struct{i int}) - // m["foo"].i = 42 - // } - _UnaddressableFieldAssign - - /* Labels */ - - // _UndeclaredLabel occurs when an undeclared label is jumped to. - // - // Example: - // func f() { - // goto L - // } - _UndeclaredLabel - - // _DuplicateLabel occurs when a label is declared more than once. - // - // Example: - // func f() int { - // L: - // L: - // return 1 - // } - _DuplicateLabel - - // _UnusedLabel occurs when a label is declared but not used. - // - // Example: - // func f() { - // L: - // } - _UnusedLabel - - // _MisplacedLabel occurs when a break or continue label is not on a for, - // switch, or select statement. - // - // Example: - // func f() { - // L: - // a := []int{1,2,3} - // for _, e := range a { - // if e > 10 { - // break L - // } - // println(a) - // } - // } - _MisplacedLabel - - // _JumpOverDecl occurs when a label jumps over a variable declaration. - // - // Example: - // func f() int { - // goto L - // x := 2 - // L: - // x++ - // return x - // } - _JumpOverDecl - - // _JumpIntoBlock occurs when a forward jump goes to a label inside a nested - // block. - // - // Example: - // func f(x int) { - // goto L - // if x > 0 { - // L: - // print("inside block") - // } - // } - _JumpIntoBlock - - /* type declarations */ - - // _DuplicateFieldAndMethod occurs when an identifier appears as both a field - // and method name. - // - // Example: - // type T struct { - // m int - // } - // - // func (T) m() {} - _DuplicateFieldAndMethod - - // _DuplicateMethod occurs when two methods on the same receiver type have - // the same name. - // - // Example: - // type T struct {} - // func (T) m() {} - // func (T) m(i int) int { return i } - _DuplicateMethod - - // _InvalidArrayLen occurs when an array length is not a constant value. - // - // Example: - // var n = 3 - // var _ = [n]int{} - _InvalidArrayLen - - // _BlankIfaceMethod occurs when a method name is '_'. - // - // Per the spec: - // "The name of each explicitly specified method must be unique and not - // blank." - // - // Example: - // type T interface { - // _(int) - // } - _BlankIfaceMethod - - // _NotAType occurs when the identifier used as the underlying type in a type - // declaration or the right-hand side of a type alias does not denote a type. - // - // Example: - // var S = 2 - // - // type T S - _NotAType - - // _IncomparableMapKey occurs when a map key type does not support the == and - // != operators. - // - // Per the spec: - // "The comparison operators == and != must be fully defined for operands of - // the key type; thus the key type must not be a function, map, or slice." - // - // Example: - // var x map[T]int - // - // type T []int - _IncomparableMapKey - - // _InvalidIfaceEmbed occurs when a non-interface type is embedded in an - // interface. - // - // Example: - // type T struct {} - // - // func (T) m() - // - // type I interface { - // T - // } - _InvalidIfaceEmbed - - // _InvalidPtrEmbed occurs when an embedded field is of the pointer form *T, - // and T itself is itself a pointer, an unsafe.Pointer, or an interface. - // - // Per the spec: - // "An embedded field must be specified as a type name T or as a pointer to - // a non-interface type name *T, and T itself may not be a pointer type." - // - // Example: - // type T *int - // - // type S struct { - // *T - // } - _InvalidPtrEmbed - - // _InvalidTypeCycle occurs when a cycle in type definitions results in a - // type that is not well-defined. - // - // Example: - // import "unsafe" - // - // type T [unsafe.Sizeof(T{})]int - _InvalidTypeCycle - - /* function declarations */ - - // _MissingInitBody occurs when an init function is missing its body. - // - // Example: - // func init() - _MissingInitBody - - // _BadRecv occurs when a method declaration does not have exactly one - // receiver parameter. - // - // Example: - // func () _() {} - _BadRecv - - // _InvalidRecv occurs when a receiver type expression is not of the form T - // or *T, or T is a pointer type. - // - // Example: - // type T struct {} - // - // func (**T) m() {} - _InvalidRecv - - // _MissingReturn occurs when a function with results is missing a return - // statement. - // - // Example: - // func f() int {} - _MissingReturn - - // _WrongResultCount occurs when a return statement returns an incorrect - // number of values. - // - // Example: - // func ReturnOne() int { - // return 1, 2 - // } - _WrongResultCount - - // _OutOfScopeResult occurs when the name of a value implicitly returned by - // an empty return statement is shadowed in a nested scope. - // - // Example: - // func factor(n int) (i int) { - // for i := 2; i < n; i++ { - // if n%i == 0 { - // return - // } - // } - // return 0 - // } - _OutOfScopeResult - - // _InvalidInitDecl occurs when init is declared as anything other than a - // function. - // - // Example: - // var init = 1 - _InvalidInitDecl - - // _InvalidMainDecl occurs when main is declared as anything other than a - // function, in a main package. - _InvalidMainDecl - - // _InvalidInitSig occurs when an init function declares parameters or - // results. - // - // Example: - // func init() int { return 1 } - _InvalidInitSig - - /* imports */ - - // _BadImportPath occurs when an import path is not valid. - _BadImportPath - - // _BrokenImport occurs when importing a package fails. - // - // Example: - // import "amissingpackage" - _BrokenImport - - // _UnusedImport occurs when an import is unused. - // - // Example: - // import "fmt" - // - // func main() {} - _UnusedImport - - // _ImportCRenamed occurs when the special import "C" is renamed. "C" is a - // pseudo-package, and must not be renamed. - // - // Example: - // import _ "C" - _ImportCRenamed - - // _UndeclaredImportedName occurs when a package-qualified identifier is - // undeclared by the imported package. - // - // Example: - // import "go/types" - // - // var _ = types.NotAnActualIdentifier - _UndeclaredImportedName - - // _UnexportedName occurs when a selector refers to an unexported identifier - // of an imported package. - // - // Example: - // import "reflect" - // - // type _ reflect.flag - _UnexportedName - - // _InvalidPkgUse occurs when a package identifier is used outside of a - // selector expression. - // - // Example: - // import "fmt" - // - // var _ = fmt - _InvalidPkgUse - - /* assignment */ + // var x = nil + _UntypedNil // _WrongAssignCount occurs when the number of values on the right-hand side // of an assignment or or initialization expression does not match the number @@ -624,23 +163,25 @@ const ( // var x = 1, 2 _WrongAssignCount - // _UntypedNil occurs when the predeclared (untyped) value nil is used to - // initialize a variable declared without an explicit type. + // _UnassignableOperand occurs when the left-hand side of an assignment is + // not assignable. // // Example: - // var x = nil - _UntypedNil - - // _TooManyValues occurs when a function returns too many values for the - // expression context in which it is used. - // - // Example: - // func ReturnTwo() (int, int) { - // return 1, 2 + // func f() { + // const c = 1 + // c = 2 // } + _UnassignableOperand + + // _NoNewVar occurs when a short variable declaration (':=') does not declare + // new variables. // - // var x = ReturnTwo() - _TooManyValues + // Example: + // func f() { + // x := 1 + // x := 2 + // } + _NoNewVar // _MultiValAssignOp occurs when an assignment operation (+=, *=, etc) does // not have single-valued left-hand or right-hand side. @@ -695,82 +236,502 @@ const ( // var _ int = x _IncompatibleAssign - /* assertions */ + // _UnaddressableFieldAssign occurs when trying to assign to a struct field + // in a map value. + // + // Example: + // func f() { + // m := make(map[string]struct{i int}) + // m["foo"].i = 42 + // } + _UnaddressableFieldAssign - // _InvalidAssert occurs when a type assertion is applied to a - // value that is not of interface type. + /* decls > type (+ other type expression codes) */ + + // _NotAType occurs when the identifier used as the underlying type in a type + // declaration or the right-hand side of a type alias does not denote a type. + // + // Example: + // var S = 2 + // + // type T S + _NotAType + + // _InvalidArrayLen occurs when an array length is not a constant value. + // + // Example: + // var n = 3 + // var _ = [n]int{} + _InvalidArrayLen + + // _BlankIfaceMethod occurs when a method name is '_'. + // + // Per the spec: + // "The name of each explicitly specified method must be unique and not + // blank." + // + // Example: + // type T interface { + // _(int) + // } + _BlankIfaceMethod + + // _IncomparableMapKey occurs when a map key type does not support the == and + // != operators. + // + // Per the spec: + // "The comparison operators == and != must be fully defined for operands of + // the key type; thus the key type must not be a function, map, or slice." + // + // Example: + // var x map[T]int + // + // type T []int + _IncomparableMapKey + + // _InvalidIfaceEmbed occurs when a non-interface type is embedded in an + // interface. + // + // Example: + // type T struct {} + // + // func (T) m() + // + // type I interface { + // T + // } + _InvalidIfaceEmbed + + // _InvalidPtrEmbed occurs when an embedded field is of the pointer form *T, + // and T itself is itself a pointer, an unsafe.Pointer, or an interface. + // + // Per the spec: + // "An embedded field must be specified as a type name T or as a pointer to + // a non-interface type name *T, and T itself may not be a pointer type." + // + // Example: + // type T *int + // + // type S struct { + // *T + // } + _InvalidPtrEmbed + + /* decls > func and method */ + + // _BadRecv occurs when a method declaration does not have exactly one + // receiver parameter. + // + // Example: + // func () _() {} + _BadRecv + + // _InvalidRecv occurs when a receiver type expression is not of the form T + // or *T, or T is a pointer type. + // + // Example: + // type T struct {} + // + // func (**T) m() {} + _InvalidRecv + + // _DuplicateFieldAndMethod occurs when an identifier appears as both a field + // and method name. + // + // Example: + // type T struct { + // m int + // } + // + // func (T) m() {} + _DuplicateFieldAndMethod + + // _DuplicateMethod occurs when two methods on the same receiver type have + // the same name. + // + // Example: + // type T struct {} + // func (T) m() {} + // func (T) m(i int) int { return i } + _DuplicateMethod + + /* decls > special */ + + // _InvalidBlank occurs when a blank identifier is used as a value or type. + // + // Per the spec: + // "The blank identifier may appear as an operand only on the left-hand side + // of an assignment." + // + // Example: + // var x = _ + _InvalidBlank + + // _InvalidIota occurs when the predeclared identifier iota is used outside + // of a constant declaration. + // + // Example: + // var x = iota + _InvalidIota + + // _MissingInitBody occurs when an init function is missing its body. + // + // Example: + // func init() + _MissingInitBody + + // _InvalidInitSig occurs when an init function declares parameters or + // results. + // + // Example: + // func init() int { return 1 } + _InvalidInitSig + + // _InvalidInitDecl occurs when init is declared as anything other than a + // function. + // + // Example: + // var init = 1 + _InvalidInitDecl + + // _InvalidMainDecl occurs when main is declared as anything other than a + // function, in a main package. + _InvalidMainDecl + + /* exprs */ + + // _TooManyValues occurs when a function returns too many values for the + // expression context in which it is used. + // + // Example: + // func ReturnTwo() (int, int) { + // return 1, 2 + // } + // + // var x = ReturnTwo() + _TooManyValues + + // _NotAnExpr occurs when a type expression is used where a value expression + // is expected. + // + // Example: + // type T struct {} + // + // func f() { + // T + // } + _NotAnExpr + + /* exprs > const */ + + // _TruncatedFloat occurs when a float constant is truncated to an integer + // value. + // + // Example: + // var _ int = 98.6 + _TruncatedFloat + + // _NumericOverflow occurs when a numeric constant overflows its target type. + // + // Example: + // var x int8 = 1000 + _NumericOverflow + + /* exprs > operation */ + + // _UndefinedOp occurs when an operator is not defined for the type(s) used + // in an operation. + // + // Example: + // var c = "a" - "b" + _UndefinedOp + + // _MismatchedTypes occurs when operand types are incompatible in a binary + // operation. + // + // Example: + // var a = "hello" + // var b = 1 + // var c = a - b + _MismatchedTypes + + // _DivByZero occurs when a division operation is provable at compile + // time to be a division by zero. + // + // Example: + // const divisor = 0 + // var x int = 1/divisor + _DivByZero + + // _NonNumericIncDec occurs when an increment or decrement operator is + // applied to a non-numeric value. + // + // Example: + // func f() { + // var c = "c" + // c++ + // } + _NonNumericIncDec + + /* exprs > ptr */ + + // _UnaddressableOperand occurs when the & operator is applied to an + // unaddressable expression. + // + // Example: + // var x = &1 + _UnaddressableOperand + + // _InvalidIndirection occurs when a non-pointer value is indirected via the + // '*' operator. + // + // Example: + // var x int + // var y = *x + _InvalidIndirection + + /* exprs > [] */ + + // _NonIndexableOperand occurs when an index operation is applied to a value + // that cannot be indexed. // // Example: // var x = 1 - // var _ = x.(float64) - _InvalidAssert + // var y = x[1] + _NonIndexableOperand - // _ImpossibleAssert occurs for a type assertion x.(T) when the value x of - // interface cannot have dynamic type T, due to a missing or mismatching - // method on T. + // _InvalidIndex occurs when an index argument is not of integer type, + // negative, or out-of-bounds. // // Example: - // type T int - // - // func (t *T) m() int { return int(*t) } - // - // type I interface { m() int } - // - // var x I - // var _ = x.(T) - _ImpossibleAssert - - /* conversions */ - - // _InvalidConversion occurs when the argument type cannot be converted to the - // target. - // - // See https://golang.org/ref/spec#Conversions for the rules of - // convertibility. + // var s = [...]int{1,2,3} + // var x = s[5] // // Example: - // var x float64 - // var _ = string(x) - _InvalidConversion + // var s = []int{1,2,3} + // var _ = s[-1] + // + // Example: + // var s = []int{1,2,3} + // var i string + // var _ = s[i] + _InvalidIndex - // _UnassignableOperand occurs when the left-hand side of an assignment is - // not assignable. + // _SwappedSliceIndices occurs when constant indices in a slice expression + // are decreasing in value. + // + // Example: + // var _ = []int{1,2,3}[2:1] + _SwappedSliceIndices + + /* operators > slice */ + + // _NonSliceableOperand occurs when a slice operation is applied to a value + // whose type is not sliceable, or is unaddressable. + // + // Example: + // var x = [...]int{1, 2, 3}[:1] + // + // Example: + // var x = 1 + // var y = 1[:1] + _NonSliceableOperand + + // _InvalidSliceExpr occurs when a three-index slice expression (a[x:y:z]) is + // applied to a string. + // + // Example: + // var s = "hello" + // var x = s[1:2:3] + _InvalidSliceExpr + + /* exprs > shift */ + + // _InvalidShiftCount occurs when the right-hand side of a shift operation is + // either non-integer, negative, or too large. + // + // Example: + // var ( + // x string + // y int = 1 << x + // ) + _InvalidShiftCount + + // _InvalidShiftOperand occurs when the shifted operand is not an integer. + // + // Example: + // var s = "hello" + // var x = s << 2 + _InvalidShiftOperand + + /* exprs > chan */ + + // _InvalidReceive occurs when there is a channel receive from a value that + // is either not a channel, or is a send-only channel. // // Example: // func f() { - // const c = 1 - // c = 2 + // var x = 1 + // <-x // } - _UnassignableOperand + _InvalidReceive - // _InvalidPostDecl occurs when there is a declaration in a for-loop post - // statement. + // _InvalidSend occurs when there is a channel send to a value that is not a + // channel, or is a receive-only channel. // // Example: // func f() { - // for i := 0; i < 10; j := 0 {} + // var x = 1 + // x <- "hello!" // } - _InvalidPostDecl + _InvalidSend - // _UnusedVar occurs when a variable is declared but unused. + /* exprs > literal */ + + // _DuplicateLitKey occurs when an index is duplicated in a slice, array, or + // map literal. // // Example: - // func f() { - // x := 1 - // } - _UnusedVar - - // _NoNewVar occurs when a short variable declaration (':=') does not declare - // new variables. + // var _ = []int{0:1, 0:2} // // Example: - // func f() { - // x := 1 - // x := 2 - // } - _NoNewVar + // var _ = map[string]int{"a": 1, "a": 2} + _DuplicateLitKey - /* dot dot dot */ + // _MissingLitKey occurs when a map literal is missing a key expression. + // + // Example: + // var _ = map[string]int{1} + _MissingLitKey + + // _InvalidLitIndex occurs when the key in a key-value element of a slice or + // array literal is not an integer constant. + // + // Example: + // var i = 0 + // var x = []string{i: "world"} + _InvalidLitIndex + + // _OversizeArrayLit occurs when an array literal exceeds its length. + // + // Example: + // var _ = [2]int{1,2,3} + _OversizeArrayLit + + // _MixedStructLit occurs when a struct literal contains a mix of positional + // and named elements. + // + // Example: + // var _ = struct{i, j int}{i: 1, 2} + _MixedStructLit + + // _InvalidStructLit occurs when a positional struct literal has an incorrect + // number of values. + // + // Example: + // var _ = struct{i, j int}{1,2,3} + _InvalidStructLit + + // _MissingLitField occurs when a struct literal refers to a field that does + // not exist on the struct type. + // + // Example: + // var _ = struct{i int}{j: 2} + _MissingLitField + + // _DuplicateLitField occurs when a struct literal contains duplicated + // fields. + // + // Example: + // var _ = struct{i int}{i: 1, i: 2} + _DuplicateLitField + + // _UnexportedLitField occurs when a positional struct literal implicitly + // assigns an unexported field of an imported type. + _UnexportedLitField + + // _InvalidLitField occurs when a field name is not a valid identifier. + // + // Example: + // var _ = struct{i int}{1: 1} + _InvalidLitField + + // _UntypedLit occurs when a composite literal omits a required type + // identifier. + // + // Example: + // type outer struct{ + // inner struct { i int } + // } + // + // var _ = outer{inner: {1}} + _UntypedLit + + // _InvalidLit occurs when a composite literal expression does not match its + // type. + // + // Example: + // type P *struct{ + // x int + // } + // var _ = P {} + _InvalidLit + + /* exprs > selector */ + + // _AmbiguousSelector occurs when a selector is ambiguous. + // + // Example: + // type E1 struct { i int } + // type E2 struct { i int } + // type T struct { E1; E2 } + // + // var x T + // var _ = x.i + _AmbiguousSelector + + // _UndeclaredImportedName occurs when a package-qualified identifier is + // undeclared by the imported package. + // + // Example: + // import "go/types" + // + // var _ = types.NotAnActualIdentifier + _UndeclaredImportedName + + // _UnexportedName occurs when a selector refers to an unexported identifier + // of an imported package. + // + // Example: + // import "reflect" + // + // type _ reflect.flag + _UnexportedName + + // _UndeclaredName occurs when an identifier is not declared in the current + // scope. + // + // Example: + // var x T + _UndeclaredName + + // _MissingFieldOrMethod occurs when a selector references a field or method + // that does not exist. + // + // Example: + // type T struct {} + // + // var x = T{}.f + _MissingFieldOrMethod + + /* exprs > ... */ + + // _BadDotDotDotSyntax occurs when a "..." occurs in a context where it is + // not valid. + // + // Example: + // var _ = map[int][...]int{0: {}} + _BadDotDotDotSyntax // _NonVariadicDotDotDot occurs when a "..." is used on the final argument to // a non-variadic function. @@ -835,91 +796,15 @@ const ( // } _InvalidDotDotDotOperand - /* selectors */ - - // _MissingFieldOrMethod occurs when a selector references a field or method - // that does not exist. + // _InvalidDotDotDot occurs when a "..." is used in a non-variadic built-in + // function. // // Example: - // type T struct {} - // - // var x = T{}.f - _MissingFieldOrMethod + // var s = []int{1, 2, 3} + // var l = len(s...) + _InvalidDotDotDot - // _AmbiguousSelector occurs when a selector is ambiguous. - // - // Example: - // type E1 struct { i int } - // type E2 struct { i int } - // type T struct { E1; E2 } - // - // var x T - // var _ = x.i - _AmbiguousSelector - - /* calls */ - - // _InvalidMethodExpr occurs when a pointer method is called but the argument - // is not addressable. - // - // Example: - // type T struct {} - // - // func (*T) m() int { return 1 } - // - // var _ = T.m(T{}) - _InvalidMethodExpr - - // _InvalidCall occurs when an expression is called that is not of function - // type. - // - // Example: - // var x = "x" - // var y = x() - _InvalidCall - - // _WrongArgCount occurs when too few or too many arguments are passed by a - // function call. - // - // Example: - // func f(i int) {} - // var x = f() - _WrongArgCount - - /* suspended calls */ - - // _InvalidDefer occurs when a deferred expression is not a function call, - // for example if the expression is a type conversion. - // - // Example: - // func f(i int) int { - // defer int32(i) - // return i - // } - _InvalidDefer - - // _InvalidGo occurs when a go expression is not a function call, for example - // if the expression is a type conversion. - // - // Example: - // func f(i int) int { - // go int32(i) - // return i - // } - _InvalidGo - - // _UnusedResults occurs when a restricted expression-only built-in function - // is suspended via go or defer. Such a suspension discards the results of - // these side-effect free built-in functions, and therefore is ineffectual. - // - // Example: - // func f(a []int) int { - // defer len(a) - // return i - // } - _UnusedResults - - /* built-in functions */ + /* exprs > built-in */ // _UncalledBuiltin occurs when a built-in function is used as a // function-valued expression, instead of being called. @@ -932,15 +817,33 @@ const ( // var _ = copy _UncalledBuiltin - // _InvalidDotDotDot occurs when a "..." is used in a non-variadic built-in - // function. + // _InvalidAppend occurs when append is called with a first argument that is + // not a slice. // // Example: - // var s = []int{1, 2, 3} - // var l = len(s...) - _InvalidDotDotDot + // var _ = append(1, 2) + _InvalidAppend - /* built-ins > copy */ + // _InvalidCap occurs when an argument to the cap built-in function is not of + // supported type. + // + // See https://golang.org/ref/spec#Length_and_capacity for information on + // which underlying types are supported as arguments to cap and len. + // + // Example: + // var s = 2 + // var x = cap(s) + _InvalidCap + + // _InvalidClose occurs when close(...) is called with an argument that is + // not of channel type, or that is a receive-only channel. + // + // Example: + // func f() { + // var x int + // close(x) + // } + _InvalidClose // _InvalidCopy occurs when the arguments are not of slice type or do not // have compatible type. @@ -956,18 +859,29 @@ const ( // } _InvalidCopy - /* built-ins > cap/len */ - - // _InvalidCap occurs when an argument to the cap built-in function is not of - // supported type. - // - // See https://golang.org/ref/spec#Length_and_capacity for information on - // which underlying types are supported as arguments to cap and len. + // _InvalidComplex occurs when the complex built-in function is called with + // arguments with incompatible types. // // Example: - // var s = 2 - // var x = cap(s) - _InvalidCap + // var _ = complex(float32(1), float64(2)) + _InvalidComplex + + // _InvalidDelete occurs when the delete built-in function is called with a + // first argument that is not a map. + // + // Example: + // func f() { + // m := "hello" + // delete(m, "e") + // } + _InvalidDelete + + // _InvalidImag occurs when the imag built-in function is called with an + // argument that does not have complex type. + // + // Example: + // var _ = imag(int(1)) + _InvalidImag // _InvalidLen occurs when an argument to the len built-in function is not of // supported type. @@ -980,20 +894,6 @@ const ( // var x = len(s) _InvalidLen - /* built-ins > close */ - - // _InvalidClose occurs when close(...) is called with an argument that is - // not of channel type, or that is a receive-only channel. - // - // Example: - // func f() { - // var x int - // close(x) - // } - _InvalidClose - - /* built-ins > make */ - // _SwappedMakeArgs occurs when make is called with three arguments, and its // length argument is larger than its capacity argument. // @@ -1010,27 +910,6 @@ const ( // var x = make(int) _InvalidMake - /* built-ins > delete */ - - // _InvalidDelete occurs when the delete built-in function is called with a - // first argument that is not a map. - // - // Example: - // func f() { - // m := "hello" - // delete(m, "e") - // } - _InvalidDelete - - /* built-ins > complex/imag/real */ - - // _InvalidImag occurs when the imag built-in function is called with an - // argument that does not have complex type. - // - // Example: - // var _ = imag(int(1)) - _InvalidImag - // _InvalidReal occurs when the real built-in function is called with an // argument that does not have complex type. // @@ -1038,111 +917,199 @@ const ( // var _ = real(int(1)) _InvalidReal - // _InvalidComplex occurs when the complex built-in function is called with - // arguments with incompatible types. + /* exprs > assertion */ + + // _InvalidAssert occurs when a type assertion is applied to a + // value that is not of interface type. // // Example: - // var _ = complex(float32(1), float64(2)) - _InvalidComplex + // var x = 1 + // var _ = x.(float64) + _InvalidAssert - /* built-ins > append */ - - // _InvalidAppend occurs when append is called with a first argument that is - // not a slice. + // _ImpossibleAssert occurs for a type assertion x.(T) when the value x of + // interface cannot have dynamic type T, due to a missing or mismatching + // method on T. // // Example: - // var _ = append(1, 2) - _InvalidAppend + // type T int + // + // func (t *T) m() int { return int(*t) } + // + // type I interface { m() int } + // + // var x I + // var _ = x.(T) + _ImpossibleAssert - /* literals */ + /* exprs > conversion */ - // _InvalidLitIndex occurs when the key in a key-value element of a slice or - // array literal is not an integer constant. + // _InvalidConversion occurs when the argument type cannot be converted to the + // target. + // + // See https://golang.org/ref/spec#Conversions for the rules of + // convertibility. // // Example: - // var i = 0 - // var x = []string{i: "world"} - _InvalidLitIndex + // var x float64 + // var _ = string(x) + _InvalidConversion - // _OversizeArrayLit occurs when an array literal exceeds its length. + // _InvalidUntypedConversion occurs when an there is no valid implicit + // conversion from an untyped value satisfying the type constraints of the + // context in which it is used. // // Example: - // var _ = [2]int{1,2,3} - _OversizeArrayLit + // var _ = 1 + "" + _InvalidUntypedConversion - // _DuplicateLitKey occurs when an index is duplicated in a slice, array, or - // map literal. + /* offsetof */ + + // _BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument + // that is not a selector expression. // // Example: - // var _ = []int{0:1, 0:2} + // import "unsafe" + // + // var x int + // var _ = unsafe.Offsetof(x) + _BadOffsetofSyntax + + // _InvalidOffsetof occurs when unsafe.Offsetof is called with a method + // selector, rather than a field selector, or when the field is embedded via + // a pointer. + // + // Per the spec: + // + // "If f is an embedded field, it must be reachable without pointer + // indirections through fields of the struct. " // // Example: - // var _ = map[string]int{"a": 1, "a": 2} - _DuplicateLitKey - - // _BadDotDotDotSyntax occurs when a "..." occurs in a context where it is - // not valid. + // import "unsafe" + // + // type T struct { f int } + // type S struct { *T } + // var s S + // var _ = unsafe.Offsetof(s.f) // // Example: - // var _ = map[int][...]int{0: {}} - _BadDotDotDotSyntax + // import "unsafe" + // + // type S struct{} + // + // func (S) m() {} + // + // var s S + // var _ = unsafe.Offsetof(s.m) + _InvalidOffsetof - // _MissingLitKey occurs when a map literal is missing a key expression. + /* control flow > scope */ + + // _UnusedExpr occurs when a side-effect free expression is used as a + // statement. Such a statement has no effect. // // Example: - // var _ = map[string]int{1} - _MissingLitKey + // func f(i int) { + // i*i + // } + _UnusedExpr - // _InvalidStructLit occurs when a positional struct literal has an incorrect + // _UnusedVar occurs when a variable is declared but unused. + // + // Example: + // func f() { + // x := 1 + // } + _UnusedVar + + // _MissingReturn occurs when a function with results is missing a return + // statement. + // + // Example: + // func f() int {} + _MissingReturn + + // _WrongResultCount occurs when a return statement returns an incorrect // number of values. // // Example: - // var _ = struct{i, j int}{1,2,3} - _InvalidStructLit - - // _UntypedLit occurs when a composite literal omits a required type - // identifier. - // - // Example: - // type outer struct{ - // inner struct { i int } + // func ReturnOne() int { + // return 1, 2 // } - // - // var _ = outer{inner: {1}} - _UntypedLit + _WrongResultCount - // _MixedStructLit occurs when a struct literal contains a mix of positional - // and named elements. + // _OutOfScopeResult occurs when the name of a value implicitly returned by + // an empty return statement is shadowed in a nested scope. // // Example: - // var _ = struct{i, j int}{i: 1, 2} - _MixedStructLit + // func factor(n int) (i int) { + // for i := 2; i < n; i++ { + // if n%i == 0 { + // return + // } + // } + // return 0 + // } + _OutOfScopeResult - // _InvalidLitField occurs when a field name is not a valid identifier. + /* control flow > if */ + + // _InvalidCond occurs when an if condition is not a boolean expression. // // Example: - // var _ = struct{i int}{1: 1} - _InvalidLitField + // func checkReturn(i int) { + // if i { + // panic("non-zero return") + // } + // } + _InvalidCond - // _MissingLitField occurs when a struct literal refers to a field that does - // not exist on the struct type. + /* control flow > for */ + + // _InvalidPostDecl occurs when there is a declaration in a for-loop post + // statement. // // Example: - // var _ = struct{i int}{j: 2} - _MissingLitField + // func f() { + // for i := 0; i < 10; j := 0 {} + // } + _InvalidPostDecl - // _DuplicateLitField occurs when a struct literal contains duplicated - // fields. + // _InvalidChanRange occurs when a send-only channel used in a range + // expression. // // Example: - // var _ = struct{i int}{i: 1, i: 2} - _DuplicateLitField + // func sum(c chan<- int) { + // s := 0 + // for i := range c { + // s += i + // } + // } + _InvalidChanRange - // _UnexportedLitField occurs when a positional struct literal implicitly - // assigns an unexported field of an imported type. - _UnexportedLitField + // _InvalidIterVar occurs when two iteration variables are used while ranging + // over a channel. + // + // Example: + // func f(c chan int) { + // for k, v := range c { + // println(k, v) + // } + // } + _InvalidIterVar - /* control flow */ + // _InvalidRangeExpr occurs when the type of a range expression is not array, + // slice, string, map, or channel. + // + // Example: + // func f(i int) { + // for j := range i { + // println(j) + // } + // } + _InvalidRangeExpr + + /* control flow > switch */ // _MisplacedBreak occurs when a break statement is not within a for, switch, // or select statement of the innermost function definition. @@ -1228,49 +1195,16 @@ const ( // var _ = t.(type) _BadTypeKeyword - // _InvalidCond occurs when an if condition is not a boolean expression. - // - // Example: - // func checkReturn(i int) { - // if i { - // panic("non-zero return") - // } - // } - _InvalidCond - - // _InvalidChanRange occurs when a send-only channel used in a range - // expression. - // - // Example: - // func sum(c chan<- int) { - // s := 0 - // for i := range c { - // s += i - // } - // } - _InvalidChanRange - - // _InvalidIterVar occurs when two iteration variables are used while ranging - // over a channel. - // - // Example: - // func f(c chan int) { - // for k, v := range c { - // println(k, v) - // } - // } - _InvalidIterVar - - // _InvalidRangeExpr occurs when the type of a range expression is not array, - // slice, string, map, or channel. + // _InvalidTypeSwitch occurs when .(type) is used on an expression that is + // not of interface type. // // Example: // func f(i int) { - // for j := range i { - // println(j) - // } + // switch x := i.(type) {} // } - _InvalidRangeExpr + _InvalidTypeSwitch + + /* control flow > select */ // _InvalidSelectCase occurs when a select case is not a channel send or // receive. @@ -1286,76 +1220,134 @@ const ( // } _InvalidSelectCase - // _InvalidTypeSwitch occurs when .(type) is used on an expression that is - // not of interface type. + /* control flow > labels and jumps */ + + // _UndeclaredLabel occurs when an undeclared label is jumped to. // // Example: - // func f(i int) { - // switch x := i.(type) {} + // func f() { + // goto L // } - _InvalidTypeSwitch + _UndeclaredLabel - // _InvalidLit occurs when a composite literal expression does not match its - // type. + // _DuplicateLabel occurs when a label is declared more than once. // // Example: - // type P *struct{ - // x int + // func f() int { + // L: + // L: + // return 1 // } - // var _ = P {} - _InvalidLit + _DuplicateLabel - /* miscellaneous codes */ + // _MisplacedLabel occurs when a break or continue label is not on a for, + // switch, or select statement. + // + // Example: + // func f() { + // L: + // a := []int{1,2,3} + // for _, e := range a { + // if e > 10 { + // break L + // } + // println(a) + // } + // } + _MisplacedLabel - // _NotAnExpr occurs when a type expression is used where a value expression - // is expected. + // _UnusedLabel occurs when a label is declared but not used. + // + // Example: + // func f() { + // L: + // } + _UnusedLabel + + // _JumpOverDecl occurs when a label jumps over a variable declaration. + // + // Example: + // func f() int { + // goto L + // x := 2 + // L: + // x++ + // return x + // } + _JumpOverDecl + + // _JumpIntoBlock occurs when a forward jump goes to a label inside a nested + // block. + // + // Example: + // func f(x int) { + // goto L + // if x > 0 { + // L: + // print("inside block") + // } + // } + _JumpIntoBlock + + /* control flow > calls */ + + // _InvalidMethodExpr occurs when a pointer method is called but the argument + // is not addressable. // // Example: // type T struct {} // - // func f() { - // T + // func (*T) m() int { return 1 } + // + // var _ = T.m(T{}) + _InvalidMethodExpr + + // _WrongArgCount occurs when too few or too many arguments are passed by a + // function call. + // + // Example: + // func f(i int) {} + // var x = f() + _WrongArgCount + + // _InvalidCall occurs when an expression is called that is not of function + // type. + // + // Example: + // var x = "x" + // var y = x() + _InvalidCall + + /* control flow > suspended */ + + // _UnusedResults occurs when a restricted expression-only built-in function + // is suspended via go or defer. Such a suspension discards the results of + // these side-effect free built-in functions, and therefore is ineffectual. + // + // Example: + // func f(a []int) int { + // defer len(a) + // return i // } - _NotAnExpr + _UnusedResults - // _UnusedExpr occurs when a side-effect free expression is used as a - // statement. Such a statement has no effect. + // _InvalidDefer occurs when a deferred expression is not a function call, + // for example if the expression is a type conversion. // // Example: - // func f(i int) { - // i*i + // func f(i int) int { + // defer int32(i) + // return i // } - _UnusedExpr + _InvalidDefer - // _UndeclaredName occurs when an identifier is not declared in the current - // scope. + // _InvalidGo occurs when a go expression is not a function call, for example + // if the expression is a type conversion. // // Example: - // var x T - _UndeclaredName - - // _InvalidBlank occurs when a blank identifier is used as a value or type. - // - // Per the spec: - // "The blank identifier may appear as an operand only on the left-hand side - // of an assignment." - // - // Example: - // var x = _ - _InvalidBlank - - // _InvalidIota occurs when the predeclared identifier iota is used outside - // of a constant declaration. - // - // Example: - // var x = iota - _InvalidIota - - // _InvalidUntypedConversion occurs when an there is no valid implicit - // conversion from an untyped value satisfying the type constraints of the - // context in which it is used. - // - // Example: - // var _ = 1 + "" - _InvalidUntypedConversion + // func f(i int) int { + // go int32(i) + // return i + // } + _InvalidGo ) From 1af388f1c0a3f61903ea55098c135d153aac5ae7 Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Thu, 29 Oct 2020 12:03:18 +0100 Subject: [PATCH 284/403] cmd/compile: replace int32(a.Off()) calls with a.Off32() Change-Id: Ib833954e8400a63624359a81f5196ca9080199a3 Reviewed-on: https://go-review.googlesource.com/c/go/+/266081 Trust: Alberto Donizetti Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/ssa/gen/386.rules | 16 +++++------ src/cmd/compile/internal/ssa/rewrite386.go | 32 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules index 36a66d6bf11..537705c6819 100644 --- a/src/cmd/compile/internal/ssa/gen/386.rules +++ b/src/cmd/compile/internal/ssa/gen/386.rules @@ -993,49 +993,49 @@ && x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x) - => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p mem) + => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem) (MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem)) && x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x) - => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p mem) + => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem) (MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem)) && x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x) - => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p0 mem) + => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem) (MOVBstoreconst [a] {s} p0 x:(MOVBstoreconst [c] {s} p1 mem)) && x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x) - => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p0 mem) + => (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem) (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) && x.Uses == 1 && a.Off() + 2 == c.Off() && clobber(x) - => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p mem) + => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem) (MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem)) && x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p mem) + => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem) (MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem)) && x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x) - => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p0 mem) + => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem) (MOVWstoreconst [a] {s} p0 x:(MOVWstoreconst [c] {s} p1 mem)) && x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x) - => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p0 mem) + => (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem) // Combine stores into larger (unaligned) stores. (MOVBstore [i] {s} p (SHR(W|L)const [8] w) x:(MOVBstore [i-1] {s} p w mem)) diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go index b75dcc98fa6..eca4817b9bd 100644 --- a/src/cmd/compile/internal/ssa/rewrite386.go +++ b/src/cmd/compile/internal/ssa/rewrite386.go @@ -4074,7 +4074,7 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { } // match: (MOVBstoreconst [c] {s} p x:(MOVBstoreconst [a] {s} p mem)) // cond: x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x) - // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p mem) + // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem) for { c := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -4092,14 +4092,14 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { break } v.reset(Op386MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p, mem) return true } // match: (MOVBstoreconst [a] {s} p x:(MOVBstoreconst [c] {s} p mem)) // cond: x.Uses == 1 && a.Off() + 1 == c.Off() && clobber(x) - // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p mem) + // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p mem) for { a := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -4117,14 +4117,14 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { break } v.reset(Op386MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p, mem) return true } // match: (MOVBstoreconst [c] {s} p1 x:(MOVBstoreconst [a] {s} p0 mem)) // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x) - // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p0 mem) + // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem) for { c := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -4143,14 +4143,14 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { break } v.reset(Op386MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p0, mem) return true } // match: (MOVBstoreconst [a] {s} p0 x:(MOVBstoreconst [c] {s} p1 mem)) // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 1) && clobber(x) - // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), int32(a.Off()))] {s} p0 mem) + // result: (MOVWstoreconst [makeValAndOff32(int32(a.Val()&0xff | c.Val()<<8), a.Off32())] {s} p0 mem) for { a := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -4169,7 +4169,7 @@ func rewriteValue386_Op386MOVBstoreconst(v *Value) bool { break } v.reset(Op386MOVWstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xff|c.Val()<<8), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p0, mem) return true @@ -5474,7 +5474,7 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { } // match: (MOVWstoreconst [c] {s} p x:(MOVWstoreconst [a] {s} p mem)) // cond: x.Uses == 1 && a.Off() + 2 == c.Off() && clobber(x) - // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p mem) + // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem) for { c := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -5492,14 +5492,14 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { break } v.reset(Op386MOVLstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p, mem) return true } // match: (MOVWstoreconst [a] {s} p x:(MOVWstoreconst [c] {s} p mem)) // cond: x.Uses == 1 && ValAndOff(a).Off() + 2 == ValAndOff(c).Off() && clobber(x) - // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p mem) + // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p mem) for { a := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -5517,14 +5517,14 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { break } v.reset(Op386MOVLstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p, mem) return true } // match: (MOVWstoreconst [c] {s} p1 x:(MOVWstoreconst [a] {s} p0 mem)) // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x) - // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p0 mem) + // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem) for { c := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -5543,14 +5543,14 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { break } v.reset(Op386MOVLstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p0, mem) return true } // match: (MOVWstoreconst [a] {s} p0 x:(MOVWstoreconst [c] {s} p1 mem)) // cond: x.Uses == 1 && a.Off() == c.Off() && sequentialAddresses(p0, p1, 2) && clobber(x) - // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), int32(a.Off()))] {s} p0 mem) + // result: (MOVLstoreconst [makeValAndOff32(int32(a.Val()&0xffff | c.Val()<<16), a.Off32())] {s} p0 mem) for { a := auxIntToValAndOff(v.AuxInt) s := auxToSym(v.Aux) @@ -5569,7 +5569,7 @@ func rewriteValue386_Op386MOVWstoreconst(v *Value) bool { break } v.reset(Op386MOVLstoreconst) - v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), int32(a.Off()))) + v.AuxInt = valAndOffToAuxInt(makeValAndOff32(int32(a.Val()&0xffff|c.Val()<<16), a.Off32())) v.Aux = symToAux(s) v.AddArg2(p0, mem) return true From a313eec3869c609c0da2402a4cac2d32113d599c Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Wed, 14 Oct 2020 08:36:11 -0400 Subject: [PATCH 285/403] reflect,runtime: use internal ABI for selected ASM routines, attempt 2 [This is a roll-forward of CL 262319, with a fix for some Darwin test failures]. Change the definitions of selected runtime assembly routines from ABI0 (the default) to ABIInternal. The ABIInternal def is intended to indicate that these functions don't follow the existing Go runtime ABI. In addition, convert the assembly reference to runtime.main (from runtime.mainPC) to ABIInternal. Finally, for functions such as "runtime.duffzero" that are called directly from generated code, make sure that the compiler looks up the correct ABI version. This is intended to support the register abi work, however these changes should not have any issues even when GOEXPERIMENT=regabi is not in effect. Updates #27539, #40724. Change-Id: Idf507f1c06176073563845239e1a54dad51a9ea9 Reviewed-on: https://go-review.googlesource.com/c/go/+/266638 Trust: Than McIntosh Run-TryBot: Than McIntosh Reviewed-by: Cherry Zhang TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/ssa.go | 86 ++++++++++++------------- src/cmd/internal/obj/wasm/wasmobj.go | 6 +- src/cmd/internal/obj/x86/obj6.go | 4 +- src/reflect/asm_amd64.s | 12 ++-- src/runtime/asm_amd64.s | 96 +++++++++++++++++----------- src/runtime/asm_wasm.s | 4 +- src/runtime/duff_amd64.s | 4 +- src/runtime/mkpreempt.go | 3 +- src/runtime/preempt_386.s | 3 +- src/runtime/preempt_amd64.s | 3 +- src/runtime/preempt_arm.s | 3 +- src/runtime/preempt_arm64.s | 3 +- src/runtime/preempt_mips64x.s | 3 +- src/runtime/preempt_mipsx.s | 3 +- src/runtime/preempt_ppc64x.s | 3 +- src/runtime/preempt_riscv64.s | 3 +- src/runtime/preempt_s390x.s | 3 +- src/runtime/preempt_wasm.s | 3 +- src/runtime/race_amd64.s | 12 +++- src/runtime/sys_linux_amd64.s | 13 ++-- 20 files changed, 156 insertions(+), 114 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 45d628cc5e8..7388e4e3e83 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -72,9 +72,9 @@ func initssaconfig() { deferproc = sysfunc("deferproc") deferprocStack = sysfunc("deferprocStack") Deferreturn = sysfunc("deferreturn") - Duffcopy = sysvar("duffcopy") // asm func with special ABI - Duffzero = sysvar("duffzero") // asm func with special ABI - gcWriteBarrier = sysvar("gcWriteBarrier") // asm func with special ABI + Duffcopy = sysfunc("duffcopy") + Duffzero = sysfunc("duffzero") + gcWriteBarrier = sysfunc("gcWriteBarrier") goschedguarded = sysfunc("goschedguarded") growslice = sysfunc("growslice") msanread = sysfunc("msanread") @@ -105,51 +105,51 @@ func initssaconfig() { // asm funcs with special ABI if thearch.LinkArch.Name == "amd64" { GCWriteBarrierReg = map[int16]*obj.LSym{ - x86.REG_AX: sysvar("gcWriteBarrier"), - x86.REG_CX: sysvar("gcWriteBarrierCX"), - x86.REG_DX: sysvar("gcWriteBarrierDX"), - x86.REG_BX: sysvar("gcWriteBarrierBX"), - x86.REG_BP: sysvar("gcWriteBarrierBP"), - x86.REG_SI: sysvar("gcWriteBarrierSI"), - x86.REG_R8: sysvar("gcWriteBarrierR8"), - x86.REG_R9: sysvar("gcWriteBarrierR9"), + x86.REG_AX: sysfunc("gcWriteBarrier"), + x86.REG_CX: sysfunc("gcWriteBarrierCX"), + x86.REG_DX: sysfunc("gcWriteBarrierDX"), + x86.REG_BX: sysfunc("gcWriteBarrierBX"), + x86.REG_BP: sysfunc("gcWriteBarrierBP"), + x86.REG_SI: sysfunc("gcWriteBarrierSI"), + x86.REG_R8: sysfunc("gcWriteBarrierR8"), + x86.REG_R9: sysfunc("gcWriteBarrierR9"), } } if thearch.LinkArch.Family == sys.Wasm { - BoundsCheckFunc[ssa.BoundsIndex] = sysvar("goPanicIndex") - BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("goPanicIndexU") - BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("goPanicSliceAlen") - BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("goPanicSliceAlenU") - BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("goPanicSliceAcap") - BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("goPanicSliceAcapU") - BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("goPanicSliceB") - BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("goPanicSliceBU") - BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("goPanicSlice3Alen") - BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("goPanicSlice3AlenU") - BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("goPanicSlice3Acap") - BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("goPanicSlice3AcapU") - BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("goPanicSlice3B") - BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("goPanicSlice3BU") - BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("goPanicSlice3C") - BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("goPanicSlice3CU") + BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("goPanicIndex") + BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("goPanicIndexU") + BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("goPanicSliceAlen") + BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("goPanicSliceAlenU") + BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("goPanicSliceAcap") + BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("goPanicSliceAcapU") + BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("goPanicSliceB") + BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("goPanicSliceBU") + BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("goPanicSlice3Alen") + BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("goPanicSlice3AlenU") + BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("goPanicSlice3Acap") + BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("goPanicSlice3AcapU") + BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("goPanicSlice3B") + BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("goPanicSlice3BU") + BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("goPanicSlice3C") + BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("goPanicSlice3CU") } else { - BoundsCheckFunc[ssa.BoundsIndex] = sysvar("panicIndex") - BoundsCheckFunc[ssa.BoundsIndexU] = sysvar("panicIndexU") - BoundsCheckFunc[ssa.BoundsSliceAlen] = sysvar("panicSliceAlen") - BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysvar("panicSliceAlenU") - BoundsCheckFunc[ssa.BoundsSliceAcap] = sysvar("panicSliceAcap") - BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysvar("panicSliceAcapU") - BoundsCheckFunc[ssa.BoundsSliceB] = sysvar("panicSliceB") - BoundsCheckFunc[ssa.BoundsSliceBU] = sysvar("panicSliceBU") - BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysvar("panicSlice3Alen") - BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysvar("panicSlice3AlenU") - BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysvar("panicSlice3Acap") - BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysvar("panicSlice3AcapU") - BoundsCheckFunc[ssa.BoundsSlice3B] = sysvar("panicSlice3B") - BoundsCheckFunc[ssa.BoundsSlice3BU] = sysvar("panicSlice3BU") - BoundsCheckFunc[ssa.BoundsSlice3C] = sysvar("panicSlice3C") - BoundsCheckFunc[ssa.BoundsSlice3CU] = sysvar("panicSlice3CU") + BoundsCheckFunc[ssa.BoundsIndex] = sysfunc("panicIndex") + BoundsCheckFunc[ssa.BoundsIndexU] = sysfunc("panicIndexU") + BoundsCheckFunc[ssa.BoundsSliceAlen] = sysfunc("panicSliceAlen") + BoundsCheckFunc[ssa.BoundsSliceAlenU] = sysfunc("panicSliceAlenU") + BoundsCheckFunc[ssa.BoundsSliceAcap] = sysfunc("panicSliceAcap") + BoundsCheckFunc[ssa.BoundsSliceAcapU] = sysfunc("panicSliceAcapU") + BoundsCheckFunc[ssa.BoundsSliceB] = sysfunc("panicSliceB") + BoundsCheckFunc[ssa.BoundsSliceBU] = sysfunc("panicSliceBU") + BoundsCheckFunc[ssa.BoundsSlice3Alen] = sysfunc("panicSlice3Alen") + BoundsCheckFunc[ssa.BoundsSlice3AlenU] = sysfunc("panicSlice3AlenU") + BoundsCheckFunc[ssa.BoundsSlice3Acap] = sysfunc("panicSlice3Acap") + BoundsCheckFunc[ssa.BoundsSlice3AcapU] = sysfunc("panicSlice3AcapU") + BoundsCheckFunc[ssa.BoundsSlice3B] = sysfunc("panicSlice3B") + BoundsCheckFunc[ssa.BoundsSlice3BU] = sysfunc("panicSlice3BU") + BoundsCheckFunc[ssa.BoundsSlice3C] = sysfunc("panicSlice3C") + BoundsCheckFunc[ssa.BoundsSlice3CU] = sysfunc("panicSlice3CU") } if thearch.LinkArch.PtrSize == 4 { ExtendCheckFunc[ssa.BoundsIndex] = sysvar("panicExtendIndex") diff --git a/src/cmd/internal/obj/wasm/wasmobj.go b/src/cmd/internal/obj/wasm/wasmobj.go index f7f66a1255b..2e9890d86c0 100644 --- a/src/cmd/internal/obj/wasm/wasmobj.go +++ b/src/cmd/internal/obj/wasm/wasmobj.go @@ -129,7 +129,6 @@ var ( morestackNoCtxt *obj.LSym gcWriteBarrier *obj.LSym sigpanic *obj.LSym - sigpanic0 *obj.LSym deferreturn *obj.LSym jmpdefer *obj.LSym ) @@ -142,9 +141,8 @@ const ( func instinit(ctxt *obj.Link) { morestack = ctxt.Lookup("runtime.morestack") morestackNoCtxt = ctxt.Lookup("runtime.morestack_noctxt") - gcWriteBarrier = ctxt.Lookup("runtime.gcWriteBarrier") + gcWriteBarrier = ctxt.LookupABI("runtime.gcWriteBarrier", obj.ABIInternal) sigpanic = ctxt.LookupABI("runtime.sigpanic", obj.ABIInternal) - sigpanic0 = ctxt.LookupABI("runtime.sigpanic", 0) // sigpanic called from assembly, which has ABI0 deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal) // jmpdefer is defined in assembly as ABI0, but what we're // looking for is the *call* to jmpdefer from the Go function @@ -493,7 +491,7 @@ func preprocess(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) { } // return value of call is on the top of the stack, indicating whether to unwind the WebAssembly stack - if call.As == ACALLNORESUME && call.To.Sym != sigpanic && call.To.Sym != sigpanic0 { // sigpanic unwinds the stack, but it never resumes + if call.As == ACALLNORESUME && call.To.Sym != sigpanic { // sigpanic unwinds the stack, but it never resumes // trying to unwind WebAssembly stack but call has no resume point, terminate with error p = appendp(p, AIf) p = appendp(p, obj.AUNDEF) diff --git a/src/cmd/internal/obj/x86/obj6.go b/src/cmd/internal/obj/x86/obj6.go index e11fa13f65d..184fb4308bd 100644 --- a/src/cmd/internal/obj/x86/obj6.go +++ b/src/cmd/internal/obj/x86/obj6.go @@ -324,9 +324,9 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) { // flags and duffzero on 386 does not otherwise do so). var sym *obj.LSym if p.As == obj.ADUFFZERO { - sym = ctxt.Lookup("runtime.duffzero") + sym = ctxt.LookupABI("runtime.duffzero", obj.ABIInternal) } else { - sym = ctxt.Lookup("runtime.duffcopy") + sym = ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal) } offset := p.To.Offset p.As = mov diff --git a/src/reflect/asm_amd64.s b/src/reflect/asm_amd64.s index fb28ab87f11..5c8e56558c2 100644 --- a/src/reflect/asm_amd64.s +++ b/src/reflect/asm_amd64.s @@ -9,7 +9,9 @@ // See the comment on the declaration of makeFuncStub in makefunc.go // for more details. // No arg size here; runtime pulls arg map out of the func value. -TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32 +// makeFuncStub must be ABIInternal because it is placed directly +// in function values. +TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32 NO_LOCAL_POINTERS MOVQ DX, 0(SP) LEAQ argframe+0(FP), CX @@ -17,14 +19,16 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$32 MOVB $0, 24(SP) LEAQ 24(SP), AX MOVQ AX, 16(SP) - CALL ·callReflect(SB) + CALL ·callReflect(SB) RET // methodValueCall is the code half of the function returned by makeMethodValue. // See the comment on the declaration of methodValueCall in makefunc.go // for more details. // No arg size here; runtime pulls arg map out of the func value. -TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32 +// methodValueCall must be ABIInternal because it is placed directly +// in function values. +TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32 NO_LOCAL_POINTERS MOVQ DX, 0(SP) LEAQ argframe+0(FP), CX @@ -32,5 +36,5 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$32 MOVB $0, 24(SP) LEAQ 24(SP), AX MOVQ AX, 16(SP) - CALL ·callMethod(SB) + CALL ·callMethod(SB) RET diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 19a3bb2d7d3..196252e1dd9 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -84,7 +84,9 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8 DATA _rt0_amd64_lib_argv<>(SB)/8, $0 GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8 -TEXT runtime·rt0_go(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stack-based Go ABI (and +// in addition there are no calls to this entry point from Go code). +TEXT runtime·rt0_go(SB),NOSPLIT,$0 // copy arguments forward on an even stack MOVQ DI, AX // argc MOVQ SI, BX // argv @@ -229,10 +231,13 @@ ok: // Prevent dead-code elimination of debugCallV1, which is // intended to be called by debuggers. - MOVQ $runtime·debugCallV1(SB), AX + MOVQ $runtime·debugCallV1(SB), AX RET -DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) +// mainPC is a function value for runtime.main, to be passed to newproc. +// The reference to runtime.main is made via ABIInternal, since the +// actual function (not the ABI0 wrapper) is needed by newproc. +DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) GLOBL runtime·mainPC(SB),RODATA,$8 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0 @@ -468,7 +473,7 @@ TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0 JMP AX // Note: can't just "JMP NAME(SB)" - bad inlining results. -TEXT ·reflectcall(SB), NOSPLIT, $0-32 +TEXT ·reflectcall(SB), NOSPLIT, $0-32 MOVLQZX argsize+24(FP), CX DISPATCH(runtime·call16, 16) DISPATCH(runtime·call32, 32) @@ -1354,8 +1359,11 @@ TEXT _cgo_topofstack(SB),NOSPLIT,$0 RET // The top-most function running on a goroutine -// returns to goexit+PCQuantum. -TEXT runtime·goexit(SB),NOSPLIT,$0-0 +// returns to goexit+PCQuantum. Defined as ABIInternal +// so as to make it identifiable to traceback (this +// function it used as a sentinel; traceback wants to +// see the func PC, not a wrapper PC). +TEXT runtime·goexit(SB),NOSPLIT,$0-0 BYTE $0x90 // NOP CALL runtime·goexit1(SB) // does not return // traceback from goexit1 must hit code range of goexit @@ -1377,7 +1385,8 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 // - AX is the value being written at DI // It clobbers FLAGS. It does not clobber any general-purpose registers, // but may clobber others (e.g., SSE registers). -TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120 +// Defined as ABIInternal since it does not use the stack-based Go ABI. +TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$120 // Save the registers clobbered by the fast path. This is slightly // faster than having the caller spill these. MOVQ R14, 104(SP) @@ -1461,51 +1470,58 @@ flush: JMP ret // gcWriteBarrierCX is gcWriteBarrier, but with args in DI and CX. -TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stable Go ABI. +TEXT runtime·gcWriteBarrierCX(SB),NOSPLIT,$0 XCHGQ CX, AX - CALL runtime·gcWriteBarrier(SB) + CALL runtime·gcWriteBarrier(SB) XCHGQ CX, AX RET // gcWriteBarrierDX is gcWriteBarrier, but with args in DI and DX. -TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stable Go ABI. +TEXT runtime·gcWriteBarrierDX(SB),NOSPLIT,$0 XCHGQ DX, AX - CALL runtime·gcWriteBarrier(SB) + CALL runtime·gcWriteBarrier(SB) XCHGQ DX, AX RET // gcWriteBarrierBX is gcWriteBarrier, but with args in DI and BX. -TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stable Go ABI. +TEXT runtime·gcWriteBarrierBX(SB),NOSPLIT,$0 XCHGQ BX, AX - CALL runtime·gcWriteBarrier(SB) + CALL runtime·gcWriteBarrier(SB) XCHGQ BX, AX RET // gcWriteBarrierBP is gcWriteBarrier, but with args in DI and BP. -TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stable Go ABI. +TEXT runtime·gcWriteBarrierBP(SB),NOSPLIT,$0 XCHGQ BP, AX - CALL runtime·gcWriteBarrier(SB) + CALL runtime·gcWriteBarrier(SB) XCHGQ BP, AX RET // gcWriteBarrierSI is gcWriteBarrier, but with args in DI and SI. -TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stable Go ABI. +TEXT runtime·gcWriteBarrierSI(SB),NOSPLIT,$0 XCHGQ SI, AX - CALL runtime·gcWriteBarrier(SB) + CALL runtime·gcWriteBarrier(SB) XCHGQ SI, AX RET // gcWriteBarrierR8 is gcWriteBarrier, but with args in DI and R8. -TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stable Go ABI. +TEXT runtime·gcWriteBarrierR8(SB),NOSPLIT,$0 XCHGQ R8, AX - CALL runtime·gcWriteBarrier(SB) + CALL runtime·gcWriteBarrier(SB) XCHGQ R8, AX RET // gcWriteBarrierR9 is gcWriteBarrier, but with args in DI and R9. -TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stable Go ABI. +TEXT runtime·gcWriteBarrierR9(SB),NOSPLIT,$0 XCHGQ R9, AX - CALL runtime·gcWriteBarrier(SB) + CALL runtime·gcWriteBarrier(SB) XCHGQ R9, AX RET @@ -1544,7 +1560,10 @@ GLOBL debugCallFrameTooLarge<>(SB), RODATA, $20 // Size duplicated below // obey escape analysis requirements. Specifically, it must not pass // a stack pointer to an escaping argument. debugCallV1 cannot check // this invariant. -TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0 +// +// This is ABIInternal because Go code injects its PC directly into new +// goroutine stacks. +TEXT runtime·debugCallV1(SB),NOSPLIT,$152-0 // Save all registers that may contain pointers so they can be // conservatively scanned. // @@ -1705,67 +1724,68 @@ TEXT runtime·debugCallPanicked(SB),NOSPLIT,$16-16 // in the caller's stack frame. These stubs write the args into that stack space and // then tail call to the corresponding runtime handler. // The tail call makes these stubs disappear in backtraces. -TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 +// Defined as ABIInternal since they do not use the stack-based Go ABI. +TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 MOVQ AX, x+0(FP) MOVQ CX, y+8(FP) JMP runtime·goPanicIndex(SB) -TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 +TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 MOVQ AX, x+0(FP) MOVQ CX, y+8(FP) JMP runtime·goPanicIndexU(SB) -TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 +TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 MOVQ CX, x+0(FP) MOVQ DX, y+8(FP) JMP runtime·goPanicSliceAlen(SB) -TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 +TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 MOVQ CX, x+0(FP) MOVQ DX, y+8(FP) JMP runtime·goPanicSliceAlenU(SB) -TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 +TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 MOVQ CX, x+0(FP) MOVQ DX, y+8(FP) JMP runtime·goPanicSliceAcap(SB) -TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 +TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 MOVQ CX, x+0(FP) MOVQ DX, y+8(FP) JMP runtime·goPanicSliceAcapU(SB) -TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 +TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 MOVQ AX, x+0(FP) MOVQ CX, y+8(FP) JMP runtime·goPanicSliceB(SB) -TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 +TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 MOVQ AX, x+0(FP) MOVQ CX, y+8(FP) JMP runtime·goPanicSliceBU(SB) -TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 MOVQ DX, x+0(FP) MOVQ BX, y+8(FP) JMP runtime·goPanicSlice3Alen(SB) -TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 MOVQ DX, x+0(FP) MOVQ BX, y+8(FP) JMP runtime·goPanicSlice3AlenU(SB) -TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 MOVQ DX, x+0(FP) MOVQ BX, y+8(FP) JMP runtime·goPanicSlice3Acap(SB) -TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 MOVQ DX, x+0(FP) MOVQ BX, y+8(FP) JMP runtime·goPanicSlice3AcapU(SB) -TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 MOVQ CX, x+0(FP) MOVQ DX, y+8(FP) JMP runtime·goPanicSlice3B(SB) -TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 MOVQ CX, x+0(FP) MOVQ DX, y+8(FP) JMP runtime·goPanicSlice3BU(SB) -TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 MOVQ AX, x+0(FP) MOVQ CX, y+8(FP) JMP runtime·goPanicSlice3C(SB) -TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 +TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 MOVQ AX, x+0(FP) MOVQ CX, y+8(FP) JMP runtime·goPanicSlice3CU(SB) diff --git a/src/runtime/asm_wasm.s b/src/runtime/asm_wasm.s index 67e81adf0b9..fcb780f1dc8 100644 --- a/src/runtime/asm_wasm.s +++ b/src/runtime/asm_wasm.s @@ -196,7 +196,7 @@ TEXT runtime·jmpdefer(SB), NOSPLIT, $0-16 Get CTXT I64Eqz If - CALLNORESUME runtime·sigpanic(SB) + CALLNORESUME runtime·sigpanic(SB) End // caller sp after CALL @@ -300,7 +300,7 @@ TEXT ·reflectcall(SB), NOSPLIT, $0-32 I64Load fn+8(FP) I64Eqz If - CALLNORESUME runtime·sigpanic(SB) + CALLNORESUME runtime·sigpanic(SB) End MOVW argsize+24(FP), R0 diff --git a/src/runtime/duff_amd64.s b/src/runtime/duff_amd64.s index 44dc75d2976..2ff5bf6dbcd 100644 --- a/src/runtime/duff_amd64.s +++ b/src/runtime/duff_amd64.s @@ -4,7 +4,7 @@ #include "textflag.h" -TEXT runtime·duffzero(SB), NOSPLIT, $0-0 +TEXT runtime·duffzero(SB), NOSPLIT, $0-0 MOVUPS X0,(DI) MOVUPS X0,16(DI) MOVUPS X0,32(DI) @@ -103,7 +103,7 @@ TEXT runtime·duffzero(SB), NOSPLIT, $0-0 RET -TEXT runtime·duffcopy(SB), NOSPLIT, $0-0 +TEXT runtime·duffcopy(SB), NOSPLIT, $0-0 MOVUPS (SI), X0 ADDQ $16, SI MOVUPS X0, (DI) diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index 286f81489a1..1d614dd0039 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -126,7 +126,8 @@ func header(arch string) { } fmt.Fprintf(out, "#include \"go_asm.h\"\n") fmt.Fprintf(out, "#include \"textflag.h\"\n\n") - fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n") + fmt.Fprintf(out, "// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally.\n") + fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n") } func p(f string, args ...interface{}) { diff --git a/src/runtime/preempt_386.s b/src/runtime/preempt_386.s index c3a5fa1f361..a803b24dc6f 100644 --- a/src/runtime/preempt_386.s +++ b/src/runtime/preempt_386.s @@ -3,7 +3,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 PUSHFL ADJSP $156 NOP SP diff --git a/src/runtime/preempt_amd64.s b/src/runtime/preempt_amd64.s index 4765e9f448a..92c664d79ab 100644 --- a/src/runtime/preempt_amd64.s +++ b/src/runtime/preempt_amd64.s @@ -3,7 +3,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 PUSHQ BP MOVQ SP, BP // Save flags before clobbering them diff --git a/src/runtime/preempt_arm.s b/src/runtime/preempt_arm.s index 8f243c0dcd6..bbc9fbb1eae 100644 --- a/src/runtime/preempt_arm.s +++ b/src/runtime/preempt_arm.s @@ -3,7 +3,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVW.W R14, -188(R13) MOVW R0, 4(R13) MOVW R1, 8(R13) diff --git a/src/runtime/preempt_arm64.s b/src/runtime/preempt_arm64.s index 36ee13282c7..2b70a28479d 100644 --- a/src/runtime/preempt_arm64.s +++ b/src/runtime/preempt_arm64.s @@ -3,7 +3,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVD R30, -496(RSP) SUB $496, RSP #ifdef GOOS_linux diff --git a/src/runtime/preempt_mips64x.s b/src/runtime/preempt_mips64x.s index 1e123e80773..0d0c157c36c 100644 --- a/src/runtime/preempt_mips64x.s +++ b/src/runtime/preempt_mips64x.s @@ -5,7 +5,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVV R31, -488(R29) SUBV $488, R29 MOVV R1, 8(R29) diff --git a/src/runtime/preempt_mipsx.s b/src/runtime/preempt_mipsx.s index afac33e0a03..86d3a918d33 100644 --- a/src/runtime/preempt_mipsx.s +++ b/src/runtime/preempt_mipsx.s @@ -5,7 +5,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVW R31, -244(R29) SUB $244, R29 MOVW R1, 4(R29) diff --git a/src/runtime/preempt_ppc64x.s b/src/runtime/preempt_ppc64x.s index b2d7e30ec7b..90634386dbf 100644 --- a/src/runtime/preempt_ppc64x.s +++ b/src/runtime/preempt_ppc64x.s @@ -5,7 +5,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOVD R31, -488(R1) MOVD LR, R31 MOVDU R31, -520(R1) diff --git a/src/runtime/preempt_riscv64.s b/src/runtime/preempt_riscv64.s index eb68dcba2b9..d4f9cc277f4 100644 --- a/src/runtime/preempt_riscv64.s +++ b/src/runtime/preempt_riscv64.s @@ -3,7 +3,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 MOV X1, -472(X2) ADD $-472, X2 MOV X3, 8(X2) diff --git a/src/runtime/preempt_s390x.s b/src/runtime/preempt_s390x.s index ca9e47cde17..c6f11571df7 100644 --- a/src/runtime/preempt_s390x.s +++ b/src/runtime/preempt_s390x.s @@ -3,7 +3,8 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 IPM R10 MOVD R14, -248(R15) ADD $-248, R15 diff --git a/src/runtime/preempt_wasm.s b/src/runtime/preempt_wasm.s index 0cf57d3d226..da90e8aa6dd 100644 --- a/src/runtime/preempt_wasm.s +++ b/src/runtime/preempt_wasm.s @@ -3,6 +3,7 @@ #include "go_asm.h" #include "textflag.h" -TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 +// Note: asyncPreempt doesn't use the internal ABI, but we must be able to inject calls to it from the signal handler, so Go code has to see the PC of this function literally. +TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0 // No async preemption on wasm UNDEF diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index 758d5432034..4a86b3371a5 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -41,7 +41,9 @@ // func runtime·raceread(addr uintptr) // Called from instrumented code. -TEXT runtime·raceread(SB), NOSPLIT, $0-8 +// Defined as ABIInternal so as to avoid introducing a wrapper, +// which would render runtime.getcallerpc ineffective. +TEXT runtime·raceread(SB), NOSPLIT, $0-8 MOVQ addr+0(FP), RARG1 MOVQ (SP), RARG2 // void __tsan_read(ThreadState *thr, void *addr, void *pc); @@ -65,7 +67,9 @@ TEXT runtime·racereadpc(SB), NOSPLIT, $0-24 // func runtime·racewrite(addr uintptr) // Called from instrumented code. -TEXT runtime·racewrite(SB), NOSPLIT, $0-8 +// Defined as ABIInternal so as to avoid introducing a wrapper, +// which would render runtime.getcallerpc ineffective. +TEXT runtime·racewrite(SB), NOSPLIT, $0-8 MOVQ addr+0(FP), RARG1 MOVQ (SP), RARG2 // void __tsan_write(ThreadState *thr, void *addr, void *pc); @@ -114,7 +118,9 @@ TEXT runtime·racereadrangepc1(SB), NOSPLIT, $0-24 // func runtime·racewriterange(addr, size uintptr) // Called from instrumented code. -TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 +// Defined as ABIInternal so as to avoid introducing a wrapper, +// which would render runtime.getcallerpc ineffective. +TEXT runtime·racewriterange(SB), NOSPLIT, $0-16 MOVQ addr+0(FP), RARG1 MOVQ size+8(FP), RARG2 MOVQ (SP), RARG3 diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index 681cd202747..37cb8dad036 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -380,7 +380,8 @@ TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 POPQ BP RET -TEXT runtime·sigtramp(SB),NOSPLIT,$72 +// Defined as ABIInternal since it does not use the stack-based Go ABI. +TEXT runtime·sigtramp(SB),NOSPLIT,$72 // Save callee-saved C registers, since the caller may be a C signal handler. MOVQ BX, bx-8(SP) MOVQ BP, bp-16(SP) // save in case GOEXPERIMENT=noframepointer is set @@ -407,7 +408,8 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$72 // Used instead of sigtramp in programs that use cgo. // Arguments from kernel are in DI, SI, DX. -TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stack-based Go ABI. +TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 // If no traceback function, do usual sigtramp. MOVQ runtime·cgoTraceback(SB), AX TESTQ AX, AX @@ -450,12 +452,12 @@ TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 // The first three arguments, and the fifth, are already in registers. // Set the two remaining arguments now. MOVQ runtime·cgoTraceback(SB), CX - MOVQ $runtime·sigtramp(SB), R9 + MOVQ $runtime·sigtramp(SB), R9 MOVQ _cgo_callers(SB), AX JMP AX sigtramp: - JMP runtime·sigtramp(SB) + JMP runtime·sigtramp(SB) sigtrampnog: // Signal arrived on a non-Go thread. If this is SIGPROF, get a @@ -486,7 +488,8 @@ sigtrampnog: // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/x86_64/sigaction.c // The code that cares about the precise instructions used is: // https://gcc.gnu.org/viewcvs/gcc/trunk/libgcc/config/i386/linux-unwind.h?revision=219188&view=markup -TEXT runtime·sigreturn(SB),NOSPLIT,$0 +// Defined as ABIInternal since it does not use the stack-based Go ABI. +TEXT runtime·sigreturn(SB),NOSPLIT,$0 MOVQ $SYS_rt_sigreturn, AX SYSCALL INT $3 // not reached From e02ab89eb8994fa6f2dfa2924cdadb097633fcc1 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 29 Oct 2020 16:23:27 -0700 Subject: [PATCH 286/403] runtime: simplify nobarrierWakeTime Also use the simplified nobarrierWakeTime in findrunnable, as it no longer needs the current time. Change-Id: I77b125d6a184dde0aeb517fc068164c274f0a046 Reviewed-on: https://go-review.googlesource.com/c/go/+/266304 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/proc.go | 15 +++------------ src/runtime/time.go | 13 ++++++------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index c97f4820da3..939757f3a72 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -2659,18 +2659,9 @@ stop: // checkTimers here because it calls adjusttimers which may need to allocate // memory, and that isn't allowed when we don't have an active P. for _, _p_ := range allpSnapshot { - // This is similar to nobarrierWakeTime, but minimizes calls to - // nanotime. - if atomic.Load(&_p_.adjustTimers) > 0 { - if now == 0 { - now = nanotime() - } - pollUntil = now - } else { - w := int64(atomic.Load64(&_p_.timer0When)) - if w != 0 && (pollUntil == 0 || w < pollUntil) { - pollUntil = w - } + w := nobarrierWakeTime(_p_) + if w != 0 && (pollUntil == 0 || w < pollUntil) { + pollUntil = w } } if pollUntil != 0 { diff --git a/src/runtime/time.go b/src/runtime/time.go index 99290f66d0e..75b66f8492e 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -742,16 +742,15 @@ func addAdjustedTimers(pp *p, moved []*timer) { // nobarrierWakeTime looks at P's timers and returns the time when we // should wake up the netpoller. It returns 0 if there are no timers. // This function is invoked when dropping a P, and must run without -// any write barriers. Therefore, if there are any timers that needs -// to be moved earlier, it conservatively returns the current time. -// The netpoller M will wake up and adjust timers before sleeping again. +// any write barriers. //go:nowritebarrierrec func nobarrierWakeTime(pp *p) int64 { - if atomic.Load(&pp.adjustTimers) > 0 { - return nanotime() - } else { - return int64(atomic.Load64(&pp.timer0When)) + next := int64(atomic.Load64(&pp.timer0When)) + nextAdj := int64(atomic.Load64(&pp.timerModifiedEarliest)) + if next == 0 || (nextAdj != 0 && nextAdj < next) { + next = nextAdj } + return next } // runtimer examines the first timer in timers. If it is ready based on now, From fb184a383e756cb57267590ac290be0d3bb64874 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Fri, 16 Oct 2020 09:22:31 -0400 Subject: [PATCH 287/403] cmd/link: emit include directories in DWARF line table prologue This patch changes the way the linker emits the DWARF line table prologue, specifically the file table. Previously files were left unmodified, and the directory table was empty. For each compilation unit we now scan the unit file table and build up a common set of directories, emit them into the directory table, and then emit file entries that refer to the dirs. This provides a modest binary size savings. For kubernetes kubelet: $ objdump -h /tmp/kubelet.old | fgrep debug_line 36 .zdebug_line 019a55f5 0000000000000000 0000000000000000 084a5123 2**0 $ objdump -h /tmp/kubelet.new | fgrep debug_line 36 .zdebug_line 01146fd2 0000000000000000 0000000000000000 084a510a 2**0 [where the value following the section name above is the section size in hex, so roughly a 30% decrease in this case.] The actual savings will depend on the length of the pathnames involved, so it's hard to really pin down how much savings we'll see here. In addition, emitting the files this way reduces the "compressibility" of the line table, so there could even be cases where we don't win at all. Updates #6853, #19784, #36495. Change-Id: I298d8561da5ed3ebc9d38aa772874851baa2f4f4 Reviewed-on: https://go-review.googlesource.com/c/go/+/263017 Run-TryBot: Than McIntosh TryBot-Result: Go Bot Reviewed-by: Austin Clements Trust: Than McIntosh --- src/cmd/link/internal/ld/dwarf.go | 109 ++++++++++++++++++++---------- src/debug/dwarf/line.go | 6 +- src/debug/dwarf/line_test.go | 8 +++ 3 files changed, 88 insertions(+), 35 deletions(-) diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 2b95ad5a67d..2ab9a55e969 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -23,6 +23,7 @@ import ( "cmd/link/internal/sym" "fmt" "log" + "path" "runtime" "sort" "strings" @@ -1173,13 +1174,81 @@ func expandFile(fname string) string { return expandGoroot(fname) } -// writelines collects up and chai,ns together the symbols needed to +// writeDirFileTables emits the portion of the DWARF line table +// prologue containing the include directories and file names, +// described in section 6.2.4 of the DWARF 4 standard. It walks the +// filepaths for the unit to discover any common directories, which +// are emitted to the directory table first, then the file table is +// emitted after that. +func (d *dwctxt) writeDirFileTables(unit *sym.CompilationUnit, lsu *loader.SymbolBuilder) { + type fileDir struct { + base string + dir int + } + dirNums := make(map[string]int) + dirs := []string{""} + files := []fileDir{} + + // Preprocess files to collect directories. This assumes that the + // file table is already de-duped. + for i, name := range unit.FileTable { + name := expandFile(name) + if len(name) == 0 { + // Can't have empty filenames, and having a unique + // filename is quite useful for debugging. + name = fmt.Sprintf("_%d", i) + } + // Note the use of "path" here and not "filepath". The compiler + // hard-codes to use "/" in DWARF paths (even for Windows), so we + // want to maintain that here. + file := path.Base(name) + dir := path.Dir(name) + dirIdx, ok := dirNums[dir] + if !ok && dir != "." { + dirIdx = len(dirNums) + 1 + dirNums[dir] = dirIdx + dirs = append(dirs, dir) + } + files = append(files, fileDir{base: file, dir: dirIdx}) + + // We can't use something that may be dead-code + // eliminated from a binary here. proc.go contains + // main and the scheduler, so it's not going anywhere. + if i := strings.Index(name, "runtime/proc.go"); i >= 0 { + d.dwmu.Lock() + if gdbscript == "" { + k := strings.Index(name, "runtime/proc.go") + gdbscript = name[:k] + "runtime/runtime-gdb.py" + } + d.dwmu.Unlock() + } + } + + // Emit directory section. This is a series of nul terminated + // strings, followed by a single zero byte. + lsDwsym := dwSym(lsu.Sym()) + for k := 1; k < len(dirs); k++ { + d.AddString(lsDwsym, dirs[k]) + } + lsu.AddUint8(0) // terminator + + // Emit file section. + for k := 0; k < len(files); k++ { + d.AddString(lsDwsym, files[k].base) + dwarf.Uleb128put(d, lsDwsym, int64(files[k].dir)) + lsu.AddUint8(0) // mtime + lsu.AddUint8(0) // length + } + lsu.AddUint8(0) // terminator +} + +// writelines collects up and chains together the symbols needed to // form the DWARF line table for the specified compilation unit, // returning a list of symbols. The returned list will include an -// initial symbol containing the line table header and prolog (with +// initial symbol containing the line table header and prologue (with // file table), then a series of compiler-emitted line table symbols // (one per live function), and finally an epilog symbol containing an -// end-of-sequence operator. The prolog and epilog symbols are passed +// end-of-sequence operator. The prologue and epilog symbols are passed // in (having been created earlier); here we add content to them. func (d *dwctxt) writelines(unit *sym.CompilationUnit, lineProlog loader.Sym) []loader.Sym { is_stmt := uint8(1) // initially = recommended default_is_stmt = 1, tracks is_stmt toggles. @@ -1220,39 +1289,11 @@ func (d *dwctxt) writelines(unit *sym.CompilationUnit, lineProlog loader.Sym) [] lsu.AddUint8(0) // standard_opcode_lengths[8] lsu.AddUint8(1) // standard_opcode_lengths[9] lsu.AddUint8(0) // standard_opcode_lengths[10] - lsu.AddUint8(0) // include_directories (empty) - // Copy over the file table. - fileNums := make(map[string]int) - for i, name := range unit.FileTable { - name := expandFile(name) - if len(name) == 0 { - // Can't have empty filenames, and having a unique - // filename is quite useful for debugging. - name = fmt.Sprintf("_%d", i) - } - fileNums[name] = i + 1 - d.AddString(lsDwsym, name) - lsu.AddUint8(0) - lsu.AddUint8(0) - lsu.AddUint8(0) + // Call helper to emit dir and file sections. + d.writeDirFileTables(unit, lsu) - // We can't use something that may be dead-code - // eliminated from a binary here. proc.go contains - // main and the scheduler, so it's not going anywhere. - if i := strings.Index(name, "runtime/proc.go"); i >= 0 { - d.dwmu.Lock() - if gdbscript == "" { - k := strings.Index(name, "runtime/proc.go") - gdbscript = name[:k] + "runtime/runtime-gdb.py" - } - d.dwmu.Unlock() - } - } - - // 4 zeros: the string termination + 3 fields. - lsu.AddUint8(0) - // terminate file_names. + // capture length at end of file names. headerend = lsu.Size() unitlen := lsu.Size() - unitstart diff --git a/src/debug/dwarf/line.go b/src/debug/dwarf/line.go index 7692f055521..c4937ca7dd8 100644 --- a/src/debug/dwarf/line.go +++ b/src/debug/dwarf/line.go @@ -814,7 +814,11 @@ func pathJoin(dirname, filename string) string { // Drives are the same. Ignore drive on filename. } if !(strings.HasSuffix(dirname, "/") || strings.HasSuffix(dirname, `\`)) && dirname != "" { - dirname += `\` + sep := `\` + if strings.HasPrefix(dirname, "/") { + sep = `/` + } + dirname += sep } return drive + dirname + filename } diff --git a/src/debug/dwarf/line_test.go b/src/debug/dwarf/line_test.go index 1fd9b19b035..b13818e8b50 100644 --- a/src/debug/dwarf/line_test.go +++ b/src/debug/dwarf/line_test.go @@ -341,6 +341,14 @@ var joinTests = []joinTest{ {`\\host\share\`, `foo\bar`, `\\host\share\foo\bar`}, {`//host/share/`, `foo/bar`, `//host/share/foo/bar`}, + // Note: the Go compiler currently emits DWARF line table paths + // with '/' instead of '\' (see issues #19784, #36495). These + // tests are to cover cases that might come up for Windows Go + // binaries. + {`c:/workdir/go/src/x`, `y.go`, `c:/workdir/go/src/x/y.go`}, + {`d:/some/thing/`, `b.go`, `d:/some/thing/b.go`}, + {`e:\blah\`, `foo.c`, `e:\blah\foo.c`}, + // The following are "best effort". We shouldn't see relative // base directories in DWARF, but these test that pathJoin // doesn't fail miserably if it sees one. From 34665c63ff39b83dcc5d3ca6400c19ee737ac988 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 28 Oct 2020 21:29:19 -0400 Subject: [PATCH 288/403] cmd/go/internal/mvs: omit modules at version "none" in BuildList and Req For #37438 Change-Id: Icb28035ae4027aa09d8959d4ac2f4b94a6c843a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/266339 Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod Reviewed-by: Michael Matloob TryBot-Result: Go Bot Trust: Bryan C. Mills --- src/cmd/go/internal/mvs/mvs.go | 7 ++++++- src/cmd/go/internal/mvs/mvs_test.go | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/internal/mvs/mvs.go b/src/cmd/go/internal/mvs/mvs.go index ea23a9f45e1..3524a7a90ee 100644 --- a/src/cmd/go/internal/mvs/mvs.go +++ b/src/cmd/go/internal/mvs/mvs.go @@ -120,7 +120,9 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m } node.required = required for _, r := range node.required { - work.Add(r) + if r.Version != "none" { + work.Add(r) + } } if upgrade != nil { @@ -208,6 +210,9 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m n := modGraph[module.Version{Path: path, Version: vers}] required := n.required for _, r := range required { + if r.Version == "none" { + continue + } v := min[r.Path] if r.Path != target.Path && reqs.Max(v, r.Version) != v { panic(fmt.Sprintf("mistake: version %q does not satisfy requirement %+v", v, r)) // TODO: Don't panic. diff --git a/src/cmd/go/internal/mvs/mvs_test.go b/src/cmd/go/internal/mvs/mvs_test.go index 9a30a8c3ac0..f6f07b200ea 100644 --- a/src/cmd/go/internal/mvs/mvs_test.go +++ b/src/cmd/go/internal/mvs/mvs_test.go @@ -317,6 +317,13 @@ B1: X2 X1: I1 X2: req M: A1 B1 + +name: reqnone +M: Anone B1 D1 E1 +B1: Cnone D1 +E1: Fnone +build M: M B1 D1 E1 +req M: B1 E1 ` func Test(t *testing.T) { From 36d412f7548d90f4764c780a6f7d7da04bb90a9e Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 28 Oct 2020 23:49:54 -0400 Subject: [PATCH 289/403] cmd/go/internal/modload: ensure that modRoot and targetPrefix are initialized in DirImportPath For #37438 Change-Id: I2e1f47d567842ac5504b7b8ed0b3fba6f92d778b Reviewed-on: https://go-review.googlesource.com/c/go/+/266340 Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod Reviewed-by: Michael Matloob TryBot-Result: Go Bot Trust: Bryan C. Mills --- src/cmd/go/internal/modload/load.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index f9c468c8b2c..0a84a1765a5 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -520,9 +520,10 @@ func ImportFromFiles(ctx context.Context, gofiles []string) { // DirImportPath returns the effective import path for dir, // provided it is within the main module, or else returns ".". func DirImportPath(dir string) string { - if modRoot == "" { + if !HasModRoot() { return "." } + LoadModFile(context.TODO()) if !filepath.IsAbs(dir) { dir = filepath.Join(base.Cwd, dir) From 8494a6243ee5c80da51da8f4e1ad4d719eddf409 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 29 Oct 2020 16:06:19 -0400 Subject: [PATCH 290/403] cmd/go: make TestScript/mod_get_patchmod self-contained I find it pretty difficult to reason about test-dependency modules when they aren't in the same file as the rest of the test. Now that 'go get' supports replacements (CL 258220 and CL 266018), we can localize tests that need 'go get' but don't specifically depend on module proxy semantics. For #36460 For #37438 Change-Id: Ib37a6c170f251435399dfc23e60d96681a81eadc Reviewed-on: https://go-review.googlesource.com/c/go/+/266369 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod Reviewed-by: Michael Matloob TryBot-Result: Go Bot --- .../mod/example.net_pkgremoved_v0.1.0.txt | 16 ---------------- .../mod/example.net_pkgremoved_v0.2.0.txt | 15 --------------- .../mod/example.net_pkgremoved_v0.2.1.txt | 15 --------------- src/cmd/go/testdata/script/mod_get_patchmod.txt | 16 +++++++++++++++- 4 files changed, 15 insertions(+), 47 deletions(-) delete mode 100644 src/cmd/go/testdata/mod/example.net_pkgremoved_v0.1.0.txt delete mode 100644 src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.0.txt delete mode 100644 src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.1.txt diff --git a/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.1.0.txt b/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.1.0.txt deleted file mode 100644 index f5e76b00c9b..00000000000 --- a/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.1.0.txt +++ /dev/null @@ -1,16 +0,0 @@ -Written by hand. -Test module with a root package added in v0.1.0 and removed in v0.2.0. - --- .mod -- -module example.net/pkgremoved - -go 1.16 --- .info -- -{"Version": "v0.1.0"} --- go.mod -- -module example.net/pkgremoved - -go 1.16 --- pkgremoved.go -- -// Package pkgremoved exists in v0.1.0. -package pkgremoved diff --git a/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.0.txt b/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.0.txt deleted file mode 100644 index f1fc9fb61f3..00000000000 --- a/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.0.txt +++ /dev/null @@ -1,15 +0,0 @@ -Written by hand. -Test module with a root package added in v0.1.0 and removed in v0.2.0. - --- .mod -- -module example.net/pkgremoved - -go 1.16 --- .info -- -{"Version": "v0.2.0"} --- go.mod -- -module example.net/pkgremoved - -go 1.16 --- README.txt -- -Package pkgremove was removed in v0.2.0. diff --git a/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.1.txt b/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.1.txt deleted file mode 100644 index 0e961853d52..00000000000 --- a/src/cmd/go/testdata/mod/example.net_pkgremoved_v0.2.1.txt +++ /dev/null @@ -1,15 +0,0 @@ -Written by hand. -Test module with a root package added in v0.1.0 and removed in v0.2.0. - --- .mod -- -module example.net/pkgremoved - -go 1.16 --- .info -- -{"Version": "v0.2.1"} --- go.mod -- -module example.net/pkgremoved - -go 1.16 --- README.txt -- -Package pkgremove was removed in v0.2.0. diff --git a/src/cmd/go/testdata/script/mod_get_patchmod.txt b/src/cmd/go/testdata/script/mod_get_patchmod.txt index 45d680d0211..0f4e2e1647f 100644 --- a/src/cmd/go/testdata/script/mod_get_patchmod.txt +++ b/src/cmd/go/testdata/script/mod_get_patchmod.txt @@ -17,7 +17,7 @@ stdout '^example.net/pkgremoved' ! go get -d example.net/pkgremoved@patch example.net/other@v0.1.0 -stderr '^go get example.net/pkgremoved@patch: module example.net/pkgremoved@latest found \(v0.2.1\), but does not contain package example.net/pkgremoved$' +stderr '^go get example.net/pkgremoved@patch: module example.net/pkgremoved@latest found \(v0.2.1, replaced by ./pr2\), but does not contain package example.net/pkgremoved$' -- go.mod -- @@ -27,6 +27,10 @@ go 1.16 replace ( example.net/other v0.1.0 => ./other + example.net/pkgremoved v0.1.0 => ./pr1 + example.net/pkgremoved v0.1.1 => ./pr1 + example.net/pkgremoved v0.2.0 => ./pr2 + example.net/pkgremoved v0.2.1 => ./pr2 ) -- other/go.mod -- module example.net/other @@ -36,3 +40,13 @@ go 1.16 require example.net/pkgremoved v0.2.0 -- other/other.go -- package other +-- pr1/go.mod -- +module example.net/pkgremoved + +go 1.16 +-- pr1/pkgremoved.go -- +package pkgremoved +-- pr2/go.mod -- +module example.net/pkgremoved +-- pr2/README.txt -- +Package pkgremoved was removed in v0.2.0. From 6d087c807e558a7e4f7da29fd44998e6f605c27d Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 29 Oct 2020 16:36:50 -0400 Subject: [PATCH 291/403] cmd/go/internal/modload: handle NotExist errors in (*mvsReqs).Previous Previous is used during downgrading. If the module proxy does not advertise any versions (for example, because it contains only pseudo-versions), then Previous should return "none" instead of a non-nil error. For #37438 Change-Id: I4edfec19cfeb3ffe50df4979f99a01321c442509 Reviewed-on: https://go-review.googlesource.com/c/go/+/266370 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod Reviewed-by: Michael Matloob TryBot-Result: Go Bot --- src/cmd/go/internal/modload/mvs.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/go/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go index 79ef2475b6a..94373bc5f39 100644 --- a/src/cmd/go/internal/modload/mvs.go +++ b/src/cmd/go/internal/modload/mvs.go @@ -7,6 +7,7 @@ package modload import ( "context" "errors" + "os" "sort" "cmd/go/internal/modfetch" @@ -102,6 +103,9 @@ func (*mvsReqs) Previous(m module.Version) (module.Version, error) { // TODO(golang.org/issue/38714): thread tracing context through MVS. list, err := versions(context.TODO(), m.Path, CheckAllowed) if err != nil { + if errors.Is(err, os.ErrNotExist) { + return module.Version{Path: m.Path, Version: "none"}, nil + } return module.Version{}, err } i := sort.Search(len(list), func(i int) bool { return semver.Compare(list[i], m.Version) >= 0 }) From b53df56001a6bd375b1dc2026908f331729cd731 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Thu, 29 Oct 2020 11:27:17 -0400 Subject: [PATCH 292/403] runtime, cmd: support race detector on darwin/arm64 https://reviews.llvm.org/D90435 is the counterpart in LLVM TSAN. race_linux_arm64.syso is built with LLVM commit 00da38ce2d36c07f12c287dc515d37bb7bc410e9 on a macOS/ARM64 machine. (It is not built on a builder with golang.org/x/build/cmd/racebuild as we don't have darwin/arm64 builder for now.) Updates #38485. Change-Id: I391efdacd9480197e308370bfccd05777deb4aee Reviewed-on: https://go-review.googlesource.com/c/go/+/266373 Trust: Cherry Zhang Reviewed-by: Ian Lance Taylor --- src/cmd/dist/test.go | 4 +++- src/cmd/go/internal/work/init.go | 2 +- src/cmd/internal/sys/supported.go | 4 +++- src/cmd/link/internal/ld/config.go | 2 +- src/cmd/link/internal/loadmacho/ldmacho.go | 12 ++++++++++-- src/runtime/race/README | 1 + src/runtime/race/race.go | 2 +- src/runtime/race/race_darwin_arm64.syso | Bin 0 -> 438936 bytes src/runtime/race_arm64.s | 15 +++++++++++++++ 9 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 src/runtime/race/race_darwin_arm64.syso diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 7c454dd38d5..9c25392cc03 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1619,7 +1619,9 @@ func raceDetectorSupported(goos, goarch string) bool { switch goos { case "linux": return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" - case "darwin", "freebsd", "netbsd", "windows": + case "darwin": + return goarch == "amd64" || goarch == "arm64" + case "freebsd", "netbsd", "windows": return goarch == "amd64" default: return false diff --git a/src/cmd/go/internal/work/init.go b/src/cmd/go/internal/work/init.go index d65c076c6a8..102def48383 100644 --- a/src/cmd/go/internal/work/init.go +++ b/src/cmd/go/internal/work/init.go @@ -79,7 +79,7 @@ func instrumentInit() { } if cfg.BuildRace { if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) { - fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0]) + fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64, darwin/arm64, and windows/amd64\n", flag.Args()[0]) base.SetExitStatus(2) base.Exit() } diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 3c750774ed2..69d75914406 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -13,7 +13,9 @@ func RaceDetectorSupported(goos, goarch string) bool { switch goos { case "linux": return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" - case "darwin", "freebsd", "netbsd", "windows": + case "darwin": + return goarch == "amd64" || goarch == "arm64" + case "freebsd", "netbsd", "windows": return goarch == "amd64" default: return false diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 0cb3cc25c06..cd64d86a4af 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -206,7 +206,7 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { // When the race flag is set, the LLVM tsan relocatable file is linked // into the final binary, which means external linking is required because // internal linking does not support it. - if *flagRace && ctxt.Arch.InFamily(sys.PPC64) { + if *flagRace && (ctxt.Arch.InFamily(sys.PPC64) || ctxt.IsDarwin() && ctxt.IsARM64()) { return true, "race on " + objabi.GOARCH } diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index d12f2bc2ac7..d26869e23a7 100644 --- a/src/cmd/link/internal/loadmacho/ldmacho.go +++ b/src/cmd/link/internal/loadmacho/ldmacho.go @@ -47,7 +47,7 @@ THE SOFTWARE. const ( MACHO_X86_64_RELOC_UNSIGNED = 0 MACHO_X86_64_RELOC_SIGNED = 1 - MACHO_FAKE_GOTPCREL = 100 + MACHO_ARM64_RELOC_ADDEND = 10 ) type ldMachoObj struct { @@ -707,11 +707,11 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, } sb := l.MakeSymbolUpdater(sect.sym) + var rAdd int64 for j := uint32(0); j < sect.nreloc; j++ { var ( rOff int32 rSize uint8 - rAdd int64 rType objabi.RelocType rSym loader.Sym ) @@ -722,6 +722,14 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, return errorf("%v: unexpected scattered relocation", s) } + if arch.Family == sys.ARM64 && rel.type_ == MACHO_ARM64_RELOC_ADDEND { + // Two relocations. This addend will be applied to the next one. + rAdd = int64(rel.symnum) + continue + } else { + rAdd = 0 + } + rSize = rel.length rType = objabi.MachoRelocOffset + (objabi.RelocType(rel.type_) << 1) + objabi.RelocType(rel.pcrel) rOff = int32(rel.addr) diff --git a/src/runtime/race/README b/src/runtime/race/README index b36d82ccfd6..178ab94ab57 100644 --- a/src/runtime/race/README +++ b/src/runtime/race/README @@ -11,3 +11,4 @@ race_linux_ppc64le.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 race_netbsd_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. race_windows_amd64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. race_linux_arm64.syso built with LLVM 89f7ccea6f6488c443655880229c54db1f180153 and Go f62d3202bf9dbb3a00ad2a2c63ff4fa4188c5d3b. +race_darwin_arm64.syso built with LLVM 00da38ce2d36c07f12c287dc515d37bb7bc410e9 and Go fe70a3a0fd31441bcbb9932ecab11a6083cf2119. diff --git a/src/runtime/race/race.go b/src/runtime/race/race.go index c894de5f722..d6a14b79e71 100644 --- a/src/runtime/race/race.go +++ b/src/runtime/race/race.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. -// +build race,linux,amd64 race,freebsd,amd64 race,netbsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le race,linux,arm64 +// +build race,linux,amd64 race,freebsd,amd64 race,netbsd,amd64 race,darwin,amd64 race,windows,amd64 race,linux,ppc64le race,linux,arm64 race,darwin,arm64 package race diff --git a/src/runtime/race/race_darwin_arm64.syso b/src/runtime/race/race_darwin_arm64.syso new file mode 100644 index 0000000000000000000000000000000000000000..f6eaa62ae3a88744f0f79d1ed6e9645909d1110c GIT binary patch literal 438936 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 z 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 z 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�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 a5FODH4N)pA0{o=lKy*Y)G(>dgU;ZCpS;n0J literal 0 HcmV?d00001 diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index 9b909ac0216..59373a9f3f4 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -25,8 +25,15 @@ // The race ctx, ThreadState *thr below, is passed in R0 and loaded in racecalladdr. +#ifdef TLS_darwin +#define TP_ALIGN AND $~7, R0 +#else +#define TP_ALIGN +#endif + #define load_g \ MRS_TPIDR_R0 \ + TP_ALIGN \ MOVD runtime·tls_g(SB), R11 \ ADD R11, R0 \ MOVD 0(R0), g @@ -423,7 +430,13 @@ TEXT runtime·racecallbackthunk(SB), NOSPLIT|NOFRAME, $0 // benefit from this fast path. CBNZ R0, rest MOVD g, R13 +#ifdef TLS_darwin + MOVD R27, R12 // save R27 a.k.a. REGTMP (callee-save in C). load_g clobbers it +#endif load_g +#ifdef TLS_darwin + MOVD R12, R27 +#endif MOVD g_m(g), R0 MOVD m_p(R0), R0 MOVD p_raceprocctx(R0), R0 @@ -477,5 +490,7 @@ noswitch: BL runtime·racecallback(SB) JMP ret +#ifndef TLSG_IS_VARIABLE // tls_g, g value for each thread in TLS GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8 +#endif From 7191f1136b1526703c5af7fc04ff948e3a6c26b9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 30 Oct 2020 10:36:31 -0700 Subject: [PATCH 293/403] cmd/compile: fix reassignVisitor reassignVisitor was short-circuiting on assignment statements after checking the LHS, but there might be further assignment statements nested within the RHS expressions. Fixes #42284. Change-Id: I175eef87513b973ed5ebe6a6527adb9766dde6cf Reviewed-on: https://go-review.googlesource.com/c/go/+/266618 Trust: Matthew Dempsky Run-TryBot: Matthew Dempsky Reviewed-by: Cuong Manh Le Reviewed-by: David Chase TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/inl.go | 2 -- test/fixedbugs/issue42284.dir/a.go | 23 +++++++++++++++++++++++ test/fixedbugs/issue42284.dir/b.go | 15 +++++++++++++++ test/fixedbugs/issue42284.go | 7 +++++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/fixedbugs/issue42284.dir/a.go create mode 100644 test/fixedbugs/issue42284.dir/b.go create mode 100644 test/fixedbugs/issue42284.go diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 5b589082994..8a5c6d86666 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -839,14 +839,12 @@ func (v *reassignVisitor) visit(n *Node) *Node { if n.Left == v.name && n != v.name.Name.Defn { return n } - return nil case OAS2, OAS2FUNC, OAS2MAPR, OAS2DOTTYPE: for _, p := range n.List.Slice() { if p == v.name && n != v.name.Name.Defn { return n } } - return nil } if a := v.visit(n.Left); a != nil { return a diff --git a/test/fixedbugs/issue42284.dir/a.go b/test/fixedbugs/issue42284.dir/a.go new file mode 100644 index 00000000000..e1271af32d0 --- /dev/null +++ b/test/fixedbugs/issue42284.dir/a.go @@ -0,0 +1,23 @@ +// Copyright 2020 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 a + +type I interface{ M() } +type T int + +func (T) M() {} // ERROR "can inline T.M" + +func F(i I) I { // ERROR "can inline F" "leaking param: i to result ~r1 level=0" + i = nil + return i +} + +func g() { // ERROR "can inline g" + // BAD: T(0) could be stack allocated. + i := F(T(0)) // ERROR "inlining call to F" "T\(0\) escapes to heap" + + // Testing that we do NOT devirtualize here: + i.M() +} diff --git a/test/fixedbugs/issue42284.dir/b.go b/test/fixedbugs/issue42284.dir/b.go new file mode 100644 index 00000000000..3305166db06 --- /dev/null +++ b/test/fixedbugs/issue42284.dir/b.go @@ -0,0 +1,15 @@ +// Copyright 2020 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 b + +import "./a" + +func g() { // ERROR "can inline g" + // BAD: T(0) could be stack allocated. + i := a.F(a.T(0)) // ERROR "inlining call to a.F" "a.T\(0\) escapes to heap" + + // Testing that we do NOT devirtualize here: + i.M() +} diff --git a/test/fixedbugs/issue42284.go b/test/fixedbugs/issue42284.go new file mode 100644 index 00000000000..e5d6173f5c9 --- /dev/null +++ b/test/fixedbugs/issue42284.go @@ -0,0 +1,7 @@ +// errorcheckdir -0 -m + +// Copyright 2020 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 ignored From 94b3fd06cb431358f45786246cd279c8bdb9370b Mon Sep 17 00:00:00 2001 From: Michele Di Pede Date: Fri, 30 Oct 2020 11:55:18 +0100 Subject: [PATCH 294/403] cmd/compile: code cleanup Change-Id: Ibf68e663f29a5cb3b64a7d923c005c16da647769 Reviewed-on: https://go-review.googlesource.com/c/go/+/266537 Reviewed-by: Keith Randall Reviewed-by: Matthew Dempsky Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot --- src/cmd/compile/internal/amd64/ssa.go | 9 +++--- src/cmd/compile/internal/ssa/compile.go | 40 +++++++++++++------------ src/cmd/compile/internal/x86/ssa.go | 7 +++-- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index f30a47b9037..76e33a36899 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -42,10 +42,11 @@ func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) { // loadByType returns the load instruction of the given type. func loadByType(t *types.Type) obj.As { // Avoid partial register write - if !t.IsFloat() && t.Size() <= 2 { - if t.Size() == 1 { + if !t.IsFloat() { + switch t.Size() { + case 1: return x86.AMOVBLZX - } else { + case 2: return x86.AMOVWLZX } } @@ -1070,7 +1071,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p := s.Prog(v.Op.Asm()) val := v.AuxInt // 0 means math.RoundToEven, 1 Floor, 2 Ceil, 3 Trunc - if val != 0 && val != 1 && val != 2 && val != 3 { + if val < 0 || val > 3 { v.Fatalf("Invalid rounding mode") } p.From.Offset = val diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index 9ddc53060ce..63994d1778e 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -304,37 +304,39 @@ commas. For example: ` } - if phase == "check" && flag == "on" { - checkEnabled = val != 0 - debugPoset = checkEnabled // also turn on advanced self-checking in prove's datastructure - return "" - } - if phase == "check" && flag == "off" { - checkEnabled = val == 0 - debugPoset = checkEnabled - return "" - } - if phase == "check" && flag == "seed" { - checkEnabled = true - checkRandSeed = val - debugPoset = checkEnabled - return "" + if phase == "check" { + switch flag { + case "on": + checkEnabled = val != 0 + debugPoset = checkEnabled // also turn on advanced self-checking in prove's datastructure + return "" + case "off": + checkEnabled = val == 0 + debugPoset = checkEnabled + return "" + case "seed": + checkEnabled = true + checkRandSeed = val + debugPoset = checkEnabled + return "" + } } alltime := false allmem := false alldump := false if phase == "all" { - if flag == "time" { + switch flag { + case "time": alltime = val != 0 - } else if flag == "mem" { + case "mem": allmem = val != 0 - } else if flag == "dump" { + case "dump": alldump = val != 0 if alldump { BuildDump = valString } - } else { + default: return fmt.Sprintf("Did not find a flag matching %s in -d=ssa/%s debug option", flag, phase) } } diff --git a/src/cmd/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go index 74a4570770c..fbf76d0c5ef 100644 --- a/src/cmd/compile/internal/x86/ssa.go +++ b/src/cmd/compile/internal/x86/ssa.go @@ -42,10 +42,11 @@ func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) { // loadByType returns the load instruction of the given type. func loadByType(t *types.Type) obj.As { // Avoid partial register write - if !t.IsFloat() && t.Size() <= 2 { - if t.Size() == 1 { + if !t.IsFloat() { + switch t.Size() { + case 1: return x86.AMOVBLZX - } else { + case 2: return x86.AMOVWLZX } } From 6abbfc17c255c07134a69c3ca305231db80530ec Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 28 Oct 2020 18:06:05 -0400 Subject: [PATCH 295/403] runtime: add world-stopped assertions Stopping the world is an implicit lock for many operations, so we should assert the world is stopped in functions that require it. This is enabled along with the rest of lock ranking, though it is a bit orthogonal and likely cheap enough to enable all the time should we choose. Requiring a lock _or_ world stop is common, so that can be expressed as well. Updates #40677 Change-Id: If0a58544f4251d367f73c4120c9d39974c6cd091 Reviewed-on: https://go-review.googlesource.com/c/go/+/248577 Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Austin Clements Trust: Michael Pratt --- src/runtime/heapdump.go | 15 +++++++ src/runtime/lockrank_off.go | 16 ++++++++ src/runtime/lockrank_on.go | 79 +++++++++++++++++++++++++++++++++++++ src/runtime/mcheckmark.go | 2 + src/runtime/mgc.go | 2 + src/runtime/mgcmark.go | 4 ++ src/runtime/mgcsweep.go | 2 + src/runtime/mstats.go | 14 +++++-- src/runtime/proc.go | 14 +++++++ 9 files changed, 145 insertions(+), 3 deletions(-) diff --git a/src/runtime/heapdump.go b/src/runtime/heapdump.go index 33e224d5877..2d531571aa6 100644 --- a/src/runtime/heapdump.go +++ b/src/runtime/heapdump.go @@ -431,6 +431,9 @@ func finq_callback(fn *funcval, obj unsafe.Pointer, nret uintptr, fint *_type, o } func dumproots() { + // To protect mheap_.allspans. + assertWorldStopped() + // TODO(mwhudson): dump datamask etc from all objects // data segment dumpint(tagData) @@ -468,6 +471,9 @@ func dumproots() { var freemark [_PageSize / 8]bool func dumpobjs() { + // To protect mheap_.allspans. + assertWorldStopped() + for _, s := range mheap_.allspans { if s.state.get() != mSpanInUse { continue @@ -552,6 +558,8 @@ func dumpms() { //go:systemstack func dumpmemstats(m *MemStats) { + assertWorldStopped() + // These ints should be identical to the exported // MemStats structure and should be ordered the same // way too. @@ -634,6 +642,9 @@ func dumpmemprof_callback(b *bucket, nstk uintptr, pstk *uintptr, size, allocs, } func dumpmemprof() { + // To protect mheap_.allspans. + assertWorldStopped() + iterate_memprof(dumpmemprof_callback) for _, s := range mheap_.allspans { if s.state.get() != mSpanInUse { @@ -655,6 +666,8 @@ func dumpmemprof() { var dumphdr = []byte("go1.7 heap dump\n") func mdump(m *MemStats) { + assertWorldStopped() + // make sure we're done sweeping for _, s := range mheap_.allspans { if s.state.get() == mSpanInUse { @@ -676,6 +689,8 @@ func mdump(m *MemStats) { } func writeheapdump_m(fd uintptr, m *MemStats) { + assertWorldStopped() + _g_ := getg() casgstatus(_g_.m.curg, _Grunning, _Gwaiting) _g_.waitreason = waitReasonDumpingHeap diff --git a/src/runtime/lockrank_off.go b/src/runtime/lockrank_off.go index 40edf882eeb..7dcd8f5fe96 100644 --- a/src/runtime/lockrank_off.go +++ b/src/runtime/lockrank_off.go @@ -46,3 +46,19 @@ func assertLockHeld(l *mutex) { //go:nosplit func assertRankHeld(r lockRank) { } + +//go:nosplit +func worldStopped() { +} + +//go:nosplit +func worldStarted() { +} + +//go:nosplit +func assertWorldStopped() { +} + +//go:nosplit +func assertWorldStoppedOrLockHeld(l *mutex) { +} diff --git a/src/runtime/lockrank_on.go b/src/runtime/lockrank_on.go index db7ff23a58d..c25b3a4656b 100644 --- a/src/runtime/lockrank_on.go +++ b/src/runtime/lockrank_on.go @@ -7,9 +7,14 @@ package runtime import ( + "runtime/internal/atomic" "unsafe" ) +// worldIsStopped is accessed atomically to track world-stops. 1 == world +// stopped. +var worldIsStopped uint32 + // lockRankStruct is embedded in mutex type lockRankStruct struct { // static lock ranking of the lock @@ -284,3 +289,77 @@ func assertRankHeld(r lockRank) { throw("not holding required lock!") }) } + +// worldStopped notes that the world is stopped. +// +// Caller must hold worldsema. +// +// nosplit to ensure it can be called in as many contexts as possible. +//go:nosplit +func worldStopped() { + if stopped := atomic.Xadd(&worldIsStopped, 1); stopped != 1 { + print("world stop count=", stopped, "\n") + throw("recursive world stop") + } +} + +// worldStarted that the world is starting. +// +// Caller must hold worldsema. +// +// nosplit to ensure it can be called in as many contexts as possible. +//go:nosplit +func worldStarted() { + if stopped := atomic.Xadd(&worldIsStopped, -1); stopped != 0 { + print("world stop count=", stopped, "\n") + throw("released non-stopped world stop") + } +} + +// nosplit to ensure it can be called in as many contexts as possible. +//go:nosplit +func checkWorldStopped() bool { + stopped := atomic.Load(&worldIsStopped) + if stopped > 1 { + print("inconsistent world stop count=", stopped, "\n") + throw("inconsistent world stop count") + } + + return stopped == 1 +} + +// assertWorldStopped throws if the world is not stopped. It does not check +// which M stopped the world. +// +// nosplit to ensure it can be called in as many contexts as possible. +//go:nosplit +func assertWorldStopped() { + if checkWorldStopped() { + return + } + + throw("world not stopped") +} + +// assertWorldStoppedOrLockHeld throws if the world is not stopped and the +// passed lock is not held. +// +// nosplit to ensure it can be called in as many contexts as possible. +//go:nosplit +func assertWorldStoppedOrLockHeld(l *mutex) { + if checkWorldStopped() { + return + } + + gp := getg() + systemstack(func() { + held := checkLockHeld(gp, l) + if !held { + printlock() + print("caller requires world stop or lock ", l, " (rank ", l.rank.String(), "), holding:\n") + println("") + printHeldLocks(gp) + throw("no world stop or required lock!") + } + }) +} diff --git a/src/runtime/mcheckmark.go b/src/runtime/mcheckmark.go index c0b028d7153..ba80ac1bdf4 100644 --- a/src/runtime/mcheckmark.go +++ b/src/runtime/mcheckmark.go @@ -34,6 +34,8 @@ var useCheckmark = false // // The world must be stopped. func startCheckmarks() { + assertWorldStopped() + // Clear all checkmarks. for _, ai := range mheap_.allArenas { arena := mheap_.arenas[ai.l1()][ai.l2()] diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index 9d2682f03cf..fb3c1499423 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -2164,6 +2164,8 @@ func gcMark(start_time int64) { // //go:systemstack func gcSweep(mode gcMode) { + assertWorldStopped() + if gcphase != _GCoff { throw("gcSweep being done but phase is not GCoff") } diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go index c71c0e58d36..5a24cdac88a 100644 --- a/src/runtime/mgcmark.go +++ b/src/runtime/mgcmark.go @@ -54,6 +54,8 @@ const ( // // The world must be stopped. func gcMarkRootPrepare() { + assertWorldStopped() + work.nFlushCacheRoots = 0 // Compute how many data and BSS root blocks there are. @@ -1535,6 +1537,8 @@ func gcmarknewobject(span *mspan, obj, size, scanSize uintptr) { // // The world must be stopped. func gcMarkTinyAllocs() { + assertWorldStopped() + for _, p := range allp { c := p.mcache if c == nil || c.tiny == 0 { diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index 9b77ce635c3..83914356301 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -123,6 +123,8 @@ func (h *mheap) nextSpanForSweep() *mspan { // //go:nowritebarrier func finishsweep_m() { + assertWorldStopped() + // Sweeping must be complete before marking commences, so // sweep any unswept spans. If this is a concurrent GC, there // shouldn't be any spans left to sweep, so this should finish diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index e0a417d213e..3829355d7b4 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -601,6 +601,8 @@ func readGCStats_m(pauses *[]uint64) { // //go:nowritebarrier func updatememstats() { + assertWorldStopped() + // Flush mcaches to mcentral before doing anything else. // // Flushing to the mcentral may in general cause stats to @@ -706,6 +708,8 @@ func updatememstats() { // //go:nowritebarrier func flushmcache(i int) { + assertWorldStopped() + p := allp[i] c := p.mcache if c == nil { @@ -721,6 +725,8 @@ func flushmcache(i int) { // //go:nowritebarrier func flushallmcaches() { + assertWorldStopped() + for i := 0; i < int(gomaxprocs); i++ { flushmcache(i) } @@ -876,10 +882,10 @@ func (m *consistentHeapStats) release(c *mcache) { // unsafeRead aggregates the delta for this shard into out. // // Unsafe because it does so without any synchronization. The -// only safe time to call this is if the world is stopped or -// we're freezing the world or going down anyway (and we just -// want _some_ estimate). +// world must be stopped. func (m *consistentHeapStats) unsafeRead(out *heapStatsDelta) { + assertWorldStopped() + for i := range m.stats { out.merge(&m.stats[i]) } @@ -890,6 +896,8 @@ func (m *consistentHeapStats) unsafeRead(out *heapStatsDelta) { // Unsafe because the world must be stopped and values should // be donated elsewhere before clearing. func (m *consistentHeapStats) unsafeClear() { + assertWorldStopped() + for i := range m.stats { m.stats[i] = heapStatsDelta{} } diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 939757f3a72..82284e6cd6e 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -587,6 +587,9 @@ func schedinit() { sched.maxmcount = 10000 + // The world starts stopped. + worldStopped() + moduledataverify() stackinit() mallocinit() @@ -617,6 +620,9 @@ func schedinit() { } unlock(&sched.lock) + // World is effectively started now, as P's can run. + worldStarted() + // For cgocheck > 1, we turn on the write barrier at all times // and check all pointer writes. We can't do this until after // procresize because the write barrier needs a P. @@ -1082,9 +1088,13 @@ func stopTheWorldWithSema() { if bad != "" { throw(bad) } + + worldStopped() } func startTheWorldWithSema(emitTraceEvent bool) int64 { + assertWorldStopped() + mp := acquirem() // disable preemption because it can be holding p in a local var if netpollinited() { list := netpoll(0) // non-blocking @@ -1105,6 +1115,8 @@ func startTheWorldWithSema(emitTraceEvent bool) int64 { } unlock(&sched.lock) + worldStarted() + for p1 != nil { p := p1 p1 = p1.link.ptr() @@ -4539,6 +4551,7 @@ func (pp *p) init(id int32) { // sched.lock must be held and the world must be stopped. func (pp *p) destroy() { assertLockHeld(&sched.lock) + assertWorldStopped() // Move all runnable goroutines to the global queue for pp.runqhead != pp.runqtail { @@ -4629,6 +4642,7 @@ func (pp *p) destroy() { // Returns list of Ps with local work, they need to be scheduled by the caller. func procresize(nprocs int32) *p { assertLockHeld(&sched.lock) + assertWorldStopped() old := gomaxprocs if old < 0 || nprocs <= 0 { From 9393b5bae5944acebed3ab6f995926b7de3ce429 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 21 Aug 2020 11:59:55 -0400 Subject: [PATCH 296/403] runtime: add heap lock assertions Some functions that required holding the heap lock _or_ world stop have been simplified to simply requiring the heap lock. This is conceptually simpler and taking the heap lock during world stop is guaranteed to not contend. This was only done on functions already called on the systemstack to avoid too many extra systemstack calls in GC. Updates #40677 Change-Id: I15aa1dadcdd1a81aac3d2a9ecad6e7d0377befdc Reviewed-on: https://go-review.googlesource.com/c/go/+/250262 Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Austin Clements Trust: Michael Pratt --- src/runtime/export_test.go | 61 ++++++++++++++++++++++++++++++++++---- src/runtime/malloc.go | 2 ++ src/runtime/mgc.go | 4 +++ src/runtime/mgcscavenge.go | 18 +++++++++++ src/runtime/mheap.go | 29 ++++++++++++++---- src/runtime/mpagealloc.go | 22 ++++++++++++++ src/runtime/mpagecache.go | 14 ++++++++- src/runtime/proc.go | 2 ++ 8 files changed, 139 insertions(+), 13 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 4ca0420d2ab..44551dcaf14 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -743,7 +743,16 @@ func (c *PageCache) Alloc(npages uintptr) (uintptr, uintptr) { return (*pageCache)(c).alloc(npages) } func (c *PageCache) Flush(s *PageAlloc) { - (*pageCache)(c).flush((*pageAlloc)(s)) + cp := (*pageCache)(c) + sp := (*pageAlloc)(s) + + systemstack(func() { + // None of the tests need any higher-level locking, so we just + // take the lock internally. + lock(sp.mheapLock) + cp.flush(sp) + unlock(sp.mheapLock) + }) } // Expose chunk index type. @@ -754,13 +763,41 @@ type ChunkIdx chunkIdx type PageAlloc pageAlloc func (p *PageAlloc) Alloc(npages uintptr) (uintptr, uintptr) { - return (*pageAlloc)(p).alloc(npages) + pp := (*pageAlloc)(p) + + var addr, scav uintptr + systemstack(func() { + // None of the tests need any higher-level locking, so we just + // take the lock internally. + lock(pp.mheapLock) + addr, scav = pp.alloc(npages) + unlock(pp.mheapLock) + }) + return addr, scav } func (p *PageAlloc) AllocToCache() PageCache { - return PageCache((*pageAlloc)(p).allocToCache()) + pp := (*pageAlloc)(p) + + var c PageCache + systemstack(func() { + // None of the tests need any higher-level locking, so we just + // take the lock internally. + lock(pp.mheapLock) + c = PageCache(pp.allocToCache()) + unlock(pp.mheapLock) + }) + return c } func (p *PageAlloc) Free(base, npages uintptr) { - (*pageAlloc)(p).free(base, npages) + pp := (*pageAlloc)(p) + + systemstack(func() { + // None of the tests need any higher-level locking, so we just + // take the lock internally. + lock(pp.mheapLock) + pp.free(base, npages) + unlock(pp.mheapLock) + }) } func (p *PageAlloc) Bounds() (ChunkIdx, ChunkIdx) { return ChunkIdx((*pageAlloc)(p).start), ChunkIdx((*pageAlloc)(p).end) @@ -768,6 +805,8 @@ func (p *PageAlloc) Bounds() (ChunkIdx, ChunkIdx) { func (p *PageAlloc) Scavenge(nbytes uintptr, mayUnlock bool) (r uintptr) { pp := (*pageAlloc)(p) systemstack(func() { + // None of the tests need any higher-level locking, so we just + // take the lock internally. lock(pp.mheapLock) r = pp.scavenge(nbytes, mayUnlock) unlock(pp.mheapLock) @@ -926,7 +965,11 @@ func NewPageAlloc(chunks, scav map[ChunkIdx][]BitRange) *PageAlloc { addr := chunkBase(chunkIdx(i)) // Mark the chunk's existence in the pageAlloc. - p.grow(addr, pallocChunkBytes) + systemstack(func() { + lock(p.mheapLock) + p.grow(addr, pallocChunkBytes) + unlock(p.mheapLock) + }) // Initialize the bitmap and update pageAlloc metadata. chunk := p.chunkOf(chunkIndex(addr)) @@ -957,13 +1000,19 @@ func NewPageAlloc(chunks, scav map[ChunkIdx][]BitRange) *PageAlloc { } // Update heap metadata for the allocRange calls above. - p.update(addr, pallocChunkPages, false, false) + systemstack(func() { + lock(p.mheapLock) + p.update(addr, pallocChunkPages, false, false) + unlock(p.mheapLock) + }) } + systemstack(func() { lock(p.mheapLock) p.scavengeStartGen() unlock(p.mheapLock) }) + return (*PageAlloc)(p) } diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 0563f49d175..4b798d129c3 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -627,6 +627,8 @@ func mallocinit() { // // h must be locked. func (h *mheap) sysAlloc(n uintptr) (v unsafe.Pointer, size uintptr) { + assertLockHeld(&h.lock) + n = alignUp(n, heapArenaBytes) // First, try the arena pre-reservation. diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go index fb3c1499423..185d3201ca2 100644 --- a/src/runtime/mgc.go +++ b/src/runtime/mgc.go @@ -821,6 +821,8 @@ func pollFractionalWorkerExit() bool { // // mheap_.lock must be held or the world must be stopped. func gcSetTriggerRatio(triggerRatio float64) { + assertWorldStoppedOrLockHeld(&mheap_.lock) + // Compute the next GC goal, which is when the allocated heap // has grown by GOGC/100 over the heap marked by the last // cycle. @@ -960,6 +962,8 @@ func gcSetTriggerRatio(triggerRatio float64) { // // mheap_.lock must be held or the world must be stopped. func gcEffectiveGrowthRatio() float64 { + assertWorldStoppedOrLockHeld(&mheap_.lock) + egogc := float64(atomic.Load64(&memstats.next_gc)-memstats.heap_marked) / float64(memstats.heap_marked) if egogc < 0 { // Shouldn't happen, but just in case. diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index 5843ada981f..a242577bd9f 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -397,6 +397,8 @@ func bgscavenge(c chan int) { // //go:systemstack func (p *pageAlloc) scavenge(nbytes uintptr, mayUnlock bool) uintptr { + assertLockHeld(p.mheapLock) + var ( addrs addrRange gen uint32 @@ -446,6 +448,8 @@ func printScavTrace(gen uint32, released uintptr, forced bool) { // //go:systemstack func (p *pageAlloc) scavengeStartGen() { + assertLockHeld(p.mheapLock) + if debug.scavtrace > 0 { printScavTrace(p.scav.gen, p.scav.released, false) } @@ -495,6 +499,8 @@ func (p *pageAlloc) scavengeStartGen() { // //go:systemstack func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { + assertLockHeld(p.mheapLock) + // Start by reserving the minimum. r := p.scav.inUse.removeLast(p.scav.reservationBytes) @@ -525,6 +531,8 @@ func (p *pageAlloc) scavengeReserve() (addrRange, uint32) { // //go:systemstack func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) { + assertLockHeld(p.mheapLock) + if r.size() == 0 || gen != p.scav.gen { return } @@ -552,6 +560,8 @@ func (p *pageAlloc) scavengeUnreserve(r addrRange, gen uint32) { // //go:systemstack func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (uintptr, addrRange) { + assertLockHeld(p.mheapLock) + // Defensively check if we've recieved an empty address range. // If so, just return. if work.size() == 0 { @@ -610,6 +620,8 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui // If we found something, scavenge it and return! if npages != 0 { work.limit = offAddr{p.scavengeRangeLocked(maxChunk, base, npages)} + + assertLockHeld(p.mheapLock) // Must be locked on return. return uintptr(npages) * pageSize, work } } @@ -674,12 +686,16 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui base, npages := chunk.findScavengeCandidate(pallocChunkPages-1, minPages, maxPages) if npages > 0 { work.limit = offAddr{p.scavengeRangeLocked(candidateChunkIdx, base, npages)} + + assertLockHeld(p.mheapLock) // Must be locked on return. return uintptr(npages) * pageSize, work } // We were fooled, so let's continue from where we left off. work.limit = offAddr{chunkBase(candidateChunkIdx)} } + + assertLockHeld(p.mheapLock) // Must be locked on return. return 0, work } @@ -692,6 +708,8 @@ func (p *pageAlloc) scavengeOne(work addrRange, max uintptr, mayUnlock bool) (ui // // p.mheapLock must be held. func (p *pageAlloc) scavengeRangeLocked(ci chunkIdx, base, npages uint) uintptr { + assertLockHeld(p.mheapLock) + p.chunkOf(ci).scavenged.setRange(base, npages) // Compute the full address for the start of the range. diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 14a73c04917..66a59cb999a 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -483,10 +483,15 @@ func (s *mspan) layout() (size, n, total uintptr) { // indirect call from the fixalloc initializer, the compiler can't see // this. // +// The heap lock must be held. +// //go:nowritebarrierrec func recordspan(vh unsafe.Pointer, p unsafe.Pointer) { h := (*mheap)(vh) s := (*mspan)(p) + + assertLockHeld(&h.lock) + if len(h.allspans) >= cap(h.allspans) { n := 64 * 1024 / sys.PtrSize if n < cap(h.allspans)*3/2 { @@ -721,7 +726,7 @@ func (h *mheap) init() { // // reclaim implements the page-reclaimer half of the sweeper. // -// h must NOT be locked. +// h.lock must NOT be held. func (h *mheap) reclaim(npage uintptr) { // TODO(austin): Half of the time spent freeing spans is in // locking/unlocking the heap (even with low contention). We @@ -804,6 +809,8 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { // In particular, if a span were freed and merged concurrently // with this probing heapArena.spans, it would be possible to // observe arbitrary, stale span pointers. + assertLockHeld(&h.lock) + n0 := n var nFreed uintptr sg := h.sweepgen @@ -858,6 +865,8 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr { traceGCSweepSpan((n0 - nFreed) * pageSize) lock(&h.lock) } + + assertLockHeld(&h.lock) // Must be locked on return. return nFreed } @@ -1011,7 +1020,7 @@ func (h *mheap) allocNeedsZero(base, npage uintptr) (needZero bool) { // tryAllocMSpan attempts to allocate an mspan object from // the P-local cache, but may fail. // -// h need not be locked. +// h.lock need not be held. // // This caller must ensure that its P won't change underneath // it during this function. Currently to ensure that we enforce @@ -1035,7 +1044,7 @@ func (h *mheap) tryAllocMSpan() *mspan { // allocMSpanLocked allocates an mspan object. // -// h must be locked. +// h.lock must be held. // // allocMSpanLocked must be called on the system stack because // its caller holds the heap lock. See mheap for details. @@ -1044,6 +1053,8 @@ func (h *mheap) tryAllocMSpan() *mspan { // //go:systemstack func (h *mheap) allocMSpanLocked() *mspan { + assertLockHeld(&h.lock) + pp := getg().m.p.ptr() if pp == nil { // We don't have a p so just do the normal thing. @@ -1065,7 +1076,7 @@ func (h *mheap) allocMSpanLocked() *mspan { // freeMSpanLocked free an mspan object. // -// h must be locked. +// h.lock must be held. // // freeMSpanLocked must be called on the system stack because // its caller holds the heap lock. See mheap for details. @@ -1074,6 +1085,8 @@ func (h *mheap) allocMSpanLocked() *mspan { // //go:systemstack func (h *mheap) freeMSpanLocked(s *mspan) { + assertLockHeld(&h.lock) + pp := getg().m.p.ptr() // First try to free the mspan directly to the cache. if pp != nil && pp.mspancache.len < len(pp.mspancache.buf) { @@ -1097,7 +1110,7 @@ func (h *mheap) freeMSpanLocked(s *mspan) { // // The returned span is fully initialized. // -// h must not be locked. +// h.lock must not be held. // // allocSpan must be called on the system stack both because it acquires // the heap lock and because it must block GC transitions. @@ -1281,8 +1294,10 @@ HaveSpan: // Try to add at least npage pages of memory to the heap, // returning whether it worked. // -// h must be locked. +// h.lock must be held. func (h *mheap) grow(npage uintptr) bool { + assertLockHeld(&h.lock) + // We must grow the heap in whole palloc chunks. ask := alignUp(npage, pallocChunkPages) * pageSize @@ -1391,6 +1406,8 @@ func (h *mheap) freeManual(s *mspan, typ spanAllocType) { } func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { + assertLockHeld(&h.lock) + switch s.state.get() { case mSpanManual: if s.allocCount != 0 { diff --git a/src/runtime/mpagealloc.go b/src/runtime/mpagealloc.go index 2af1c97e0b0..dac1f399690 100644 --- a/src/runtime/mpagealloc.go +++ b/src/runtime/mpagealloc.go @@ -349,6 +349,8 @@ func (p *pageAlloc) chunkOf(ci chunkIdx) *pallocData { // // p.mheapLock must be held. func (p *pageAlloc) grow(base, size uintptr) { + assertLockHeld(p.mheapLock) + // Round up to chunks, since we can't deal with increments smaller // than chunks. Also, sysGrow expects aligned values. limit := alignUp(base+size, pallocChunkBytes) @@ -413,6 +415,8 @@ func (p *pageAlloc) grow(base, size uintptr) { // // p.mheapLock must be held. func (p *pageAlloc) update(base, npages uintptr, contig, alloc bool) { + assertLockHeld(p.mheapLock) + // base, limit, start, and end are inclusive. limit := base + npages*pageSize - 1 sc, ec := chunkIndex(base), chunkIndex(limit) @@ -499,6 +503,8 @@ func (p *pageAlloc) update(base, npages uintptr, contig, alloc bool) { // // p.mheapLock must be held. func (p *pageAlloc) allocRange(base, npages uintptr) uintptr { + assertLockHeld(p.mheapLock) + limit := base + npages*pageSize - 1 sc, ec := chunkIndex(base), chunkIndex(limit) si, ei := chunkPageIndex(base), chunkPageIndex(limit) @@ -534,6 +540,8 @@ func (p *pageAlloc) allocRange(base, npages uintptr) uintptr { // // p.mheapLock must be held. func (p *pageAlloc) findMappedAddr(addr offAddr) offAddr { + assertLockHeld(p.mheapLock) + // If we're not in a test, validate first by checking mheap_.arenas. // This is a fast path which is only safe to use outside of testing. ai := arenaIndex(addr.addr()) @@ -568,6 +576,8 @@ func (p *pageAlloc) findMappedAddr(addr offAddr) offAddr { // // p.mheapLock must be held. func (p *pageAlloc) find(npages uintptr) (uintptr, offAddr) { + assertLockHeld(p.mheapLock) + // Search algorithm. // // This algorithm walks each level l of the radix tree from the root level @@ -786,7 +796,13 @@ nextLevel: // should be ignored. // // p.mheapLock must be held. +// +// Must run on the system stack because p.mheapLock must be held. +// +//go:systemstack func (p *pageAlloc) alloc(npages uintptr) (addr uintptr, scav uintptr) { + assertLockHeld(p.mheapLock) + // If the searchAddr refers to a region which has a higher address than // any known chunk, then we know we're out of memory. if chunkIndex(p.searchAddr.addr()) >= p.end { @@ -841,7 +857,13 @@ Found: // free returns npages worth of memory starting at base back to the page heap. // // p.mheapLock must be held. +// +// Must run on the system stack because p.mheapLock must be held. +// +//go:systemstack func (p *pageAlloc) free(base, npages uintptr) { + assertLockHeld(p.mheapLock) + // If we're freeing pages below the p.searchAddr, update searchAddr. if b := (offAddr{base}); b.lessThan(p.searchAddr) { p.searchAddr = b diff --git a/src/runtime/mpagecache.go b/src/runtime/mpagecache.go index 5f76501a1c6..4b5c66d8d6e 100644 --- a/src/runtime/mpagecache.go +++ b/src/runtime/mpagecache.go @@ -71,8 +71,14 @@ func (c *pageCache) allocN(npages uintptr) (uintptr, uintptr) { // into s. Then, it clears the cache, such that empty returns // true. // -// p.mheapLock must be held or the world must be stopped. +// p.mheapLock must be held. +// +// Must run on the system stack because p.mheapLock must be held. +// +//go:systemstack func (c *pageCache) flush(p *pageAlloc) { + assertLockHeld(p.mheapLock) + if c.empty() { return } @@ -103,7 +109,13 @@ func (c *pageCache) flush(p *pageAlloc) { // chunk. // // p.mheapLock must be held. +// +// Must run on the system stack because p.mheapLock must be held. +// +//go:systemstack func (p *pageAlloc) allocToCache() pageCache { + assertLockHeld(p.mheapLock) + // If the searchAddr refers to a region which has a higher address than // any known chunk, then we know we're out of memory. if chunkIndex(p.searchAddr.addr()) >= p.end { diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 82284e6cd6e..ced27ceb3af 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4603,7 +4603,9 @@ func (pp *p) destroy() { mheap_.spanalloc.free(unsafe.Pointer(pp.mspancache.buf[i])) } pp.mspancache.len = 0 + lock(&mheap_.lock) pp.pcache.flush(&mheap_.pages) + unlock(&mheap_.lock) }) freemcache(pp.mcache) pp.mcache = nil From 89a6540d8a93b95620080a8145c9882b063e3e46 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Thu, 29 Oct 2020 16:03:57 -0400 Subject: [PATCH 297/403] runtime: elide timer re-check if P has no timers In golang.org/cl/264477, I missed this new block after rebasing past golang.org/cl/232298. These fields must be zero if there are no timers. Updates #28808 Updates #18237 Change-Id: I2d9e1cbf326497c833daa26b11aed9a1e12c2270 Reviewed-on: https://go-review.googlesource.com/c/go/+/266367 Run-TryBot: Michael Pratt Reviewed-by: Austin Clements Reviewed-by: Ian Lance Taylor Reviewed-by: Michael Knyszek TryBot-Result: Go Bot Trust: Michael Pratt --- src/runtime/proc.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index ced27ceb3af..071257b5a50 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -2606,9 +2606,10 @@ stop: // safe-points. We don't need to snapshot the contents because // everything up to cap(allp) is immutable. allpSnapshot := allp - // Also snapshot idlepMask. Value changes are OK, but we can't allow + // Also snapshot masks. Value changes are OK, but we can't allow // len to change out from under us. idlepMaskSnapshot := idlepMask + timerpMaskSnapshot := timerpMask // return P and block lock(&sched.lock) @@ -2670,10 +2671,12 @@ stop: // transitioning from spinning to non-spinning. Note that we cannot use // checkTimers here because it calls adjusttimers which may need to allocate // memory, and that isn't allowed when we don't have an active P. - for _, _p_ := range allpSnapshot { - w := nobarrierWakeTime(_p_) - if w != 0 && (pollUntil == 0 || w < pollUntil) { - pollUntil = w + for id, _p_ := range allpSnapshot { + if timerpMaskSnapshot.read(uint32(id)) { + w := nobarrierWakeTime(_p_) + if w != 0 && (pollUntil == 0 || w < pollUntil) { + pollUntil = w + } } } if pollUntil != 0 { From 84d7a85089009332756c18e876ec91f96b362ebf Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 21 Oct 2020 20:15:48 -0400 Subject: [PATCH 298/403] cmd/compile: delete register maps, completely Remove go115ReduceLiveness feature gating flag, along with code that only needed when go115ReduceLiveness is false. Change-Id: I7571913cc74cbd17b330a0ee0160fefc9eeee66e Reviewed-on: https://go-review.googlesource.com/c/go/+/264338 Trust: Cherry Zhang Run-TryBot: Cherry Zhang Reviewed-by: Austin Clements --- src/cmd/compile/fmtmap_test.go | 2 - src/cmd/compile/internal/gc/gsubr.go | 40 +-- src/cmd/compile/internal/gc/obj.go | 2 +- src/cmd/compile/internal/gc/plive.go | 423 ++++----------------------- src/cmd/compile/internal/gc/ssa.go | 2 +- src/cmd/internal/obj/link.go | 1 - src/cmd/internal/obj/plist.go | 22 +- src/cmd/internal/objabi/funcdata.go | 9 +- 8 files changed, 88 insertions(+), 413 deletions(-) diff --git a/src/cmd/compile/fmtmap_test.go b/src/cmd/compile/fmtmap_test.go index 179c60187fe..0811df7f7b8 100644 --- a/src/cmd/compile/fmtmap_test.go +++ b/src/cmd/compile/fmtmap_test.go @@ -105,10 +105,8 @@ var knownFormats = map[string]string{ "cmd/compile/internal/ssa.GCNode %v": "", "cmd/compile/internal/ssa.ID %d": "", "cmd/compile/internal/ssa.ID %v": "", - "cmd/compile/internal/ssa.LocPair %s": "", "cmd/compile/internal/ssa.LocalSlot %s": "", "cmd/compile/internal/ssa.LocalSlot %v": "", - "cmd/compile/internal/ssa.Location %T": "", "cmd/compile/internal/ssa.Location %s": "", "cmd/compile/internal/ssa.Op %s": "", "cmd/compile/internal/ssa.Op %v": "", diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index ce5182f2032..864ada1d3cd 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -70,12 +70,8 @@ func newProgs(fn *Node, worker int) *Progs { pp.pos = fn.Pos pp.settext(fn) // PCDATA tables implicitly start with index -1. - pp.prevLive = LivenessIndex{-1, -1, false} - if go115ReduceLiveness { - pp.nextLive = pp.prevLive - } else { - pp.nextLive = LivenessInvalid - } + pp.prevLive = LivenessIndex{-1, false} + pp.nextLive = pp.prevLive return pp } @@ -120,31 +116,15 @@ func (pp *Progs) Prog(as obj.As) *obj.Prog { Addrconst(&p.From, objabi.PCDATA_StackMapIndex) Addrconst(&p.To, int64(idx)) } - if !go115ReduceLiveness { + if pp.nextLive.isUnsafePoint != pp.prevLive.isUnsafePoint { + // Emit unsafe-point marker. + pp.prevLive.isUnsafePoint = pp.nextLive.isUnsafePoint + p := pp.Prog(obj.APCDATA) + Addrconst(&p.From, objabi.PCDATA_UnsafePoint) if pp.nextLive.isUnsafePoint { - // Unsafe points are encoded as a special value in the - // register map. - pp.nextLive.regMapIndex = objabi.PCDATA_RegMapUnsafe - } - if pp.nextLive.regMapIndex != pp.prevLive.regMapIndex { - // Emit register map index change. - idx := pp.nextLive.regMapIndex - pp.prevLive.regMapIndex = idx - p := pp.Prog(obj.APCDATA) - Addrconst(&p.From, objabi.PCDATA_RegMapIndex) - Addrconst(&p.To, int64(idx)) - } - } else { - if pp.nextLive.isUnsafePoint != pp.prevLive.isUnsafePoint { - // Emit unsafe-point marker. - pp.prevLive.isUnsafePoint = pp.nextLive.isUnsafePoint - p := pp.Prog(obj.APCDATA) - Addrconst(&p.From, objabi.PCDATA_UnsafePoint) - if pp.nextLive.isUnsafePoint { - Addrconst(&p.To, objabi.PCDATA_UnsafePointUnsafe) - } else { - Addrconst(&p.To, objabi.PCDATA_UnsafePointSafe) - } + Addrconst(&p.To, objabi.PCDATA_UnsafePointUnsafe) + } else { + Addrconst(&p.To, objabi.PCDATA_UnsafePointSafe) } } diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 226eb452524..32aa7c5bb1a 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -312,7 +312,7 @@ func addGCLocals() { if fn == nil { continue } - for _, gcsym := range []*obj.LSym{fn.GCArgs, fn.GCLocals, fn.GCRegs} { + for _, gcsym := range []*obj.LSym{fn.GCArgs, fn.GCLocals} { if gcsym != nil && !gcsym.OnList() { ggloblsym(gcsym, int32(len(gcsym.P)), obj.RODATA|obj.DUPOK) } diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index b471accb658..a48173e0d65 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -24,16 +24,6 @@ import ( "strings" ) -// go115ReduceLiveness disables register maps and only produces stack -// maps at call sites. -// -// In Go 1.15, we changed debug call injection to use conservative -// scanning instead of precise pointer maps, so these are no longer -// necessary. -// -// Keep in sync with runtime/preempt.go:go115ReduceLiveness. -const go115ReduceLiveness = true - // OpVarDef is an annotation for the liveness analysis, marking a place // where a complete initialization (definition) of a variable begins. // Since the liveness analysis can see initialization of single-word @@ -96,15 +86,15 @@ type BlockEffects struct { // // uevar: upward exposed variables (used before set in block) // varkill: killed variables (set in block) - uevar varRegVec - varkill varRegVec + uevar bvec + varkill bvec // Computed during Liveness.solve using control flow information: // // livein: variables live at block entry // liveout: variables live at block exit - livein varRegVec - liveout varRegVec + livein bvec + liveout bvec } // A collection of global state used by liveness analysis. @@ -128,16 +118,14 @@ type Liveness struct { // current Block during Liveness.epilogue. Indexed in Value // order for that block. Additionally, for the entry block // livevars[0] is the entry bitmap. Liveness.compact moves - // these to stackMaps and regMaps. - livevars []varRegVec + // these to stackMaps. + livevars []bvec // livenessMap maps from safe points (i.e., CALLs) to their // liveness map indexes. livenessMap LivenessMap stackMapSet bvecSet stackMaps []bvec - regMapSet map[liveRegMask]int - regMaps []liveRegMask cache progeffectscache } @@ -158,7 +146,7 @@ func (m *LivenessMap) reset() { delete(m.vals, k) } } - m.deferreturn = LivenessInvalid + m.deferreturn = LivenessDontCare } func (m *LivenessMap) set(v *ssa.Value, i LivenessIndex) { @@ -166,27 +154,17 @@ func (m *LivenessMap) set(v *ssa.Value, i LivenessIndex) { } func (m LivenessMap) Get(v *ssa.Value) LivenessIndex { - if !go115ReduceLiveness { - // All safe-points are in the map, so if v isn't in - // the map, it's an unsafe-point. - if idx, ok := m.vals[v.ID]; ok { - return idx - } - return LivenessInvalid - } - // If v isn't in the map, then it's a "don't care" and not an // unsafe-point. if idx, ok := m.vals[v.ID]; ok { return idx } - return LivenessIndex{StackMapDontCare, StackMapDontCare, false} + return LivenessIndex{StackMapDontCare, false} } // LivenessIndex stores the liveness map information for a Value. type LivenessIndex struct { stackMapIndex int - regMapIndex int // only for !go115ReduceLiveness // isUnsafePoint indicates that this is an unsafe-point. // @@ -197,8 +175,10 @@ type LivenessIndex struct { isUnsafePoint bool } -// LivenessInvalid indicates an unsafe point with no stack map. -var LivenessInvalid = LivenessIndex{StackMapDontCare, StackMapDontCare, true} // only for !go115ReduceLiveness +// LivenessDontCare indicates that the liveness information doesn't +// matter. Currently it is used in deferreturn liveness when we don't +// actually need it. It should never be emitted to the PCDATA stream. +var LivenessDontCare = LivenessIndex{StackMapDontCare, true} // StackMapDontCare indicates that the stack map index at a Value // doesn't matter. @@ -212,46 +192,12 @@ func (idx LivenessIndex) StackMapValid() bool { return idx.stackMapIndex != StackMapDontCare } -func (idx LivenessIndex) RegMapValid() bool { - return idx.regMapIndex != StackMapDontCare -} - type progeffectscache struct { retuevar []int32 tailuevar []int32 initialized bool } -// varRegVec contains liveness bitmaps for variables and registers. -type varRegVec struct { - vars bvec - regs liveRegMask -} - -func (v *varRegVec) Eq(v2 varRegVec) bool { - return v.vars.Eq(v2.vars) && v.regs == v2.regs -} - -func (v *varRegVec) Copy(v2 varRegVec) { - v.vars.Copy(v2.vars) - v.regs = v2.regs -} - -func (v *varRegVec) Clear() { - v.vars.Clear() - v.regs = 0 -} - -func (v *varRegVec) Or(v1, v2 varRegVec) { - v.vars.Or(v1.vars, v2.vars) - v.regs = v1.regs | v2.regs -} - -func (v *varRegVec) AndNot(v1, v2 varRegVec) { - v.vars.AndNot(v1.vars, v2.vars) - v.regs = v1.regs &^ v2.regs -} - // livenessShouldTrack reports whether the liveness analysis // should track the variable n. // We don't care about variables that have no pointers, @@ -400,110 +346,6 @@ func affectedNode(v *ssa.Value) (*Node, ssa.SymEffect) { } } -// regEffects returns the registers affected by v. -func (lv *Liveness) regEffects(v *ssa.Value) (uevar, kill liveRegMask) { - if go115ReduceLiveness { - return 0, 0 - } - if v.Op == ssa.OpPhi { - // All phi node arguments must come from the same - // register and the result must also go to that - // register, so there's no overall effect. - return 0, 0 - } - addLocs := func(mask liveRegMask, v *ssa.Value, ptrOnly bool) liveRegMask { - if int(v.ID) >= len(lv.f.RegAlloc) { - // v has no allocated registers. - return mask - } - loc := lv.f.RegAlloc[v.ID] - if loc == nil { - // v has no allocated registers. - return mask - } - if v.Op == ssa.OpGetG { - // GetG represents the G register, which is a - // pointer, but not a valid GC register. The - // current G is always reachable, so it's okay - // to ignore this register. - return mask - } - - // Collect registers and types from v's location. - var regs [2]*ssa.Register - nreg := 0 - switch loc := loc.(type) { - case ssa.LocalSlot: - return mask - case *ssa.Register: - if ptrOnly && !v.Type.HasPointers() { - return mask - } - regs[0] = loc - nreg = 1 - case ssa.LocPair: - // The value will have TTUPLE type, and the - // children are nil or *ssa.Register. - if v.Type.Etype != types.TTUPLE { - v.Fatalf("location pair %s has non-tuple type %v", loc, v.Type) - } - for i, loc1 := range &loc { - if loc1 == nil { - continue - } - if ptrOnly && !v.Type.FieldType(i).HasPointers() { - continue - } - regs[nreg] = loc1.(*ssa.Register) - nreg++ - } - default: - v.Fatalf("weird RegAlloc location: %s (%T)", loc, loc) - } - - // Add register locations to vars. - for _, reg := range regs[:nreg] { - if reg.GCNum() == -1 { - if ptrOnly { - v.Fatalf("pointer in non-pointer register %v", reg) - } else { - continue - } - } - mask |= 1 << uint(reg.GCNum()) - } - return mask - } - - // v clobbers all registers it writes to (whether or not the - // write is pointer-typed). - kill = addLocs(0, v, false) - for _, arg := range v.Args { - // v uses all registers is reads from, but we only - // care about marking those containing pointers. - uevar = addLocs(uevar, arg, true) - } - return uevar, kill -} - -type liveRegMask uint32 // only if !go115ReduceLiveness - -func (m liveRegMask) niceString(config *ssa.Config) string { - if m == 0 { - return "" - } - str := "" - for i, reg := range config.GCRegMap { - if m&(1<= f.NumBlocks() { lv.be = lc.be[:f.NumBlocks()] } - lv.livenessMap = LivenessMap{vals: lc.livenessMap.vals, deferreturn: LivenessInvalid} + lv.livenessMap = LivenessMap{vals: lc.livenessMap.vals, deferreturn: LivenessDontCare} lc.livenessMap.vals = nil } if lv.be == nil { @@ -546,10 +386,10 @@ func newliveness(fn *Node, f *ssa.Func, vars []*Node, idx map[*Node]int32, stkpt for _, b := range f.Blocks { be := lv.blockEffects(b) - be.uevar = varRegVec{vars: bulk.next()} - be.varkill = varRegVec{vars: bulk.next()} - be.livein = varRegVec{vars: bulk.next()} - be.liveout = varRegVec{vars: bulk.next()} + be.uevar = bulk.next() + be.varkill = bulk.next() + be.livein = bulk.next() + be.liveout = bulk.next() } lv.livenessMap.reset() @@ -637,20 +477,6 @@ func onebitwalktype1(t *types.Type, off int64, bv bvec) { } } -// usedRegs returns the maximum width of the live register map. -func (lv *Liveness) usedRegs() int32 { - var any liveRegMask - for _, live := range lv.regMaps { - any |= live - } - i := int32(0) - for any != 0 { - any >>= 1 - i++ - } - return i -} - // Generates live pointer value maps for arguments and local variables. The // this argument and the in arguments are always assumed live. The vars // argument is a slice of *Nodes. @@ -851,31 +677,16 @@ func (lv *Liveness) markUnsafePoints() { // particular, call Values can have a stack map in case the callee // grows the stack, but not themselves be a safe-point. func (lv *Liveness) hasStackMap(v *ssa.Value) bool { - // The runtime only has safe-points in function prologues, so - // we only need stack maps at call sites. go:nosplit functions - // are similar. - if go115ReduceLiveness || compiling_runtime || lv.f.NoSplit { - if !v.Op.IsCall() { - return false - } - // typedmemclr and typedmemmove are write barriers and - // deeply non-preemptible. They are unsafe points and - // hence should not have liveness maps. - if sym, ok := v.Aux.(*ssa.AuxCall); ok && (sym.Fn == typedmemclr || sym.Fn == typedmemmove) { - return false - } - return true - } - - switch v.Op { - case ssa.OpInitMem, ssa.OpArg, ssa.OpSP, ssa.OpSB, - ssa.OpSelect0, ssa.OpSelect1, ssa.OpGetG, - ssa.OpVarDef, ssa.OpVarLive, ssa.OpKeepAlive, - ssa.OpPhi: - // These don't produce code (see genssa). + if !v.Op.IsCall() { return false } - return !lv.unsafePoints.Get(int32(v.ID)) + // typedmemclr and typedmemmove are write barriers and + // deeply non-preemptible. They are unsafe points and + // hence should not have liveness maps. + if sym, ok := v.Aux.(*ssa.AuxCall); ok && (sym.Fn == typedmemclr || sym.Fn == typedmemmove) { + return false + } + return true } // Initializes the sets for solving the live variables. Visits all the @@ -891,17 +702,13 @@ func (lv *Liveness) prologue() { // effects with the each prog effects. for j := len(b.Values) - 1; j >= 0; j-- { pos, e := lv.valueEffects(b.Values[j]) - regUevar, regKill := lv.regEffects(b.Values[j]) if e&varkill != 0 { - be.varkill.vars.Set(pos) - be.uevar.vars.Unset(pos) + be.varkill.Set(pos) + be.uevar.Unset(pos) } - be.varkill.regs |= regKill - be.uevar.regs &^= regKill if e&uevar != 0 { - be.uevar.vars.Set(pos) + be.uevar.Set(pos) } - be.uevar.regs |= regUevar } } } @@ -911,8 +718,8 @@ func (lv *Liveness) solve() { // These temporary bitvectors exist to avoid successive allocations and // frees within the loop. nvars := int32(len(lv.vars)) - newlivein := varRegVec{vars: bvalloc(nvars)} - newliveout := varRegVec{vars: bvalloc(nvars)} + newlivein := bvalloc(nvars) + newliveout := bvalloc(nvars) // Walk blocks in postorder ordering. This improves convergence. po := lv.f.Postorder() @@ -930,11 +737,11 @@ func (lv *Liveness) solve() { switch b.Kind { case ssa.BlockRet: for _, pos := range lv.cache.retuevar { - newliveout.vars.Set(pos) + newliveout.Set(pos) } case ssa.BlockRetJmp: for _, pos := range lv.cache.tailuevar { - newliveout.vars.Set(pos) + newliveout.Set(pos) } case ssa.BlockExit: // panic exit - nothing to do @@ -969,7 +776,7 @@ func (lv *Liveness) solve() { // variables at each safe point locations. func (lv *Liveness) epilogue() { nvars := int32(len(lv.vars)) - liveout := varRegVec{vars: bvalloc(nvars)} + liveout := bvalloc(nvars) livedefer := bvalloc(nvars) // always-live variables // If there is a defer (that could recover), then all output @@ -1025,12 +832,11 @@ func (lv *Liveness) epilogue() { { // Reserve an entry for function entry. live := bvalloc(nvars) - lv.livevars = append(lv.livevars, varRegVec{vars: live}) + lv.livevars = append(lv.livevars, live) } for _, b := range lv.f.Blocks { be := lv.blockEffects(b) - firstBitmapIndex := len(lv.livevars) // Walk forward through the basic block instructions and // allocate liveness maps for those instructions that need them. @@ -1040,7 +846,7 @@ func (lv *Liveness) epilogue() { } live := bvalloc(nvars) - lv.livevars = append(lv.livevars, varRegVec{vars: live}) + lv.livevars = append(lv.livevars, live) } // walk backward, construct maps at each safe point @@ -1056,21 +862,18 @@ func (lv *Liveness) epilogue() { live := &lv.livevars[index] live.Or(*live, liveout) - live.vars.Or(live.vars, livedefer) // only for non-entry safe points + live.Or(*live, livedefer) // only for non-entry safe points index-- } // Update liveness information. pos, e := lv.valueEffects(v) - regUevar, regKill := lv.regEffects(v) if e&varkill != 0 { - liveout.vars.Unset(pos) + liveout.Unset(pos) } - liveout.regs &^= regKill if e&uevar != 0 { - liveout.vars.Set(pos) + liveout.Set(pos) } - liveout.regs |= regUevar } if b == lv.f.Entry { @@ -1080,7 +883,7 @@ func (lv *Liveness) epilogue() { // Check to make sure only input variables are live. for i, n := range lv.vars { - if !liveout.vars.Get(int32(i)) { + if !liveout.Get(int32(i)) { continue } if n.Class() == PPARAM { @@ -1094,32 +897,16 @@ func (lv *Liveness) epilogue() { live.Or(*live, liveout) } - // Check that no registers are live across calls. - // For closure calls, the CALLclosure is the last use - // of the context register, so it's dead after the call. - index = int32(firstBitmapIndex) - for _, v := range b.Values { - if lv.hasStackMap(v) { - live := lv.livevars[index] - if v.Op.IsCall() && live.regs != 0 { - lv.printDebug() - v.Fatalf("%v register %s recorded as live at call", lv.fn.Func.Nname, live.regs.niceString(lv.f.Config)) - } - index++ - } - } - // The liveness maps for this block are now complete. Compact them. lv.compact(b) } // If we have an open-coded deferreturn call, make a liveness map for it. if lv.fn.Func.OpenCodedDeferDisallowed() { - lv.livenessMap.deferreturn = LivenessInvalid + lv.livenessMap.deferreturn = LivenessDontCare } else { lv.livenessMap.deferreturn = LivenessIndex{ stackMapIndex: lv.stackMapSet.add(livedefer), - regMapIndex: 0, // entry regMap, containing no live registers isUnsafePoint: false, } } @@ -1136,20 +923,10 @@ func (lv *Liveness) epilogue() { lv.f.Fatalf("%v %L recorded as live on entry", lv.fn.Func.Nname, n) } } - if !go115ReduceLiveness { - // Check that no registers are live at function entry. - // The context register, if any, comes from a - // LoweredGetClosurePtr operation first thing in the function, - // so it doesn't appear live at entry. - if regs := lv.regMaps[0]; regs != 0 { - lv.printDebug() - lv.f.Fatalf("%v register %s recorded as live on entry", lv.fn.Func.Nname, regs.niceString(lv.f.Config)) - } - } } // Compact coalesces identical bitmaps from lv.livevars into the sets -// lv.stackMapSet and lv.regMaps. +// lv.stackMapSet. // // Compact clears lv.livevars. // @@ -1165,45 +942,23 @@ func (lv *Liveness) epilogue() { // PCDATA tables cost about 100k. So for now we keep using a single index for // both bitmap lists. func (lv *Liveness) compact(b *ssa.Block) { - add := func(live varRegVec, isUnsafePoint bool) LivenessIndex { // only if !go115ReduceLiveness - // Deduplicate the stack map. - stackIndex := lv.stackMapSet.add(live.vars) - // Deduplicate the register map. - regIndex, ok := lv.regMapSet[live.regs] - if !ok { - regIndex = len(lv.regMapSet) - lv.regMapSet[live.regs] = regIndex - lv.regMaps = append(lv.regMaps, live.regs) - } - return LivenessIndex{stackIndex, regIndex, isUnsafePoint} - } pos := 0 if b == lv.f.Entry { // Handle entry stack map. - if !go115ReduceLiveness { - add(lv.livevars[0], false) - } else { - lv.stackMapSet.add(lv.livevars[0].vars) - } + lv.stackMapSet.add(lv.livevars[0]) pos++ } for _, v := range b.Values { - if go115ReduceLiveness { - hasStackMap := lv.hasStackMap(v) - isUnsafePoint := lv.allUnsafe || lv.unsafePoints.Get(int32(v.ID)) - idx := LivenessIndex{StackMapDontCare, StackMapDontCare, isUnsafePoint} - if hasStackMap { - idx.stackMapIndex = lv.stackMapSet.add(lv.livevars[pos].vars) - pos++ - } - if hasStackMap || isUnsafePoint { - lv.livenessMap.set(v, idx) - } - } else if lv.hasStackMap(v) { - isUnsafePoint := lv.allUnsafe || lv.unsafePoints.Get(int32(v.ID)) - lv.livenessMap.set(v, add(lv.livevars[pos], isUnsafePoint)) + hasStackMap := lv.hasStackMap(v) + isUnsafePoint := lv.allUnsafe || lv.unsafePoints.Get(int32(v.ID)) + idx := LivenessIndex{StackMapDontCare, isUnsafePoint} + if hasStackMap { + idx.stackMapIndex = lv.stackMapSet.add(lv.livevars[pos]) pos++ } + if hasStackMap || isUnsafePoint { + lv.livenessMap.set(v, idx) + } } // Reset livevars. @@ -1250,8 +1005,8 @@ func (lv *Liveness) showlive(v *ssa.Value, live bvec) { Warnl(pos, s) } -func (lv *Liveness) printbvec(printed bool, name string, live varRegVec) bool { - if live.vars.IsEmpty() && live.regs == 0 { +func (lv *Liveness) printbvec(printed bool, name string, live bvec) bool { + if live.IsEmpty() { return printed } @@ -1264,19 +1019,18 @@ func (lv *Liveness) printbvec(printed bool, name string, live varRegVec) bool { comma := "" for i, n := range lv.vars { - if !live.vars.Get(int32(i)) { + if !live.Get(int32(i)) { continue } fmt.Printf("%s%s", comma, n.Sym.Name) comma = "," } - fmt.Printf("%s%s", comma, live.regs.niceString(lv.f.Config)) return true } -// printeffect is like printbvec, but for valueEffects and regEffects. -func (lv *Liveness) printeffect(printed bool, name string, pos int32, x bool, regMask liveRegMask) bool { - if !x && regMask == 0 { +// printeffect is like printbvec, but for valueEffects. +func (lv *Liveness) printeffect(printed bool, name string, pos int32, x bool) bool { + if !x { return printed } if !printed { @@ -1288,15 +1042,7 @@ func (lv *Liveness) printeffect(printed bool, name string, pos int32, x bool, re if x { fmt.Printf("%s", lv.vars[pos].Sym.Name) } - for j, reg := range lv.f.Config.GCRegMap { - if regMask&(1< 32 { - // Our uint32 conversion below won't work. - Fatalf("GP registers overflow uint32") - } - - if regs.n > 0 { - for _, live := range lv.regMaps { - regs.Clear() - regs.b[0] = uint32(live) - roff = dbvec(®sSymTmp, roff, regs) - } - } - } - // Give these LSyms content-addressable names, // so that they can be de-duplicated. // This provides significant binary size savings. @@ -1502,11 +1219,7 @@ func (lv *Liveness) emit() (argsSym, liveSym, regsSym *obj.LSym) { lsym.Set(obj.AttrContentAddressable, true) }) } - if !go115ReduceLiveness { - return makeSym(&argsSymTmp), makeSym(&liveSymTmp), makeSym(®sSymTmp) - } - // TODO(go115ReduceLiveness): Remove regsSym result - return makeSym(&argsSymTmp), makeSym(&liveSymTmp), nil + return makeSym(&argsSymTmp), makeSym(&liveSymTmp) } // Entry pointer for liveness analysis. Solves for the liveness of @@ -1553,7 +1266,7 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap { // Emit the live pointer map data structures ls := e.curfn.Func.lsym fninfo := ls.Func() - fninfo.GCArgs, fninfo.GCLocals, fninfo.GCRegs = lv.emit() + fninfo.GCArgs, fninfo.GCLocals = lv.emit() p := pp.Prog(obj.AFUNCDATA) Addrconst(&p.From, objabi.FUNCDATA_ArgsPointerMaps) @@ -1567,14 +1280,6 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap { p.To.Name = obj.NAME_EXTERN p.To.Sym = fninfo.GCLocals - if !go115ReduceLiveness { - p = pp.Prog(obj.AFUNCDATA) - Addrconst(&p.From, objabi.FUNCDATA_RegPointerMaps) - p.To.Type = obj.TYPE_MEM - p.To.Name = obj.NAME_EXTERN - p.To.Sym = fninfo.GCRegs - } - return lv.livenessMap } diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 7388e4e3e83..67484904a95 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -6265,7 +6265,7 @@ func genssa(f *ssa.Func, pp *Progs) { // instruction. We won't use the actual liveness map on a // control instruction. Just mark it something that is // preemptible, unless this function is "all unsafe". - s.pp.nextLive = LivenessIndex{-1, -1, allUnsafe(f)} + s.pp.nextLive = LivenessIndex{-1, allUnsafe(f)} // Emit values in block thearch.SSAMarkMoves(&s, b) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index c652e3adbba..8c8ff587ffc 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -460,7 +460,6 @@ type FuncInfo struct { GCArgs *LSym GCLocals *LSym - GCRegs *LSym // Only if !go115ReduceLiveness StackObjects *LSym OpenCodedDeferInfo *LSym diff --git a/src/cmd/internal/obj/plist.go b/src/cmd/internal/obj/plist.go index eb54c67f6ae..2b096996f7a 100644 --- a/src/cmd/internal/obj/plist.go +++ b/src/cmd/internal/obj/plist.go @@ -178,7 +178,7 @@ func (ctxt *Link) Globl(s *LSym, size int64, flag int) { // Prog generated. func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog { pcdata := ctxt.EmitEntryStackMap(s, p, newprog) - pcdata = ctxt.EmitEntryRegMap(s, pcdata, newprog) + pcdata = ctxt.EmitEntryUnsafePoint(s, pcdata, newprog) return pcdata } @@ -195,13 +195,13 @@ func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog { return pcdata } -// Similar to EmitEntryLiveness, but just emit register map. -func (ctxt *Link) EmitEntryRegMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog { +// Similar to EmitEntryLiveness, but just emit unsafe point map. +func (ctxt *Link) EmitEntryUnsafePoint(s *LSym, p *Prog, newprog ProgAlloc) *Prog { pcdata := Appendp(p, newprog) pcdata.Pos = s.Func().Text.Pos pcdata.As = APCDATA pcdata.From.Type = TYPE_CONST - pcdata.From.Offset = objabi.PCDATA_RegMapIndex + pcdata.From.Offset = objabi.PCDATA_UnsafePoint pcdata.To.Type = TYPE_CONST pcdata.To.Offset = -1 @@ -216,9 +216,9 @@ func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog { pcdata := Appendp(p, newprog) pcdata.As = APCDATA pcdata.From.Type = TYPE_CONST - pcdata.From.Offset = objabi.PCDATA_RegMapIndex + pcdata.From.Offset = objabi.PCDATA_UnsafePoint pcdata.To.Type = TYPE_CONST - pcdata.To.Offset = objabi.PCDATA_RegMapUnsafe + pcdata.To.Offset = objabi.PCDATA_UnsafePointUnsafe return pcdata } @@ -231,7 +231,7 @@ func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog pcdata := Appendp(p, newprog) pcdata.As = APCDATA pcdata.From.Type = TYPE_CONST - pcdata.From.Offset = objabi.PCDATA_RegMapIndex + pcdata.From.Offset = objabi.PCDATA_UnsafePoint pcdata.To.Type = TYPE_CONST pcdata.To.Offset = oldval @@ -257,11 +257,11 @@ func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, is prevPcdata := int64(-1) // entry PC data value prevRestart := int64(0) for p := prev.Link; p != nil; p, prev = p.Link, p { - if p.As == APCDATA && p.From.Offset == objabi.PCDATA_RegMapIndex { + if p.As == APCDATA && p.From.Offset == objabi.PCDATA_UnsafePoint { prevPcdata = p.To.Offset continue } - if prevPcdata == objabi.PCDATA_RegMapUnsafe { + if prevPcdata == objabi.PCDATA_UnsafePointUnsafe { continue // already unsafe } if isUnsafePoint(p) { @@ -288,7 +288,7 @@ func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, is q := Appendp(prev, newprog) q.As = APCDATA q.From.Type = TYPE_CONST - q.From.Offset = objabi.PCDATA_RegMapIndex + q.From.Offset = objabi.PCDATA_UnsafePoint q.To.Type = TYPE_CONST q.To.Offset = val q.Pc = p.Pc @@ -305,7 +305,7 @@ func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint, is p = Appendp(p, newprog) p.As = APCDATA p.From.Type = TYPE_CONST - p.From.Offset = objabi.PCDATA_RegMapIndex + p.From.Offset = objabi.PCDATA_UnsafePoint p.To.Type = TYPE_CONST p.To.Offset = prevPcdata p.Pc = p.Link.Pc diff --git a/src/cmd/internal/objabi/funcdata.go b/src/cmd/internal/objabi/funcdata.go index c9480bf2f01..1c5e5e1c8c4 100644 --- a/src/cmd/internal/objabi/funcdata.go +++ b/src/cmd/internal/objabi/funcdata.go @@ -11,14 +11,12 @@ package objabi // ../../../runtime/symtab.go. const ( - PCDATA_RegMapIndex = 0 // if !go115ReduceLiveness - PCDATA_UnsafePoint = 0 // if go115ReduceLiveness + PCDATA_UnsafePoint = 0 PCDATA_StackMapIndex = 1 PCDATA_InlTreeIndex = 2 FUNCDATA_ArgsPointerMaps = 0 FUNCDATA_LocalsPointerMaps = 1 - FUNCDATA_RegPointerMaps = 2 // if !go115ReduceLiveness FUNCDATA_StackObjects = 3 FUNCDATA_InlTree = 4 FUNCDATA_OpenCodedDeferInfo = 5 @@ -32,11 +30,6 @@ const ( // Special PCDATA values. const ( - // PCDATA_RegMapIndex values. - // - // Only if !go115ReduceLiveness. - PCDATA_RegMapUnsafe = PCDATA_UnsafePointUnsafe // Unsafe for async preemption - // PCDATA_UnsafePoint values. PCDATA_UnsafePointSafe = -1 // Safe for async preemption PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption From 420c68dd68c648af6642dd7e5cf6dacf9f067f6e Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 30 Oct 2020 15:22:52 -0400 Subject: [PATCH 299/403] runtime: tighten systemstack in lock assertions We use systemstack on the locking path to avoid stack splits which could cause locks to be recorded out of order (see comment on lockWithRank). This concern is irrelevant on lock assertions, where we simply need to see if a lock is held and don't care if another is taken in the meantime. Thus we can simply drop these unless we actually need to crash. Updates #40677 Change-Id: I85d730913a59867753ee1ed0386f8c5efda5c432 Reviewed-on: https://go-review.googlesource.com/c/go/+/266718 Run-TryBot: Michael Pratt TryBot-Result: Go Bot Reviewed-by: Austin Clements Trust: Michael Pratt --- src/runtime/lockrank_on.go | 76 +++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/src/runtime/lockrank_on.go b/src/runtime/lockrank_on.go index c25b3a4656b..88ac95a0047 100644 --- a/src/runtime/lockrank_on.go +++ b/src/runtime/lockrank_on.go @@ -95,7 +95,8 @@ func lockWithRank(l *mutex, rank lockRank) { }) } -//go:systemstack +// nosplit to ensure it can be called in as many contexts as possible. +//go:nosplit func printHeldLocks(gp *g) { if gp.m.locksHeldLen == 0 { println("") @@ -113,7 +114,7 @@ func printHeldLocks(gp *g) { //go:nosplit func acquireLockRank(rank lockRank) { gp := getg() - // Log the new class. + // Log the new class. See comment on lockWithRank. systemstack(func() { i := gp.m.locksHeldLen if i >= len(gp.m.locksHeld) { @@ -238,7 +239,8 @@ func lockWithRankMayAcquire(l *mutex, rank lockRank) { }) } -//go:systemstack +// nosplit to ensure it can be called in as many contexts as possible. +//go:nosplit func checkLockHeld(gp *g, l *mutex) bool { for i := gp.m.locksHeldLen - 1; i >= 0; i-- { if gp.m.locksHeld[i].lockAddr == uintptr(unsafe.Pointer(l)) { @@ -255,14 +257,18 @@ func checkLockHeld(gp *g, l *mutex) bool { func assertLockHeld(l *mutex) { gp := getg() + held := checkLockHeld(gp, l) + if held { + return + } + + // Crash from system stack to avoid splits that may cause + // additional issues. systemstack(func() { - held := checkLockHeld(gp, l) - if !held { - printlock() - print("caller requires lock ", l, " (rank ", l.rank.String(), "), holding:\n") - printHeldLocks(gp) - throw("not holding required lock!") - } + printlock() + print("caller requires lock ", l, " (rank ", l.rank.String(), "), holding:\n") + printHeldLocks(gp) + throw("not holding required lock!") }) } @@ -276,13 +282,15 @@ func assertLockHeld(l *mutex) { func assertRankHeld(r lockRank) { gp := getg() - systemstack(func() { - for i := gp.m.locksHeldLen - 1; i >= 0; i-- { - if gp.m.locksHeld[i].rank == r { - return - } + for i := gp.m.locksHeldLen - 1; i >= 0; i-- { + if gp.m.locksHeld[i].rank == r { + return } + } + // Crash from system stack to avoid splits that may cause + // additional issues. + systemstack(func() { printlock() print("caller requires lock with rank ", r.String(), "), holding:\n") printHeldLocks(gp) @@ -298,8 +306,10 @@ func assertRankHeld(r lockRank) { //go:nosplit func worldStopped() { if stopped := atomic.Xadd(&worldIsStopped, 1); stopped != 1 { - print("world stop count=", stopped, "\n") - throw("recursive world stop") + systemstack(func() { + print("world stop count=", stopped, "\n") + throw("recursive world stop") + }) } } @@ -311,8 +321,10 @@ func worldStopped() { //go:nosplit func worldStarted() { if stopped := atomic.Xadd(&worldIsStopped, -1); stopped != 0 { - print("world stop count=", stopped, "\n") - throw("released non-stopped world stop") + systemstack(func() { + print("world stop count=", stopped, "\n") + throw("released non-stopped world stop") + }) } } @@ -321,8 +333,10 @@ func worldStarted() { func checkWorldStopped() bool { stopped := atomic.Load(&worldIsStopped) if stopped > 1 { - print("inconsistent world stop count=", stopped, "\n") - throw("inconsistent world stop count") + systemstack(func() { + print("inconsistent world stop count=", stopped, "\n") + throw("inconsistent world stop count") + }) } return stopped == 1 @@ -352,14 +366,18 @@ func assertWorldStoppedOrLockHeld(l *mutex) { } gp := getg() + held := checkLockHeld(gp, l) + if held { + return + } + + // Crash from system stack to avoid splits that may cause + // additional issues. systemstack(func() { - held := checkLockHeld(gp, l) - if !held { - printlock() - print("caller requires world stop or lock ", l, " (rank ", l.rank.String(), "), holding:\n") - println("") - printHeldLocks(gp) - throw("no world stop or required lock!") - } + printlock() + print("caller requires world stop or lock ", l, " (rank ", l.rank.String(), "), holding:\n") + println("") + printHeldLocks(gp) + throw("no world stop or required lock!") }) } From 8414b1a5a40e5ef19508e4895b4c12a91fa498e7 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 21 Oct 2020 20:43:16 -0400 Subject: [PATCH 300/403] runtime: remove go115ReduceLiveness and go115RestartSeq Make them always true. Delete code that are only executed when they are false. Change-Id: I6194fa00de23486c2b0a0c9075fe3a09d9c52762 Reviewed-on: https://go-review.googlesource.com/c/go/+/264339 Trust: Cherry Zhang Reviewed-by: Austin Clements --- src/runtime/debugcall.go | 34 ++++++------------------ src/runtime/funcdata.h | 3 +-- src/runtime/preempt.go | 57 +++++++++++----------------------------- src/runtime/symtab.go | 7 +---- 4 files changed, 26 insertions(+), 75 deletions(-) diff --git a/src/runtime/debugcall.go b/src/runtime/debugcall.go index b5480c73aee..efc68a767d4 100644 --- a/src/runtime/debugcall.go +++ b/src/runtime/debugcall.go @@ -76,32 +76,14 @@ func debugCallCheck(pc uintptr) string { return } - if !go115ReduceLiveness { - // Look up PC's register map. - pcdata := int32(-1) - if pc != f.entry { - pc-- - pcdata = pcdatavalue(f, _PCDATA_RegMapIndex, pc, nil) - } - if pcdata == -1 { - pcdata = 0 // in prologue - } - stkmap := (*stackmap)(funcdata(f, _FUNCDATA_RegPointerMaps)) - if pcdata == _PCDATA_RegMapUnsafe || stkmap == nil { - // Not at a safe point. - ret = debugCallUnsafePoint - return - } - } else { - // Check that this isn't an unsafe-point. - if pc != f.entry { - pc-- - } - up := pcdatavalue(f, _PCDATA_UnsafePoint, pc, nil) - if up != _PCDATA_UnsafePointSafe { - // Not at a safe point. - ret = debugCallUnsafePoint - } + // Check that this isn't an unsafe-point. + if pc != f.entry { + pc-- + } + up := pcdatavalue(f, _PCDATA_UnsafePoint, pc, nil) + if up != _PCDATA_UnsafePointSafe { + // Not at a safe point. + ret = debugCallUnsafePoint } }) return ret diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h index cd76c069925..e9b6a7ed06e 100644 --- a/src/runtime/funcdata.h +++ b/src/runtime/funcdata.h @@ -8,13 +8,12 @@ // // These must agree with symtab.go and ../cmd/internal/objabi/funcdata.go. -#define PCDATA_RegMapIndex 0 +#define PCDATA_UnsafePoint 0 #define PCDATA_StackMapIndex 1 #define PCDATA_InlTreeIndex 2 #define FUNCDATA_ArgsPointerMaps 0 /* garbage collector blocks */ #define FUNCDATA_LocalsPointerMaps 1 -#define FUNCDATA_RegPointerMaps 2 #define FUNCDATA_StackObjects 3 #define FUNCDATA_InlTree 4 #define FUNCDATA_OpenCodedDeferInfo 5 /* info for func with open-coded defers */ diff --git a/src/runtime/preempt.go b/src/runtime/preempt.go index 17ef2c90d35..372185266f7 100644 --- a/src/runtime/preempt.go +++ b/src/runtime/preempt.go @@ -58,11 +58,6 @@ import ( "unsafe" ) -// Keep in sync with cmd/compile/internal/gc/plive.go:go115ReduceLiveness. -const go115ReduceLiveness = true - -const go115RestartSeq = go115ReduceLiveness && true // enable restartable sequences - type suspendGState struct { g *g @@ -402,24 +397,12 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) { // use the LR for unwinding, which will be bad. return false, 0 } - var up int32 - var startpc uintptr - if !go115ReduceLiveness { - smi := pcdatavalue(f, _PCDATA_RegMapIndex, pc, nil) - if smi == _PCDATA_RegMapUnsafe { - // Unsafe-point marked by compiler. This includes - // atomic sequences (e.g., write barrier) and nosplit - // functions (except at calls). - return false, 0 - } - } else { - up, startpc = pcdatavalue2(f, _PCDATA_UnsafePoint, pc) - if up != _PCDATA_UnsafePointSafe { - // Unsafe-point marked by compiler. This includes - // atomic sequences (e.g., write barrier) and nosplit - // functions (except at calls). - return false, 0 - } + up, startpc := pcdatavalue2(f, _PCDATA_UnsafePoint, pc) + if up != _PCDATA_UnsafePointSafe { + // Unsafe-point marked by compiler. This includes + // atomic sequences (e.g., write barrier) and nosplit + // functions (except at calls). + return false, 0 } if fd := funcdata(f, _FUNCDATA_LocalsPointerMaps); fd == nil || fd == unsafe.Pointer(&no_pointers_stackmap) { // This is assembly code. Don't assume it's @@ -455,25 +438,17 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) (bool, uintptr) { // in incrementally. return false, 0 } - if go115RestartSeq { - switch up { - case _PCDATA_Restart1, _PCDATA_Restart2: - // Restartable instruction sequence. Back off PC to - // the start PC. - if startpc == 0 || startpc > pc || pc-startpc > 20 { - throw("bad restart PC") - } - return true, startpc - case _PCDATA_RestartAtEntry: - // Restart from the function entry at resumption. - return true, f.entry - } - } else { - switch up { - case _PCDATA_Restart1, _PCDATA_Restart2, _PCDATA_RestartAtEntry: - // go115RestartSeq is not enabled. Treat it as unsafe point. - return false, 0 + switch up { + case _PCDATA_Restart1, _PCDATA_Restart2: + // Restartable instruction sequence. Back off PC to + // the start PC. + if startpc == 0 || startpc > pc || pc-startpc > 20 { + throw("bad restart PC") } + return true, startpc + case _PCDATA_RestartAtEntry: + // Restart from the function entry at resumption. + return true, f.entry } return true, pc } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 932fba3de05..a4b4344ea7c 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -268,14 +268,12 @@ func (f *Func) funcInfo() funcInfo { // // See funcdata.h and ../cmd/internal/objabi/funcdata.go. const ( - _PCDATA_RegMapIndex = 0 // if !go115ReduceLiveness - _PCDATA_UnsafePoint = 0 // if go115ReduceLiveness + _PCDATA_UnsafePoint = 0 _PCDATA_StackMapIndex = 1 _PCDATA_InlTreeIndex = 2 _FUNCDATA_ArgsPointerMaps = 0 _FUNCDATA_LocalsPointerMaps = 1 - _FUNCDATA_RegPointerMaps = 2 // if !go115ReduceLiveness _FUNCDATA_StackObjects = 3 _FUNCDATA_InlTree = 4 _FUNCDATA_OpenCodedDeferInfo = 5 @@ -284,9 +282,6 @@ const ( ) const ( - // Only if !go115ReduceLiveness. - _PCDATA_RegMapUnsafe = _PCDATA_UnsafePointUnsafe // Unsafe for async preemption - // PCDATA_UnsafePoint values. _PCDATA_UnsafePointSafe = -1 // Safe for async preemption _PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption From f96b62be2edd8acc08b79777d692937e8ed79b4a Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Tue, 27 Oct 2020 19:47:29 -0400 Subject: [PATCH 301/403] cmd/internal/objabi, runtime: compact FUNCDATA indices As we deleted register maps, move FUNCDATA indices of stack objects, inline trees, and open-coded defers earlier. Change-Id: If73797b8c11fd207655c9498802fca9f6f9ac338 Reviewed-on: https://go-review.googlesource.com/c/go/+/265761 Trust: Cherry Zhang Reviewed-by: Austin Clements --- src/cmd/internal/objabi/funcdata.go | 6 +++--- src/runtime/funcdata.h | 6 +++--- src/runtime/symtab.go | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cmd/internal/objabi/funcdata.go b/src/cmd/internal/objabi/funcdata.go index 1c5e5e1c8c4..faa2863325d 100644 --- a/src/cmd/internal/objabi/funcdata.go +++ b/src/cmd/internal/objabi/funcdata.go @@ -17,9 +17,9 @@ const ( FUNCDATA_ArgsPointerMaps = 0 FUNCDATA_LocalsPointerMaps = 1 - FUNCDATA_StackObjects = 3 - FUNCDATA_InlTree = 4 - FUNCDATA_OpenCodedDeferInfo = 5 + FUNCDATA_StackObjects = 2 + FUNCDATA_InlTree = 3 + FUNCDATA_OpenCodedDeferInfo = 4 // ArgsSizeUnknown is set in Func.argsize to mark all functions // whose argument size is unknown (C vararg functions, and diff --git a/src/runtime/funcdata.h b/src/runtime/funcdata.h index e9b6a7ed06e..798dbaceabf 100644 --- a/src/runtime/funcdata.h +++ b/src/runtime/funcdata.h @@ -14,9 +14,9 @@ #define FUNCDATA_ArgsPointerMaps 0 /* garbage collector blocks */ #define FUNCDATA_LocalsPointerMaps 1 -#define FUNCDATA_StackObjects 3 -#define FUNCDATA_InlTree 4 -#define FUNCDATA_OpenCodedDeferInfo 5 /* info for func with open-coded defers */ +#define FUNCDATA_StackObjects 2 +#define FUNCDATA_InlTree 3 +#define FUNCDATA_OpenCodedDeferInfo 4 /* info for func with open-coded defers */ // Pseudo-assembly statements. diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index a4b4344ea7c..7667f23f1db 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -274,9 +274,9 @@ const ( _FUNCDATA_ArgsPointerMaps = 0 _FUNCDATA_LocalsPointerMaps = 1 - _FUNCDATA_StackObjects = 3 - _FUNCDATA_InlTree = 4 - _FUNCDATA_OpenCodedDeferInfo = 5 + _FUNCDATA_StackObjects = 2 + _FUNCDATA_InlTree = 3 + _FUNCDATA_OpenCodedDeferInfo = 4 _ArgsSizeUnknown = -0x80000000 ) From 64a9a75ce9a353ef3d488b8e3ca977bf6df204f8 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 20 Jul 2020 18:19:56 +0000 Subject: [PATCH 302/403] runtime: release worldsema with a direct G handoff Currently worldsema is not released with direct handoff, so the semaphore is an unfair synchronization mechanism. If, for example, ReadMemStats is called in a loop, it can continuously stomp on attempts by the GC to stop the world. Note that it's specifically possible for ReadMemStats to delay a STW to end GC since ReadMemStats is able to STW during a GC since #19112 was fixed. While this particular case is unlikely and the right answer in most applications is to simply not call such an expensive operation in a loop, this pattern is used often in tests. Fixes #40459. Change-Id: Ia4a54f0fd956ea145a319f9f06c4cd37dd52fd8a Reviewed-on: https://go-review.googlesource.com/c/go/+/243977 Run-TryBot: Michael Knyszek TryBot-Result: Go Bot Trust: Michael Knyszek Reviewed-by: Michael Pratt Reviewed-by: Austin Clements Reviewed-by: David Chase --- src/runtime/proc.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 071257b5a50..79529ac7ec7 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -961,10 +961,26 @@ func stopTheWorld(reason string) { // startTheWorld undoes the effects of stopTheWorld. func startTheWorld() { systemstack(func() { startTheWorldWithSema(false) }) + // worldsema must be held over startTheWorldWithSema to ensure // gomaxprocs cannot change while worldsema is held. - semrelease(&worldsema) - getg().m.preemptoff = "" + // + // Release worldsema with direct handoff to the next waiter, but + // acquirem so that semrelease1 doesn't try to yield our time. + // + // Otherwise if e.g. ReadMemStats is being called in a loop, + // it might stomp on other attempts to stop the world, such as + // for starting or ending GC. The operation this blocks is + // so heavy-weight that we should just try to be as fair as + // possible here. + // + // We don't want to just allow us to get preempted between now + // and releasing the semaphore because then we keep everyone + // (including, for example, GCs) waiting longer. + mp := acquirem() + mp.preemptoff = "" + semrelease1(&worldsema, true, 0) + releasem(mp) } // stopTheWorldGC has the same effect as stopTheWorld, but blocks From fd56942fe3725feaa53bed67daf7412742e4f2ab Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 30 Oct 2020 17:16:51 -0400 Subject: [PATCH 303/403] runtime: add a comment about thread pointer alignment on darwin/arm64 Address a review comment in CL 266373. Change-Id: Ic21bd5c4f87fd0c7dc594155a10fe23602698187 Reviewed-on: https://go-review.googlesource.com/c/go/+/266777 Trust: Cherry Zhang Reviewed-by: Austin Clements --- src/runtime/race_arm64.s | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index 59373a9f3f4..5b1a1cb89a1 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -25,12 +25,15 @@ // The race ctx, ThreadState *thr below, is passed in R0 and loaded in racecalladdr. +// Darwin may return unaligned thread pointer. Align it. (See tls_arm64.s) +// No-op on other OSes. #ifdef TLS_darwin #define TP_ALIGN AND $~7, R0 #else #define TP_ALIGN #endif +// Load g from TLS. (See tls_arm64.s) #define load_g \ MRS_TPIDR_R0 \ TP_ALIGN \ From 07e4f0fd4b0f215cdfa7d6ea50f3e6402762a1a9 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 29 Oct 2020 15:31:16 -0700 Subject: [PATCH 304/403] cmd/compile: fmt improvements for AST nodes and some comments on AST nodes Changed fmt.go to print out some extra information for various kinds of Nodes. This includes some extra (small) info in the %j (jconv) output, and some missing sections (such as Dcls and the body of a closure) in nodedump(). Also, added some extra doc comments for a few Node types in syntax.go Change-Id: I2ec7184e2abe0d5fbe3fb5a2506da7c7b06f2fb1 Reviewed-on: https://go-review.googlesource.com/c/go/+/266437 Run-TryBot: Dan Scales Trust: Dan Scales Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/fmt.go | 29 +++++++++++++++++++++++++++ src/cmd/compile/internal/gc/syntax.go | 25 +++++++++++++++-------- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index d7ed1d2ff09..240b09bb6d3 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -419,10 +419,17 @@ func (n *Node) format(s fmt.State, verb rune, mode fmtMode) { func (n *Node) jconv(s fmt.State, flag FmtFlag) { c := flag & FmtShort + // Useful to see which nodes in an AST printout are actually identical + fmt.Fprintf(s, " p(%p)", n) if c == 0 && n.Name != nil && n.Name.Vargen != 0 { fmt.Fprintf(s, " g(%d)", n.Name.Vargen) } + if c == 0 && n.Name != nil && n.Name.Defn != nil { + // Useful to see where Defn is set and what node it points to + fmt.Fprintf(s, " defn(%p)", n.Name.Defn) + } + if n.Pos.IsKnown() { pfx := "" switch n.Pos.IsStmt() { @@ -492,6 +499,15 @@ func (n *Node) jconv(s fmt.State, flag FmtFlag) { if n.Name.Assigned() { fmt.Fprint(s, " assigned") } + if n.Name.IsClosureVar() { + fmt.Fprint(s, " closurevar") + } + if n.Name.Captured() { + fmt.Fprint(s, " captured") + } + if n.Name.IsOutputParamHeapAddr() { + fmt.Fprint(s, " outputparamheapaddr") + } } if n.Bounded() { fmt.Fprint(s, " bounded") @@ -1710,6 +1726,9 @@ func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) { } } + if n.Op == OCLOSURE && n.Func.Closure != nil && n.Func.Closure.Func.Nname.Sym != nil { + mode.Fprintf(s, " fnName %v", n.Func.Closure.Func.Nname.Sym) + } if n.Sym != nil && n.Op != ONAME { mode.Fprintf(s, " %v", n.Sym) } @@ -1725,6 +1744,16 @@ func (n *Node) nodedump(s fmt.State, flag FmtFlag, mode fmtMode) { if n.Right != nil { mode.Fprintf(s, "%v", n.Right) } + if n.Func != nil && n.Func.Closure != nil && n.Func.Closure.Nbody.Len() != 0 { + indent(s) + // The function associated with a closure + mode.Fprintf(s, "%v-clofunc%v", n.Op, n.Func.Closure) + } + if n.Func != nil && n.Func.Dcl != nil && len(n.Func.Dcl) != 0 { + indent(s) + // The dcls for a func or closure + mode.Fprintf(s, "%v-dcl%v", n.Op, asNodes(n.Func.Dcl)) + } if n.List.Len() != 0 { indent(s) mode.Fprintf(s, "%v-list%v", n.Op, n.List) diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go index 58de9b5e3ff..649f7f4157b 100644 --- a/src/cmd/compile/internal/gc/syntax.go +++ b/src/cmd/compile/internal/gc/syntax.go @@ -631,7 +631,7 @@ type Func struct { Ntype *Node // signature Top int // top context (ctxCallee, etc) Closure *Node // OCLOSURE <-> ODCLFUNC - Nname *Node + Nname *Node // The ONAME node associated with an ODCLFUNC (both have same Type) lsym *obj.LSym Inl *Inline @@ -773,7 +773,7 @@ const ( OCALLPART // Left.Right (method expression x.Method, not called) OCAP // cap(Left) OCLOSE // close(Left) - OCLOSURE // func Type { Body } (func literal) + OCLOSURE // func Type { Func.Closure.Nbody } (func literal) OCOMPLIT // Right{List} (composite literal, not yet lowered to specific form) OMAPLIT // Type{List} (composite literal, Type is map) OSTRUCTLIT // Type{List} (composite literal, Type is struct) @@ -863,9 +863,14 @@ const ( OSIZEOF // unsafe.Sizeof(Left) // statements - OBLOCK // { List } (block of code) - OBREAK // break [Sym] - OCASE // case List: Nbody (List==nil means default) + OBLOCK // { List } (block of code) + OBREAK // break [Sym] + // OCASE: case List: Nbody (List==nil means default) + // For OTYPESW, List is a OTYPE node for the specified type (or OLITERAL + // for nil), and, if a type-switch variable is specified, Rlist is an + // ONAME for the version of the type-switch variable with the specified + // type. + OCASE OCONTINUE // continue [Sym] ODEFER // defer Left (Left must be call) OEMPTY // no-op (empty statement) @@ -889,15 +894,19 @@ const ( ORETURN // return List OSELECT // select { List } (List is list of OCASE) OSWITCH // switch Ninit; Left { List } (List is a list of OCASE) - OTYPESW // Left = Right.(type) (appears as .Left of OSWITCH) + // OTYPESW: Left := Right.(type) (appears as .Left of OSWITCH) + // Left is nil if there is no type-switch variable + OTYPESW // types OTCHAN // chan int OTMAP // map[string]int OTSTRUCT // struct{} OTINTER // interface{} - OTFUNC // func() - OTARRAY // []int, [8]int, [N]int or [...]int + // OTFUNC: func() - Left is receiver field, List is list of param fields, Rlist is + // list of result fields. + OTFUNC + OTARRAY // []int, [8]int, [N]int or [...]int // misc ODDD // func f(args ...int) or f(l...) or var a = [...]int{0, 1, 2}. From 79fb187be4d1a1a93c01b3a6be66ea529311ea84 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 27 Oct 2020 17:51:58 -0400 Subject: [PATCH 305/403] cmd/cgo: add -trimpath flag allowing paths to be rewritten in outputs cmd/cgo now has a -trimpath flag that behaves the same as the -trimpath flag to cmd/compile. This will be used to correct paths to cgo files that are overlaid. The code that processes trimpath in internal/objapi has been slightly refactored because it's currently only accessible via AbsFile, which does some additional processing to the path names. Now an ApplyRewrites function is exported that just applies the trimpath rewrites. Also remove unused srcfile argument to cmd/cgo.(*Package).godefs. For #39958 Change-Id: I497d48d0bc2fe1f6ab2b5835cbe79f15b839ee59 Reviewed-on: https://go-review.googlesource.com/c/go/+/266358 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Bryan C. Mills --- src/cmd/cgo/ast.go | 16 ++++----------- src/cmd/cgo/godefs.go | 2 +- src/cmd/cgo/main.go | 15 +++++++++++++- src/cmd/internal/objabi/line.go | 35 ++++++++++++++++++++++----------- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index 54d6bc2559d..a073407a961 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -13,7 +13,6 @@ import ( "go/scanner" "go/token" "os" - "path/filepath" "strings" ) @@ -44,14 +43,7 @@ func sourceLine(n ast.Node) int { // attached to the import "C" comment, a list of references to C.xxx, // a list of exported functions, and the actual AST, to be rewritten and // printed. -func (f *File) ParseGo(name string, src []byte) { - // Create absolute path for file, so that it will be used in error - // messages and recorded in debug line number information. - // This matches the rest of the toolchain. See golang.org/issue/5122. - if aname, err := filepath.Abs(name); err == nil { - name = aname - } - +func (f *File) ParseGo(abspath string, src []byte) { // Two different parses: once with comments, once without. // The printer is not good enough at printing comments in the // right place when we start editing the AST behind its back, @@ -60,8 +52,8 @@ func (f *File) ParseGo(name string, src []byte) { // and reprinting. // In cgo mode, we ignore ast2 and just apply edits directly // the text behind ast1. In godefs mode we modify and print ast2. - ast1 := parse(name, src, parser.ParseComments) - ast2 := parse(name, src, 0) + ast1 := parse(abspath, src, parser.ParseComments) + ast2 := parse(abspath, src, 0) f.Package = ast1.Name.Name f.Name = make(map[string]*Name) @@ -88,7 +80,7 @@ func (f *File) ParseGo(name string, src []byte) { cg = d.Doc } if cg != nil { - f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name) + f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), abspath) f.Preamble += commentText(cg) + "\n" f.Preamble += "#line 1 \"cgo-generated-wrapper\"\n" } diff --git a/src/cmd/cgo/godefs.go b/src/cmd/cgo/godefs.go index b4fd9c5a6e3..c0d59aee01d 100644 --- a/src/cmd/cgo/godefs.go +++ b/src/cmd/cgo/godefs.go @@ -16,7 +16,7 @@ import ( ) // godefs returns the output for -godefs mode. -func (p *Package) godefs(f *File, srcfile string) string { +func (p *Package) godefs(f *File) string { var buf bytes.Buffer fmt.Fprintf(&buf, "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n") diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 7d02ac3c546..c1116e28ecd 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -243,6 +243,8 @@ var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used wit var gccgoMangler func(string) string var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code") var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code") +var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths") + var goarch, goos string func main() { @@ -322,6 +324,13 @@ func main() { input = filepath.Join(*srcDir, input) } + // Create absolute path for file, so that it will be used in error + // messages and recorded in debug line number information. + // This matches the rest of the toolchain. See golang.org/issue/5122. + if aname, err := filepath.Abs(input); err == nil { + input = aname + } + b, err := ioutil.ReadFile(input) if err != nil { fatalf("%s", err) @@ -330,6 +339,10 @@ func main() { fatalf("%s", err) } + // Apply trimpath to the file path. The path won't be read from after this point. + input, _ = objabi.ApplyRewrites(input, *trimpath) + goFiles[i] = input + f := new(File) f.Edit = edit.NewBuffer(b) f.ParseGo(input, b) @@ -367,7 +380,7 @@ func main() { p.PackagePath = f.Package p.Record(f) if *godefs { - os.Stdout.WriteString(p.godefs(f, input)) + os.Stdout.WriteString(p.godefs(f)) } else { p.writeOutput(f, input) } diff --git a/src/cmd/internal/objabi/line.go b/src/cmd/internal/objabi/line.go index 178c8363d95..0733b65138d 100644 --- a/src/cmd/internal/objabi/line.go +++ b/src/cmd/internal/objabi/line.go @@ -37,27 +37,38 @@ func AbsFile(dir, file, rewrites string) string { abs = filepath.Join(dir, file) } - start := 0 - for i := 0; i <= len(rewrites); i++ { - if i == len(rewrites) || rewrites[i] == ';' { - if new, ok := applyRewrite(abs, rewrites[start:i]); ok { - abs = new - goto Rewritten - } - start = i + 1 - } - } - if hasPathPrefix(abs, GOROOT) { + abs, rewritten := ApplyRewrites(abs, rewrites) + if !rewritten && hasPathPrefix(abs, GOROOT) { abs = "$GOROOT" + abs[len(GOROOT):] } -Rewritten: if abs == "" { abs = "??" } return abs } +// ApplyRewrites returns the filename for file in the given directory, +// as rewritten by the rewrites argument. +// +// The rewrites argument is a ;-separated list of rewrites. +// Each rewrite is of the form "prefix" or "prefix=>replace", +// where prefix must match a leading sequence of path elements +// and is either removed entirely or replaced by the replacement. +func ApplyRewrites(file, rewrites string) (string, bool) { + start := 0 + for i := 0; i <= len(rewrites); i++ { + if i == len(rewrites) || rewrites[i] == ';' { + if new, ok := applyRewrite(file, rewrites[start:i]); ok { + return new, true + } + start = i + 1 + } + } + + return file, false +} + // applyRewrite applies the rewrite to the path, // returning the rewritten path and a boolean // indicating whether the rewrite applied at all. From 48be3ed1394d85af5a7e1a6313fa9cab4d1b7cf9 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 15 Oct 2020 11:50:31 -0400 Subject: [PATCH 306/403] cmd/go: support cgo files in overlays This requires rewriting the paths of the files passed to the cgo tool toolchain to use the overlaid paths instead of the disk paths of files. Because the directories of the overlaid paths don't exist in general, the cgo tool have been updated to run in base.Cwd instead of the package directory. For #39958 Change-Id: I8986de889f56ecc2e64fa69f5f6f29fa907408f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/262618 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Jay Conrod Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/work/exec.go | 48 +++++++++-- src/cmd/go/internal/work/gc.go | 9 +- src/cmd/go/testdata/script/build_overlay.txt | 83 ++++++++++++++++++- .../go/testdata/script/build_trimpath_cgo.txt | 28 +++++++ 4 files changed, 156 insertions(+), 12 deletions(-) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 838b00a00d2..a1a357e2acc 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -8,6 +8,7 @@ package work import ( "bytes" + "cmd/go/internal/fsys" "context" "encoding/json" "errors" @@ -2242,8 +2243,6 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s // when -trimpath is enabled. if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") { if cfg.BuildTrimpath { - // TODO(#39958): handle overlays - // Keep in sync with Action.trimpath. // The trimmed paths are a little different, but we need to trim in the // same situations. @@ -2313,7 +2312,8 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag cmdargs := []interface{}{cmd, "-o", outfile, objs, flags} dir := p.Dir - out, err := b.runOut(a, dir, b.cCompilerEnv(), cmdargs...) + out, err := b.runOut(a, base.Cwd, b.cCompilerEnv(), cmdargs...) + if len(out) > 0 { // Filter out useless linker warnings caused by bugs outside Go. // See also cmd/link/internal/ld's hostlink method. @@ -2641,7 +2641,8 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...) } - // Allows including _cgo_export.h from .[ch] files in the package. + // Allows including _cgo_export.h, as well as the user's .h files, + // from .[ch] files in the package. cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", objdir) // cgo @@ -2654,6 +2655,8 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cfiles = append(cfiles, f+".cgo2.c") } + hfiles := append([]string{}, p.HFiles...) + // TODO: make cgo not depend on $GOARCH? cgoflags := []string{} @@ -2698,7 +2701,38 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h") } - if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { + execdir := p.Dir + + // If any of the Cgo, C, or H files are overlaid, copy them all to + // objdir to ensure that they refer to the right header files. + // TODO(#39958): Ideally, we'd always do this, but this could + // subtly break some cgo files that include .h files across directory + // boundaries, even though they shouldn't. + hasOverlay := false + cgoFileLists := [][]string{cgofiles, gccfiles, gxxfiles, mfiles, ffiles, hfiles} +OverlayLoop: + for _, fs := range cgoFileLists { + for _, f := range fs { + if _, ok := fsys.OverlayPath(mkAbs(p.Dir, f)); ok { + hasOverlay = true + break OverlayLoop + } + } + } + if hasOverlay { + execdir = objdir + for _, fs := range cgoFileLists { + for i := range fs { + opath, _ := fsys.OverlayPath(mkAbs(p.Dir, fs[i])) + fs[i] = objdir + filepath.Base(fs[i]) + if err := b.copyFile(fs[i], opath, 0666, false); err != nil { + return nil, nil, err + } + } + } + } + + if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { return nil, nil, err } outGo = append(outGo, gofiles...) @@ -2792,7 +2826,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe return err } - linkobj := str.StringList(ofile, outObj, p.SysoFiles) + linkobj := str.StringList(ofile, outObj, mkAbsFiles(p.Dir, p.SysoFiles)) dynobj := objdir + "_cgo_.o" // we need to use -pie for Linux/ARM to get accurate imported sym @@ -2817,7 +2851,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = []string{"-dynlinker"} // record path to dynamic linker } - return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + return b.run(a, base.Cwd, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) } // Run SWIG on all SWIG input files. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index e79173485db..4ba9be78296 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -262,7 +262,7 @@ func (a *Action) trimpath() string { if len(objdir) > 1 && objdir[len(objdir)-1] == filepath.Separator { objdir = objdir[:len(objdir)-1] } - rewrite := objdir + "=>" + rewrite := "" rewriteDir := a.Package.Dir if cfg.BuildTrimpath { @@ -271,7 +271,7 @@ func (a *Action) trimpath() string { } else { rewriteDir = a.Package.ImportPath } - rewrite += ";" + a.Package.Dir + "=>" + rewriteDir + rewrite += a.Package.Dir + "=>" + rewriteDir + ";" } // Add rewrites for overlays. The 'from' and 'to' paths in overlays don't need to have @@ -280,11 +280,14 @@ func (a *Action) trimpath() string { if fsys.OverlayFile != "" { for _, filename := range a.Package.AllFiles() { overlayPath, ok := fsys.OverlayPath(filepath.Join(a.Package.Dir, filename)) + rewrite += filepath.Join(objdir, filename) + "=>" + filepath.Join(rewriteDir, filename) + ";" if !ok { continue } - rewrite += ";" + overlayPath + "=>" + filepath.Join(rewriteDir, filename) + rewrite += overlayPath + "=>" + filepath.Join(rewriteDir, filename) + ";" } + } else { + rewrite += objdir + "=>" } return rewrite diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt index 0602e706e9e..3af10083af6 100644 --- a/src/cmd/go/testdata/script/build_overlay.txt +++ b/src/cmd/go/testdata/script/build_overlay.txt @@ -1,9 +1,11 @@ [short] skip # Test building in overlays. -# TODO(matloob): add a test case where the destination file in the replace map +# TODO(#39958): add a test case where the destination file in the replace map # isn't a go file. Either completely exclude that case in fs.IsDirWithGoFiles # if the compiler doesn't allow it, or test that it works all the way. +# TODO(#39958): add a test that both gc and gccgo assembly files can include .h +# files. # The main package (m) is contained in an overlay. It imports m/dir2 which has one # file in an overlay and one file outside the overlay, which in turn imports m/dir, @@ -29,6 +31,18 @@ exec ./print_trimpath_two_files$GOEXE stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go +go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace +exec ./main_cgo_replace$GOEXE +stdout '^hello cgo$' + +go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote +exec ./main_cgo_quote$GOEXE +stdout '^hello cgo$' + +go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle +exec ./main_cgo_angle$GOEXE +stdout '^hello cgo$' + # Run same tests but with gccgo. env GO111MODULE=off [!exec:gccgo] stop @@ -46,6 +60,19 @@ go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -tr exec ./print_trimpath_gccgo$GOEXE stdout ^\.[/\\]printpath[/\\]main.go + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_replace_gccgo$GOEXE ./cgo_hello_replace +exec ./main_cgo_replace_gccgo$GOEXE +stdout '^hello cgo$' + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_quote_gccgo$GOEXE ./cgo_hello_quote +exec ./main_cgo_quote_gccgo$GOEXE +stdout '^hello cgo$' + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_angle_gccgo$GOEXE ./cgo_hello_angle +exec ./main_cgo_angle_gccgo$GOEXE +stdout '^hello cgo$' + -- m/go.mod -- // TODO(matloob): how do overlays work with go.mod (especially if mod=readonly) module m @@ -71,9 +98,32 @@ the actual code is in the overlay "dir/g.go": "overlay/dir_g.go", "dir2/i.go": "overlay/dir2_i.go", "printpath/main.go": "overlay/printpath.go", - "printpath/other.go": "overlay2/printpath2.go" + "printpath/other.go": "overlay2/printpath2.go", + "cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h", + "cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go", + "cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h", + "cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go", + "cgo_hello_angle/cgo_header.h": "overlay/cgo_head.h" } } +-- m/cgo_hello_replace/cgo_hello_replace.go -- +package main + +// #include "cgo_header.h" +import "C" + +func main() { + C.say_hello() +} +-- m/cgo_hello_replace/cgo_header.h -- + // Test that this header is replaced with one that has the proper declaration. +void say_goodbye(); + +-- m/cgo_hello_replace/goodbye.c -- +#include + +void say_hello() { puts("hello cgo\n"); } + -- m/overlay/f.go -- package main @@ -128,3 +178,32 @@ import "m/dir" func printMessage() { dir.PrintMessage() } +-- m/overlay/cgo_hello_quote.go -- +package main + +// #include "cgo_header.h" +import "C" + +func main() { + C.say_hello() +} +-- m/overlay/cgo_hello_angle.go -- +package main + +// #include +import "C" + +func main() { + C.say_hello() +} +-- m/overlay/cgo_head.h -- +void say_hello(); +-- m/cgo_hello_quote/hello.c -- +#include + +void say_hello() { puts("hello cgo\n"); } +-- m/cgo_hello_angle/hello.c -- +#include + +void say_hello() { puts("hello cgo\n"); } + diff --git a/src/cmd/go/testdata/script/build_trimpath_cgo.txt b/src/cmd/go/testdata/script/build_trimpath_cgo.txt index 4608d9ac6bf..3187b4d6439 100644 --- a/src/cmd/go/testdata/script/build_trimpath_cgo.txt +++ b/src/cmd/go/testdata/script/build_trimpath_cgo.txt @@ -20,10 +20,38 @@ go build -trimpath -o hello.exe . go run ./list-dwarf hello.exe ! stdout gopath/src + +# Do the above, with the cgo (but not .c) sources in an overlay +# Check that the source path appears when -trimpath is not used. +mkdir $WORK/overlay +cp hello.go $WORK/overlay/hello.go +mkdir hello_overlay +cp hello.c hello_overlay/hello.c +go build -overlay overlay.json -o hello_overlay.exe ./hello_overlay +grep -q gopath[/\\]src hello_overlay.exe +! grep -q $WORK[/\\]overlay hello_overlay.exe +go run ./list-dwarf hello_overlay.exe +stdout gopath[/\\]src +! stdout $WORK[/\\]overlay + +# Check that the source path does not appear when -trimpath is used. +go build -overlay overlay.json -trimpath -o hello_overlay.exe ./hello_overlay +! grep -q gopath[/\\]src hello_overlay.exe +! grep -q $WORK[/\\]overlay hello_overlay.exe +go run ./list-dwarf hello_overlay.exe +! stdout gopath/src +! stdout $WORK[/\\]overlay + -- go.mod -- module m go 1.14 +-- overlay.json -- +{ + "Replace": { + "hello_overlay/hello.go": "../../overlay/hello.go" + } +} -- hello.c -- #include From 12a2e72065105a7c167d7f41500b5a80547f14d0 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Mon, 26 Oct 2020 18:35:40 +1100 Subject: [PATCH 307/403] cmd/compile: avoid unnecessary sign/zero extension for consts on riscv64 Sign extension for consts is unnecessary and zero extension for consts can be avoided via casts. This removes over 16,000 instructions from the Go binary, in part because it allows for better zero const absorbtion in blocks - for example, `(BEQ (MOVBU (MOVBconst [0])) cond yes no)` now becomes `(BEQZ cond yes no)` when this change is combined with existing rules. Change-Id: I27e791bfa84869639db653af6119f6e10369ba3d Reviewed-on: https://go-review.googlesource.com/c/go/+/265041 Trust: Joel Sing Reviewed-by: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot --- .../compile/internal/ssa/gen/RISCV64.rules | 16 +++ .../compile/internal/ssa/rewriteRISCV64.go | 132 ++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 306103c7b69..449f3cad03c 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -430,6 +430,8 @@ (OffPtr [off] ptr) && is32Bit(off) => (ADDI [off] ptr) (OffPtr [off] ptr) => (ADD (MOVDconst [off]) ptr) +// TODO(jsing): Check if we actually need MOV{B,H,W}const as most platforms +// use a single MOVDconst op. (Const8 ...) => (MOVBconst ...) (Const16 ...) => (MOVHconst ...) (Const32 ...) => (MOVWconst ...) @@ -507,6 +509,20 @@ (MOVWstore [off] {sym} ptr (MOVWconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem) (MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) => (MOVDstorezero [off] {sym} ptr mem) +// Avoid sign/zero extension for consts. +(MOVBreg (MOVBconst [c])) => (MOVDconst [int64(c)]) +(MOVHreg (MOVBconst [c])) => (MOVDconst [int64(c)]) +(MOVHreg (MOVHconst [c])) => (MOVDconst [int64(c)]) +(MOVWreg (MOVBconst [c])) => (MOVDconst [int64(c)]) +(MOVWreg (MOVHconst [c])) => (MOVDconst [int64(c)]) +(MOVWreg (MOVWconst [c])) => (MOVDconst [int64(c)]) +(MOVBUreg (MOVBconst [c])) => (MOVDconst [int64(uint8(c))]) +(MOVHUreg (MOVBconst [c])) => (MOVDconst [int64(uint16(c))]) +(MOVHUreg (MOVHconst [c])) => (MOVDconst [int64(uint16(c))]) +(MOVWUreg (MOVBconst [c])) => (MOVDconst [int64(uint32(c))]) +(MOVWUreg (MOVHconst [c])) => (MOVDconst [int64(uint32(c))]) +(MOVWUreg (MOVWconst [c])) => (MOVDconst [int64(uint32(c))]) + // Avoid sign/zero extension after properly typed load. (MOVBreg x:(MOVBload _ _)) => (MOVDreg x) (MOVHreg x:(MOVBload _ _)) => (MOVDreg x) diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index 67d3ecf2cc1..a91e8428ef0 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -2512,6 +2512,17 @@ func rewriteValueRISCV64_OpRISCV64MOVBUload(v *Value) bool { func rewriteValueRISCV64_OpRISCV64MOVBUreg(v *Value) bool { v_0 := v.Args[0] b := v.Block + // match: (MOVBUreg (MOVBconst [c])) + // result: (MOVDconst [int64(uint8(c))]) + for { + if v_0.Op != OpRISCV64MOVBconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(uint8(c))) + return true + } // match: (MOVBUreg x:(MOVBUload _ _)) // result: (MOVDreg x) for { @@ -2611,6 +2622,17 @@ func rewriteValueRISCV64_OpRISCV64MOVBload(v *Value) bool { func rewriteValueRISCV64_OpRISCV64MOVBreg(v *Value) bool { v_0 := v.Args[0] b := v.Block + // match: (MOVBreg (MOVBconst [c])) + // result: (MOVDconst [int64(c)]) + for { + if v_0.Op != OpRISCV64MOVBconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(c)) + return true + } // match: (MOVBreg x:(MOVBload _ _)) // result: (MOVDreg x) for { @@ -3151,6 +3173,28 @@ func rewriteValueRISCV64_OpRISCV64MOVHUload(v *Value) bool { func rewriteValueRISCV64_OpRISCV64MOVHUreg(v *Value) bool { v_0 := v.Args[0] b := v.Block + // match: (MOVHUreg (MOVBconst [c])) + // result: (MOVDconst [int64(uint16(c))]) + for { + if v_0.Op != OpRISCV64MOVBconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(uint16(c))) + return true + } + // match: (MOVHUreg (MOVHconst [c])) + // result: (MOVDconst [int64(uint16(c))]) + for { + if v_0.Op != OpRISCV64MOVHconst { + break + } + c := auxIntToInt16(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(uint16(c))) + return true + } // match: (MOVHUreg x:(MOVBUload _ _)) // result: (MOVDreg x) for { @@ -3272,6 +3316,28 @@ func rewriteValueRISCV64_OpRISCV64MOVHload(v *Value) bool { func rewriteValueRISCV64_OpRISCV64MOVHreg(v *Value) bool { v_0 := v.Args[0] b := v.Block + // match: (MOVHreg (MOVBconst [c])) + // result: (MOVDconst [int64(c)]) + for { + if v_0.Op != OpRISCV64MOVBconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(c)) + return true + } + // match: (MOVHreg (MOVHconst [c])) + // result: (MOVDconst [int64(c)]) + for { + if v_0.Op != OpRISCV64MOVHconst { + break + } + c := auxIntToInt16(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(c)) + return true + } // match: (MOVHreg x:(MOVBload _ _)) // result: (MOVDreg x) for { @@ -3598,6 +3664,39 @@ func rewriteValueRISCV64_OpRISCV64MOVWUload(v *Value) bool { func rewriteValueRISCV64_OpRISCV64MOVWUreg(v *Value) bool { v_0 := v.Args[0] b := v.Block + // match: (MOVWUreg (MOVBconst [c])) + // result: (MOVDconst [int64(uint32(c))]) + for { + if v_0.Op != OpRISCV64MOVBconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(uint32(c))) + return true + } + // match: (MOVWUreg (MOVHconst [c])) + // result: (MOVDconst [int64(uint32(c))]) + for { + if v_0.Op != OpRISCV64MOVHconst { + break + } + c := auxIntToInt16(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(uint32(c))) + return true + } + // match: (MOVWUreg (MOVWconst [c])) + // result: (MOVDconst [int64(uint32(c))]) + for { + if v_0.Op != OpRISCV64MOVWconst { + break + } + c := auxIntToInt32(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(uint32(c))) + return true + } // match: (MOVWUreg x:(MOVBUload _ _)) // result: (MOVDreg x) for { @@ -3741,6 +3840,39 @@ func rewriteValueRISCV64_OpRISCV64MOVWload(v *Value) bool { func rewriteValueRISCV64_OpRISCV64MOVWreg(v *Value) bool { v_0 := v.Args[0] b := v.Block + // match: (MOVWreg (MOVBconst [c])) + // result: (MOVDconst [int64(c)]) + for { + if v_0.Op != OpRISCV64MOVBconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(c)) + return true + } + // match: (MOVWreg (MOVHconst [c])) + // result: (MOVDconst [int64(c)]) + for { + if v_0.Op != OpRISCV64MOVHconst { + break + } + c := auxIntToInt16(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(c)) + return true + } + // match: (MOVWreg (MOVWconst [c])) + // result: (MOVDconst [int64(c)]) + for { + if v_0.Op != OpRISCV64MOVWconst { + break + } + c := auxIntToInt32(v_0.AuxInt) + v.reset(OpRISCV64MOVDconst) + v.AuxInt = int64ToAuxInt(int64(c)) + return true + } // match: (MOVWreg x:(MOVBload _ _)) // result: (MOVDreg x) for { From f14119b561cfeefb93e8d773033caeea572dbe71 Mon Sep 17 00:00:00 2001 From: Colin Arnott Date: Thu, 16 Jul 2020 17:42:47 +0000 Subject: [PATCH 308/403] os: export errFinished as ErrProcessDone (*Process).Signal returns an error sentinel, previously errFinished, when (*Process).done or syscall.ESRCH. Callers would like the ability to test for this state, so the value has been exported as ErrProcessDone. Fixes #39444 Change-Id: I510e7647cc032af290180de5149f35ab7b09a526 Reviewed-on: https://go-review.googlesource.com/c/go/+/242998 Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Tobias Klauser Trust: Tobias Klauser --- src/os/exec_unix.go | 7 ++++--- src/os/exec_unix_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 src/os/exec_unix_test.go diff --git a/src/os/exec_unix.go b/src/os/exec_unix.go index 7759a2d2eab..624061297bb 100644 --- a/src/os/exec_unix.go +++ b/src/os/exec_unix.go @@ -59,7 +59,8 @@ func (p *Process) wait() (ps *ProcessState, err error) { return ps, nil } -var errFinished = errors.New("os: process already finished") +// ErrProcessDone indicates a Process has finished. +var ErrProcessDone = errors.New("os: process already finished") func (p *Process) signal(sig Signal) error { if p.Pid == -1 { @@ -71,7 +72,7 @@ func (p *Process) signal(sig Signal) error { p.sigMu.RLock() defer p.sigMu.RUnlock() if p.done() { - return errFinished + return ErrProcessDone } s, ok := sig.(syscall.Signal) if !ok { @@ -79,7 +80,7 @@ func (p *Process) signal(sig Signal) error { } if e := syscall.Kill(p.Pid, s); e != nil { if e == syscall.ESRCH { - return errFinished + return ErrProcessDone } return e } diff --git a/src/os/exec_unix_test.go b/src/os/exec_unix_test.go new file mode 100644 index 00000000000..d942cdb5e53 --- /dev/null +++ b/src/os/exec_unix_test.go @@ -0,0 +1,29 @@ +// Copyright 2020 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. + +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris + +package os_test + +import ( + "internal/testenv" + . "os" + "testing" +) + +func TestErrProcessDone(t *testing.T) { + testenv.MustHaveGoBuild(t) + path, err := testenv.GoTool() + if err != nil { + t.Errorf("finding go tool: %v", err) + } + p, err := StartProcess(path, []string{"go"}, &ProcAttr{}) + if err != nil { + t.Errorf("starting test process: %v", err) + } + p.Wait() + if got := p.Signal(Kill); got != ErrProcessDone { + t.Errorf("got %v want %v", got, ErrProcessDone) + } +} From 9933f6655589b1da9da7f61f04f74d921a2d67bf Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 30 Oct 2020 18:44:22 -0400 Subject: [PATCH 309/403] runtime: remove residual !go115NewMCentralImpl fields Change-Id: I1685721c82be4ac3c854084592e5e0f182b367ef Reviewed-on: https://go-review.googlesource.com/c/go/+/266858 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Michael Knyszek --- src/runtime/mcentral.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go index 97fe92c2ab3..cd20dec5394 100644 --- a/src/runtime/mcentral.go +++ b/src/runtime/mcentral.go @@ -20,10 +20,6 @@ import "runtime/internal/atomic" type mcentral struct { spanclass spanClass - // For !go115NewMCentralImpl. - nonempty mSpanList // list of spans with a free object, ie a nonempty free list - empty mSpanList // list of spans with no free objects (or cached in an mcache) - // partial and full contain two mspan sets: one of swept in-use // spans, and one of unswept in-use spans. These two trade // roles on each GC cycle. The unswept set is drained either by From 715d4e2e014fa54f527ee109f26a31f941196381 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Fri, 29 May 2020 17:19:42 -0700 Subject: [PATCH 310/403] database/sql, runtime: correct *.Fatal inside goroutines in tests Found by go vet pass "testinggoroutines". Change-Id: I6360af2079617b7aa62dcb9bd7254578ca5d1c1d Reviewed-on: https://go-review.googlesource.com/c/go/+/235527 Run-TryBot: Emmanuel Odeke Reviewed-by: Ian Lance Taylor Trust: Emmanuel Odeke --- src/database/sql/sql_test.go | 20 +++++++++++++++----- src/runtime/syscall_windows_test.go | 12 +++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index 4b02657b7e2..c968852adee 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -2888,20 +2888,26 @@ func TestConnExpiresFreshOutOfPool(t *testing.T) { waitingForConn := make(chan struct{}) go func() { + defer close(afterPutConn) + conn, err := db.conn(ctx, alwaysNewConn) - if err != nil { - t.Fatal(err) + if err == nil { + db.putConn(conn, err, false) + } else { + t.Errorf("db.conn: %v", err) } - db.putConn(conn, err, false) - close(afterPutConn) }() go func() { + defer close(waitingForConn) + for { + if t.Failed() { + return + } db.mu.Lock() ct := len(db.connRequests) db.mu.Unlock() if ct > 0 { - close(waitingForConn) return } time.Sleep(10 * time.Millisecond) @@ -2910,6 +2916,10 @@ func TestConnExpiresFreshOutOfPool(t *testing.T) { <-waitingForConn + if t.Failed() { + return + } + offsetMu.Lock() if ec.expired { offset = 11 * time.Second diff --git a/src/runtime/syscall_windows_test.go b/src/runtime/syscall_windows_test.go index 7705d2a0170..3827c6ed83f 100644 --- a/src/runtime/syscall_windows_test.go +++ b/src/runtime/syscall_windows_test.go @@ -1143,17 +1143,19 @@ func BenchmarkSyscallToSyscallPing(b *testing.B) { go func() { for i := 0; i < n; i++ { syscall.WaitForSingleObject(event1, syscall.INFINITE) - err := setEvent(event2) - if err != nil { - b.Fatal(err) + if err := setEvent(event2); err != nil { + b.Errorf("Set event failed: %v", err) + return } } }() for i := 0; i < n; i++ { - err := setEvent(event1) - if err != nil { + if err := setEvent(event1); err != nil { b.Fatal(err) } + if b.Failed() { + break + } syscall.WaitForSingleObject(event2, syscall.INFINITE) } } From 063a91c0abef445154df1ba34ffb500eeccfe8bc Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 30 Oct 2020 12:58:28 -0700 Subject: [PATCH 311/403] cmd/compile: fix recognition of unnamed return variables In golang.org/cl/266199, I reused the existing code in inlining that recognizes anonymous variables. However, it turns out that code mistakenly recognizes anonymous return parameters as named when inlining a function from the same package. The issue is funcargs (which is only used for functions parsed from source) synthesizes ~r names for anonymous return parameters, but funcargs2 (which is only used for functions imported from export data) does not. This CL fixes the behavior so that anonymous return parameters are handled identically whether a function is inlined within the same package or across packages. It also adds a proper cross-package test case demonstrating #33160 is fixed in both cases. Change-Id: Iaa39a23f5666979a1f5ca6d09fc8c398e55b784c Reviewed-on: https://go-review.googlesource.com/c/go/+/266719 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Cuong Manh Le Reviewed-by: David Chase Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/inl.go | 2 +- src/cmd/compile/internal/logopt/logopt_test.go | 8 ++++---- test/fixedbugs/issue42284.dir/a.go | 9 ++++++++- test/fixedbugs/issue42284.dir/b.go | 5 ++++- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 8a5c6d86666..253036fea64 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -1054,7 +1054,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node { var retvars []*Node for i, t := range fn.Type.Results().Fields().Slice() { var m *Node - if n := asNode(t.Nname); n != nil && !n.isBlank() { + if n := asNode(t.Nname); n != nil && !n.isBlank() && !strings.HasPrefix(n.Sym.Name, "~r") { m = inlvar(n) m = typecheck(m, ctxExpr) inlvars[n] = m diff --git a/src/cmd/compile/internal/logopt/logopt_test.go b/src/cmd/compile/internal/logopt/logopt_test.go index fca85c10fbb..51bab49518c 100644 --- a/src/cmd/compile/internal/logopt/logopt_test.go +++ b/src/cmd/compile/internal/logopt/logopt_test.go @@ -213,15 +213,15 @@ func s15a8(x *[15]int64) [15]int64 { `"relatedInformation":[`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y = z:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y := z (assign-pair)"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~r1 = y:"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~R0 = y:"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y.b (dot of pointer)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from \u0026y.b (address-of)"},`+ `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":9},"end":{"line":4,"character":9}}},"message":"inlineLoc"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~r1 = \u003cN\u003e (assign-pair)"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r2 = ~r1:"},`+ - `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return (*int)(~r1) (return)"}]}`) + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from ~R0 = \u003cN\u003e (assign-pair)"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: flow: ~r2 = ~R0:"},`+ + `{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":3},"end":{"line":9,"character":3}}},"message":"escflow: from return (*int)(~R0) (return)"}]}`) }) } diff --git a/test/fixedbugs/issue42284.dir/a.go b/test/fixedbugs/issue42284.dir/a.go index e1271af32d0..ffe9310be35 100644 --- a/test/fixedbugs/issue42284.dir/a.go +++ b/test/fixedbugs/issue42284.dir/a.go @@ -9,12 +9,19 @@ type T int func (T) M() {} // ERROR "can inline T.M" +func E() I { // ERROR "can inline E" + return T(0) // ERROR "T\(0\) escapes to heap" +} + func F(i I) I { // ERROR "can inline F" "leaking param: i to result ~r1 level=0" i = nil return i } -func g() { // ERROR "can inline g" +func g() { + h := E() // ERROR "inlining call to E" "T\(0\) does not escape" + h.M() // ERROR "devirtualizing h.M to T" + // BAD: T(0) could be stack allocated. i := F(T(0)) // ERROR "inlining call to F" "T\(0\) escapes to heap" diff --git a/test/fixedbugs/issue42284.dir/b.go b/test/fixedbugs/issue42284.dir/b.go index 3305166db06..652aa321226 100644 --- a/test/fixedbugs/issue42284.dir/b.go +++ b/test/fixedbugs/issue42284.dir/b.go @@ -6,7 +6,10 @@ package b import "./a" -func g() { // ERROR "can inline g" +func g() { + h := a.E() // ERROR "inlining call to a.E" "a.I\(a.T\(0\)\) does not escape" + h.M() // ERROR "devirtualizing h.M to a.T" + // BAD: T(0) could be stack allocated. i := a.F(a.T(0)) // ERROR "inlining call to a.F" "a.T\(0\) escapes to heap" From 5a267c840ae16c1cc7352caa14da5f500d03d338 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Fri, 29 May 2020 02:17:38 -0700 Subject: [PATCH 312/403] cmd/vet: bring in pass to catch invalid uses of testing.T in goroutines Add "go/analysis/passes/testinggoroutine" from x/tools and vendor its source in. This pass will catch misuses of: * testing.T.Fail* * testing.T.Fatal* * testing.T.Skip* inside goroutines explicitly started by the go keyword. The pass was implemented in CL 212920. While here, found 2 misuses in: * database/sql/sql_test.go * runtime/syscall_windows_test.go and fixed them in CL 235527. Fixes #5746 Change-Id: I1740ad3f1d677bb5d78dc5d8d66bac6ec287a2b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/235677 Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Emmanuel Odeke --- .../testinggoroutine/testinggoroutine.go | 154 ++++++++++++++++++ src/cmd/vet/main.go | 2 + 2 files changed, 156 insertions(+) create mode 100644 src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go new file mode 100644 index 00000000000..d2b9a5640d9 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go @@ -0,0 +1,154 @@ +// Copyright 2020 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 testinggoroutine + +import ( + "go/ast" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/analysis/passes/internal/analysisutil" + "golang.org/x/tools/go/ast/inspector" +) + +const Doc = `report calls to (*testing.T).Fatal from goroutines started by a test. + +Functions that abruptly terminate a test, such as the Fatal, Fatalf, FailNow, and +Skip{,f,Now} methods of *testing.T, must be called from the test goroutine itself. +This checker detects calls to these functions that occur within a goroutine +started by the test. For example: + +func TestFoo(t *testing.T) { + go func() { + t.Fatal("oops") // error: (*T).Fatal called from non-test goroutine + }() +} +` + +var Analyzer = &analysis.Analyzer{ + Name: "testinggoroutine", + Doc: Doc, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Run: run, +} + +var forbidden = map[string]bool{ + "FailNow": true, + "Fatal": true, + "Fatalf": true, + "Skip": true, + "Skipf": true, + "SkipNow": true, +} + +func run(pass *analysis.Pass) (interface{}, error) { + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + if !analysisutil.Imports(pass.Pkg, "testing") { + return nil, nil + } + + // Filter out anything that isn't a function declaration. + onlyFuncs := []ast.Node{ + (*ast.FuncDecl)(nil), + } + + inspect.Nodes(onlyFuncs, func(node ast.Node, push bool) bool { + fnDecl, ok := node.(*ast.FuncDecl) + if !ok { + return false + } + + if !hasBenchmarkOrTestParams(fnDecl) { + return false + } + + // Now traverse the benchmark/test's body and check that none of the + // forbidden methods are invoked in the goroutines within the body. + ast.Inspect(fnDecl, func(n ast.Node) bool { + goStmt, ok := n.(*ast.GoStmt) + if !ok { + return true + } + + checkGoStmt(pass, goStmt) + + // No need to further traverse the GoStmt since right + // above we manually traversed it in the ast.Inspect(goStmt, ...) + return false + }) + + return false + }) + + return nil, nil +} + +func hasBenchmarkOrTestParams(fnDecl *ast.FuncDecl) bool { + // Check that the function's arguments include "*testing.T" or "*testing.B". + params := fnDecl.Type.Params.List + + for _, param := range params { + if _, ok := typeIsTestingDotTOrB(param.Type); ok { + return true + } + } + + return false +} + +func typeIsTestingDotTOrB(expr ast.Expr) (string, bool) { + starExpr, ok := expr.(*ast.StarExpr) + if !ok { + return "", false + } + selExpr, ok := starExpr.X.(*ast.SelectorExpr) + if !ok { + return "", false + } + + varPkg := selExpr.X.(*ast.Ident) + if varPkg.Name != "testing" { + return "", false + } + + varTypeName := selExpr.Sel.Name + ok = varTypeName == "B" || varTypeName == "T" + return varTypeName, ok +} + +// checkGoStmt traverses the goroutine and checks for the +// use of the forbidden *testing.(B, T) methods. +func checkGoStmt(pass *analysis.Pass, goStmt *ast.GoStmt) { + // Otherwise examine the goroutine to check for the forbidden methods. + ast.Inspect(goStmt, func(n ast.Node) bool { + selExpr, ok := n.(*ast.SelectorExpr) + if !ok { + return true + } + + _, bad := forbidden[selExpr.Sel.Name] + if !bad { + return true + } + + // Now filter out false positives by the import-path/type. + ident, ok := selExpr.X.(*ast.Ident) + if !ok { + return true + } + if ident.Obj == nil || ident.Obj.Decl == nil { + return true + } + field, ok := ident.Obj.Decl.(*ast.Field) + if !ok { + return true + } + if typeName, ok := typeIsTestingDotTOrB(field.Type); ok { + pass.ReportRangef(selExpr, "call to (*%s).%s from a non-test goroutine", typeName, selExpr.Sel) + } + return true + }) +} diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go index 6381de840c0..bad3807039d 100644 --- a/src/cmd/vet/main.go +++ b/src/cmd/vet/main.go @@ -24,6 +24,7 @@ import ( "golang.org/x/tools/go/analysis/passes/stdmethods" "golang.org/x/tools/go/analysis/passes/stringintconv" "golang.org/x/tools/go/analysis/passes/structtag" + "golang.org/x/tools/go/analysis/passes/testinggoroutine" "golang.org/x/tools/go/analysis/passes/tests" "golang.org/x/tools/go/analysis/passes/unmarshal" "golang.org/x/tools/go/analysis/passes/unreachable" @@ -55,6 +56,7 @@ func main() { stringintconv.Analyzer, structtag.Analyzer, tests.Analyzer, + testinggoroutine.Analyzer, unmarshal.Analyzer, unreachable.Analyzer, unsafeptr.Analyzer, From 0be8280d8d01ef348fede17aef13aecf15cd7091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Derkacz?= Date: Thu, 29 Oct 2020 01:10:49 +0100 Subject: [PATCH 313/403] cmd/compile: optimize small zeroing/moving on riscv64 Optimize small (s <= 32) zeroing/moving operations on riscv64. Avoid generating unaligned memory accesses. The code is almost one to one translation of the corresponding mips64 rules with additional rule for s=32. Change-Id: I753b0b8e53cb9efcf43c8080cab90f3d03539fb8 Reviewed-on: https://go-review.googlesource.com/c/go/+/266217 Reviewed-by: Joel Sing Reviewed-by: Cherry Zhang --- .../compile/internal/ssa/gen/RISCV64.rules | 129 +++- .../compile/internal/ssa/rewriteRISCV64.go | 670 +++++++++++++++++- 2 files changed, 757 insertions(+), 42 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 449f3cad03c..4380a5efef7 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -9,7 +9,6 @@ // * Optimize left and right shift by simplifying SLTIU, Neg, and ADD for constants. // * Arrange for non-trivial Zero and Move lowerings to use aligned loads and stores. // * Eliminate zero immediate shifts, adds, etc. -// * Use a Duff's device for some moves and zeros. // * Avoid using Neq32 for writeBarrier.enabled checks. // Lowering arithmetic @@ -352,18 +351,64 @@ // with OffPtr -> ADDI. (ADDI [c] (MOVaddr [d] {s} x)) && is32Bit(c+int64(d)) => (MOVaddr [int32(c)+d] {s} x) -// Zeroing -// TODO: more optimized zeroing, including attempting to use aligned accesses. -(Zero [0] _ mem) => mem -(Zero [1] ptr mem) => (MOVBstore ptr (MOVBconst) mem) -(Zero [2] ptr mem) => (MOVHstore ptr (MOVHconst) mem) -(Zero [4] ptr mem) => (MOVWstore ptr (MOVWconst) mem) -(Zero [8] ptr mem) => (MOVDstore ptr (MOVDconst) mem) +// Small zeroing +(Zero [0] _ mem) => mem +(Zero [1] ptr mem) => (MOVBstore ptr (MOVBconst [0]) mem) +(Zero [2] {t} ptr mem) && t.Alignment()%2 == 0 => + (MOVHstore ptr (MOVHconst [0]) mem) +(Zero [2] ptr mem) => + (MOVBstore [1] ptr (MOVBconst [0]) + (MOVBstore ptr (MOVBconst [0]) mem)) +(Zero [4] {t} ptr mem) && t.Alignment()%4 == 0 => + (MOVWstore ptr (MOVWconst [0]) mem) +(Zero [4] {t} ptr mem) && t.Alignment()%2 == 0 => + (MOVHstore [2] ptr (MOVHconst [0]) + (MOVHstore ptr (MOVHconst [0]) mem)) +(Zero [4] ptr mem) => + (MOVBstore [3] ptr (MOVBconst [0]) + (MOVBstore [2] ptr (MOVBconst [0]) + (MOVBstore [1] ptr (MOVBconst [0]) + (MOVBstore ptr (MOVBconst [0]) mem)))) +(Zero [8] {t} ptr mem) && t.Alignment()%8 == 0 => + (MOVDstore ptr (MOVDconst [0]) mem) +(Zero [8] {t} ptr mem) && t.Alignment()%4 == 0 => + (MOVWstore [4] ptr (MOVWconst [0]) + (MOVWstore ptr (MOVWconst [0]) mem)) +(Zero [8] {t} ptr mem) && t.Alignment()%2 == 0 => + (MOVHstore [6] ptr (MOVHconst [0]) + (MOVHstore [4] ptr (MOVHconst [0]) + (MOVHstore [2] ptr (MOVHconst [0]) + (MOVHstore ptr (MOVHconst [0]) mem)))) -// Medium zeroing uses a Duff's device +(Zero [3] ptr mem) => + (MOVBstore [2] ptr (MOVBconst [0]) + (MOVBstore [1] ptr (MOVBconst [0]) + (MOVBstore ptr (MOVBconst [0]) mem))) +(Zero [6] {t} ptr mem) && t.Alignment()%2 == 0 => + (MOVHstore [4] ptr (MOVHconst [0]) + (MOVHstore [2] ptr (MOVHconst [0]) + (MOVHstore ptr (MOVHconst [0]) mem))) +(Zero [12] {t} ptr mem) && t.Alignment()%4 == 0 => + (MOVWstore [8] ptr (MOVWconst [0]) + (MOVWstore [4] ptr (MOVWconst [0]) + (MOVWstore ptr (MOVWconst [0]) mem))) +(Zero [16] {t} ptr mem) && t.Alignment()%8 == 0 => + (MOVDstore [8] ptr (MOVDconst [0]) + (MOVDstore ptr (MOVDconst [0]) mem)) +(Zero [24] {t} ptr mem) && t.Alignment()%8 == 0 => + (MOVDstore [16] ptr (MOVDconst [0]) + (MOVDstore [8] ptr (MOVDconst [0]) + (MOVDstore ptr (MOVDconst [0]) mem))) +(Zero [32] {t} ptr mem) && t.Alignment()%8 == 0 => + (MOVDstore [24] ptr (MOVDconst [0]) + (MOVDstore [16] ptr (MOVDconst [0]) + (MOVDstore [8] ptr (MOVDconst [0]) + (MOVDstore ptr (MOVDconst [0]) mem)))) + +// Medium 8-aligned zeroing uses a Duff's device // 8 and 128 are magic constants, see runtime/mkduff.go (Zero [s] {t} ptr mem) - && s%8 == 0 && s >= 16 && s <= 8*128 + && s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice => (DUFFZERO [8 * (128 - s/8)] ptr mem) @@ -377,7 +422,7 @@ (Convert ...) => (MOVconvert ...) // Checks -(IsNonNil p) => (NeqPtr (MOVDconst) p) +(IsNonNil p) => (NeqPtr (MOVDconst [0]) p) (IsInBounds ...) => (Less64U ...) (IsSliceInBounds ...) => (Leq64U ...) @@ -394,18 +439,64 @@ (PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem) (PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem) -// Moves -// TODO: more optimized moves, including attempting to use aligned accesses. -(Move [0] _ _ mem) => mem +// Small moves +(Move [0] _ _ mem) => mem (Move [1] dst src mem) => (MOVBstore dst (MOVBload src mem) mem) -(Move [2] dst src mem) => (MOVHstore dst (MOVHload src mem) mem) -(Move [4] dst src mem) => (MOVWstore dst (MOVWload src mem) mem) -(Move [8] dst src mem) => (MOVDstore dst (MOVDload src mem) mem) +(Move [2] {t} dst src mem) && t.Alignment()%2 == 0 => + (MOVHstore dst (MOVHload src mem) mem) +(Move [2] dst src mem) => + (MOVBstore [1] dst (MOVBload [1] src mem) + (MOVBstore dst (MOVBload src mem) mem)) +(Move [4] {t} dst src mem) && t.Alignment()%4 == 0 => + (MOVWstore dst (MOVWload src mem) mem) +(Move [4] {t} dst src mem) && t.Alignment()%2 == 0 => + (MOVHstore [2] dst (MOVHload [2] src mem) + (MOVHstore dst (MOVHload src mem) mem)) +(Move [4] dst src mem) => + (MOVBstore [3] dst (MOVBload [3] src mem) + (MOVBstore [2] dst (MOVBload [2] src mem) + (MOVBstore [1] dst (MOVBload [1] src mem) + (MOVBstore dst (MOVBload src mem) mem)))) +(Move [8] {t} dst src mem) && t.Alignment()%8 == 0 => + (MOVDstore dst (MOVDload src mem) mem) +(Move [8] {t} dst src mem) && t.Alignment()%4 == 0 => + (MOVWstore [4] dst (MOVWload [4] src mem) + (MOVWstore dst (MOVWload src mem) mem)) +(Move [8] {t} dst src mem) && t.Alignment()%2 == 0 => + (MOVHstore [6] dst (MOVHload [6] src mem) + (MOVHstore [4] dst (MOVHload [4] src mem) + (MOVHstore [2] dst (MOVHload [2] src mem) + (MOVHstore dst (MOVHload src mem) mem)))) -// Medium move uses a Duff's device +(Move [3] dst src mem) => + (MOVBstore [2] dst (MOVBload [2] src mem) + (MOVBstore [1] dst (MOVBload [1] src mem) + (MOVBstore dst (MOVBload src mem) mem))) +(Move [6] {t} dst src mem) && t.Alignment()%2 == 0 => + (MOVHstore [4] dst (MOVHload [4] src mem) + (MOVHstore [2] dst (MOVHload [2] src mem) + (MOVHstore dst (MOVHload src mem) mem))) +(Move [12] {t} dst src mem) && t.Alignment()%4 == 0 => + (MOVWstore [8] dst (MOVWload [8] src mem) + (MOVWstore [4] dst (MOVWload [4] src mem) + (MOVWstore dst (MOVWload src mem) mem))) +(Move [16] {t} dst src mem) && t.Alignment()%8 == 0 => + (MOVDstore [8] dst (MOVDload [8] src mem) + (MOVDstore dst (MOVDload src mem) mem)) +(Move [24] {t} dst src mem) && t.Alignment()%8 == 0 => + (MOVDstore [16] dst (MOVDload [16] src mem) + (MOVDstore [8] dst (MOVDload [8] src mem) + (MOVDstore dst (MOVDload src mem) mem))) +(Move [32] {t} dst src mem) && t.Alignment()%8 == 0 => + (MOVDstore [24] dst (MOVDload [24] src mem) + (MOVDstore [16] dst (MOVDload [16] src mem) + (MOVDstore [8] dst (MOVDload [8] src mem) + (MOVDstore dst (MOVDload src mem) mem)))) + +// Medium 8-aligned move uses a Duff's device // 16 and 128 are magic constants, see runtime/mkduff.go (Move [s] {t} dst src mem) - && s%8 == 0 && s >= 16 && s <= 8*128 && t.Alignment()%8 == 0 + && s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s) => (DUFFCOPY [16 * (128 - s/8)] dst src mem) diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index a91e8428ef0..fb507b65c4c 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -4,6 +4,7 @@ package ssa import "math" +import "cmd/compile/internal/types" func rewriteValueRISCV64(v *Value) bool { switch v.Op { @@ -1020,11 +1021,12 @@ func rewriteValueRISCV64_OpIsNonNil(v *Value) bool { b := v.Block typ := &b.Func.Config.Types // match: (IsNonNil p) - // result: (NeqPtr (MOVDconst) p) + // result: (NeqPtr (MOVDconst [0]) p) for { p := v_0 v.reset(OpNeqPtr) v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64) + v0.AuxInt = int64ToAuxInt(0) v.AddArg2(v0, p) return true } @@ -1971,8 +1973,28 @@ func rewriteValueRISCV64_OpMove(v *Value) bool { v.AddArg3(dst, v0, mem) return true } - // match: (Move [2] dst src mem) + // match: (Move [2] {t} dst src mem) + // cond: t.Alignment()%2 == 0 // result: (MOVHstore dst (MOVHload src mem) mem) + for { + if auxIntToInt64(v.AuxInt) != 2 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v0.AddArg2(src, mem) + v.AddArg3(dst, v0, mem) + return true + } + // match: (Move [2] dst src mem) + // result: (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem)) for { if auxIntToInt64(v.AuxInt) != 2 { break @@ -1980,14 +2002,66 @@ func rewriteValueRISCV64_OpMove(v *Value) bool { dst := v_0 src := v_1 mem := v_2 - v.reset(OpRISCV64MOVHstore) - v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v.reset(OpRISCV64MOVBstore) + v.AuxInt = int32ToAuxInt(1) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v0.AuxInt = int32ToAuxInt(1) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v2.AddArg2(src, mem) + v1.AddArg3(dst, v2, mem) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [4] {t} dst src mem) + // cond: t.Alignment()%4 == 0 + // result: (MOVWstore dst (MOVWload src mem) mem) + for { + if auxIntToInt64(v.AuxInt) != 4 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%4 == 0) { + break + } + v.reset(OpRISCV64MOVWstore) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32) v0.AddArg2(src, mem) v.AddArg3(dst, v0, mem) return true } + // match: (Move [4] {t} dst src mem) + // cond: t.Alignment()%2 == 0 + // result: (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem)) + for { + if auxIntToInt64(v.AuxInt) != 4 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v.AuxInt = int32ToAuxInt(2) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v0.AuxInt = int32ToAuxInt(2) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v2.AddArg2(src, mem) + v1.AddArg3(dst, v2, mem) + v.AddArg3(dst, v0, v1) + return true + } // match: (Move [4] dst src mem) - // result: (MOVWstore dst (MOVWload src mem) mem) + // result: (MOVBstore [3] dst (MOVBload [3] src mem) (MOVBstore [2] dst (MOVBload [2] src mem) (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem)))) for { if auxIntToInt64(v.AuxInt) != 4 { break @@ -1995,29 +2069,303 @@ func rewriteValueRISCV64_OpMove(v *Value) bool { dst := v_0 src := v_1 mem := v_2 - v.reset(OpRISCV64MOVWstore) - v0 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32) + v.reset(OpRISCV64MOVBstore) + v.AuxInt = int32ToAuxInt(3) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v0.AuxInt = int32ToAuxInt(3) v0.AddArg2(src, mem) - v.AddArg3(dst, v0, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(2) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v2.AuxInt = int32ToAuxInt(2) + v2.AddArg2(src, mem) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v3.AuxInt = int32ToAuxInt(1) + v4 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v4.AuxInt = int32ToAuxInt(1) + v4.AddArg2(src, mem) + v5 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v6 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v6.AddArg2(src, mem) + v5.AddArg3(dst, v6, mem) + v3.AddArg3(dst, v4, v5) + v1.AddArg3(dst, v2, v3) + v.AddArg3(dst, v0, v1) return true } - // match: (Move [8] dst src mem) + // match: (Move [8] {t} dst src mem) + // cond: t.Alignment()%8 == 0 // result: (MOVDstore dst (MOVDload src mem) mem) for { if auxIntToInt64(v.AuxInt) != 8 { break } + t := auxToType(v.Aux) dst := v_0 src := v_1 mem := v_2 + if !(t.Alignment()%8 == 0) { + break + } v.reset(OpRISCV64MOVDstore) v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) v0.AddArg2(src, mem) v.AddArg3(dst, v0, mem) return true } + // match: (Move [8] {t} dst src mem) + // cond: t.Alignment()%4 == 0 + // result: (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem)) + for { + if auxIntToInt64(v.AuxInt) != 8 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%4 == 0) { + break + } + v.reset(OpRISCV64MOVWstore) + v.AuxInt = int32ToAuxInt(4) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32) + v0.AuxInt = int32ToAuxInt(4) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32) + v2.AddArg2(src, mem) + v1.AddArg3(dst, v2, mem) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [8] {t} dst src mem) + // cond: t.Alignment()%2 == 0 + // result: (MOVHstore [6] dst (MOVHload [6] src mem) (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem)))) + for { + if auxIntToInt64(v.AuxInt) != 8 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v.AuxInt = int32ToAuxInt(6) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v0.AuxInt = int32ToAuxInt(6) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(4) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v2.AuxInt = int32ToAuxInt(4) + v2.AddArg2(src, mem) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v3.AuxInt = int32ToAuxInt(2) + v4 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v4.AuxInt = int32ToAuxInt(2) + v4.AddArg2(src, mem) + v5 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v6 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v6.AddArg2(src, mem) + v5.AddArg3(dst, v6, mem) + v3.AddArg3(dst, v4, v5) + v1.AddArg3(dst, v2, v3) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [3] dst src mem) + // result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVBstore [1] dst (MOVBload [1] src mem) (MOVBstore dst (MOVBload src mem) mem))) + for { + if auxIntToInt64(v.AuxInt) != 3 { + break + } + dst := v_0 + src := v_1 + mem := v_2 + v.reset(OpRISCV64MOVBstore) + v.AuxInt = int32ToAuxInt(2) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v0.AuxInt = int32ToAuxInt(2) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(1) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v2.AuxInt = int32ToAuxInt(1) + v2.AddArg2(src, mem) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v4 := b.NewValue0(v.Pos, OpRISCV64MOVBload, typ.Int8) + v4.AddArg2(src, mem) + v3.AddArg3(dst, v4, mem) + v1.AddArg3(dst, v2, v3) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [6] {t} dst src mem) + // cond: t.Alignment()%2 == 0 + // result: (MOVHstore [4] dst (MOVHload [4] src mem) (MOVHstore [2] dst (MOVHload [2] src mem) (MOVHstore dst (MOVHload src mem) mem))) + for { + if auxIntToInt64(v.AuxInt) != 6 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v.AuxInt = int32ToAuxInt(4) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v0.AuxInt = int32ToAuxInt(4) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(2) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v2.AuxInt = int32ToAuxInt(2) + v2.AddArg2(src, mem) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v4 := b.NewValue0(v.Pos, OpRISCV64MOVHload, typ.Int16) + v4.AddArg2(src, mem) + v3.AddArg3(dst, v4, mem) + v1.AddArg3(dst, v2, v3) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [12] {t} dst src mem) + // cond: t.Alignment()%4 == 0 + // result: (MOVWstore [8] dst (MOVWload [8] src mem) (MOVWstore [4] dst (MOVWload [4] src mem) (MOVWstore dst (MOVWload src mem) mem))) + for { + if auxIntToInt64(v.AuxInt) != 12 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%4 == 0) { + break + } + v.reset(OpRISCV64MOVWstore) + v.AuxInt = int32ToAuxInt(8) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32) + v0.AuxInt = int32ToAuxInt(8) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(4) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32) + v2.AuxInt = int32ToAuxInt(4) + v2.AddArg2(src, mem) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem) + v4 := b.NewValue0(v.Pos, OpRISCV64MOVWload, typ.Int32) + v4.AddArg2(src, mem) + v3.AddArg3(dst, v4, mem) + v1.AddArg3(dst, v2, v3) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [16] {t} dst src mem) + // cond: t.Alignment()%8 == 0 + // result: (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem)) + for { + if auxIntToInt64(v.AuxInt) != 16 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%8 == 0) { + break + } + v.reset(OpRISCV64MOVDstore) + v.AuxInt = int32ToAuxInt(8) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v0.AuxInt = int32ToAuxInt(8) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v2.AddArg2(src, mem) + v1.AddArg3(dst, v2, mem) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [24] {t} dst src mem) + // cond: t.Alignment()%8 == 0 + // result: (MOVDstore [16] dst (MOVDload [16] src mem) (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem))) + for { + if auxIntToInt64(v.AuxInt) != 24 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%8 == 0) { + break + } + v.reset(OpRISCV64MOVDstore) + v.AuxInt = int32ToAuxInt(16) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v0.AuxInt = int32ToAuxInt(16) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(8) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v2.AuxInt = int32ToAuxInt(8) + v2.AddArg2(src, mem) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v4 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v4.AddArg2(src, mem) + v3.AddArg3(dst, v4, mem) + v1.AddArg3(dst, v2, v3) + v.AddArg3(dst, v0, v1) + return true + } + // match: (Move [32] {t} dst src mem) + // cond: t.Alignment()%8 == 0 + // result: (MOVDstore [24] dst (MOVDload [24] src mem) (MOVDstore [16] dst (MOVDload [16] src mem) (MOVDstore [8] dst (MOVDload [8] src mem) (MOVDstore dst (MOVDload src mem) mem)))) + for { + if auxIntToInt64(v.AuxInt) != 32 { + break + } + t := auxToType(v.Aux) + dst := v_0 + src := v_1 + mem := v_2 + if !(t.Alignment()%8 == 0) { + break + } + v.reset(OpRISCV64MOVDstore) + v.AuxInt = int32ToAuxInt(24) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v0.AuxInt = int32ToAuxInt(24) + v0.AddArg2(src, mem) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(16) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v2.AuxInt = int32ToAuxInt(16) + v2.AddArg2(src, mem) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v3.AuxInt = int32ToAuxInt(8) + v4 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v4.AuxInt = int32ToAuxInt(8) + v4.AddArg2(src, mem) + v5 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v6 := b.NewValue0(v.Pos, OpRISCV64MOVDload, typ.Int64) + v6.AddArg2(src, mem) + v5.AddArg3(dst, v6, mem) + v3.AddArg3(dst, v4, v5) + v1.AddArg3(dst, v2, v3) + v.AddArg3(dst, v0, v1) + return true + } // match: (Move [s] {t} dst src mem) - // cond: s%8 == 0 && s >= 16 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s) + // cond: s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s) // result: (DUFFCOPY [16 * (128 - s/8)] dst src mem) for { s := auxIntToInt64(v.AuxInt) @@ -2025,7 +2373,7 @@ func rewriteValueRISCV64_OpMove(v *Value) bool { dst := v_0 src := v_1 mem := v_2 - if !(s%8 == 0 && s >= 16 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) { + if !(s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) { break } v.reset(OpRISCV64DUFFCOPY) @@ -5747,7 +6095,7 @@ func rewriteValueRISCV64_OpZero(v *Value) bool { return true } // match: (Zero [1] ptr mem) - // result: (MOVBstore ptr (MOVBconst) mem) + // result: (MOVBstore ptr (MOVBconst [0]) mem) for { if auxIntToInt64(v.AuxInt) != 1 { break @@ -5756,57 +6104,333 @@ func rewriteValueRISCV64_OpZero(v *Value) bool { mem := v_1 v.reset(OpRISCV64MOVBstore) v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8) + v0.AuxInt = int8ToAuxInt(0) + v.AddArg3(ptr, v0, mem) + return true + } + // match: (Zero [2] {t} ptr mem) + // cond: t.Alignment()%2 == 0 + // result: (MOVHstore ptr (MOVHconst [0]) mem) + for { + if auxIntToInt64(v.AuxInt) != 2 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16) + v0.AuxInt = int16ToAuxInt(0) v.AddArg3(ptr, v0, mem) return true } // match: (Zero [2] ptr mem) - // result: (MOVHstore ptr (MOVHconst) mem) + // result: (MOVBstore [1] ptr (MOVBconst [0]) (MOVBstore ptr (MOVBconst [0]) mem)) for { if auxIntToInt64(v.AuxInt) != 2 { break } ptr := v_0 mem := v_1 - v.reset(OpRISCV64MOVHstore) - v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16) + v.reset(OpRISCV64MOVBstore) + v.AuxInt = int32ToAuxInt(1) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8) + v0.AuxInt = int8ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v1.AddArg3(ptr, v0, mem) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [4] {t} ptr mem) + // cond: t.Alignment()%4 == 0 + // result: (MOVWstore ptr (MOVWconst [0]) mem) + for { + if auxIntToInt64(v.AuxInt) != 4 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%4 == 0) { + break + } + v.reset(OpRISCV64MOVWstore) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32) + v0.AuxInt = int32ToAuxInt(0) v.AddArg3(ptr, v0, mem) return true } + // match: (Zero [4] {t} ptr mem) + // cond: t.Alignment()%2 == 0 + // result: (MOVHstore [2] ptr (MOVHconst [0]) (MOVHstore ptr (MOVHconst [0]) mem)) + for { + if auxIntToInt64(v.AuxInt) != 4 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v.AuxInt = int32ToAuxInt(2) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16) + v0.AuxInt = int16ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v1.AddArg3(ptr, v0, mem) + v.AddArg3(ptr, v0, v1) + return true + } // match: (Zero [4] ptr mem) - // result: (MOVWstore ptr (MOVWconst) mem) + // result: (MOVBstore [3] ptr (MOVBconst [0]) (MOVBstore [2] ptr (MOVBconst [0]) (MOVBstore [1] ptr (MOVBconst [0]) (MOVBstore ptr (MOVBconst [0]) mem)))) for { if auxIntToInt64(v.AuxInt) != 4 { break } ptr := v_0 mem := v_1 - v.reset(OpRISCV64MOVWstore) - v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32) - v.AddArg3(ptr, v0, mem) + v.reset(OpRISCV64MOVBstore) + v.AuxInt = int32ToAuxInt(3) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8) + v0.AuxInt = int8ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(2) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v2.AuxInt = int32ToAuxInt(1) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v3.AddArg3(ptr, v0, mem) + v2.AddArg3(ptr, v0, v3) + v1.AddArg3(ptr, v0, v2) + v.AddArg3(ptr, v0, v1) return true } - // match: (Zero [8] ptr mem) - // result: (MOVDstore ptr (MOVDconst) mem) + // match: (Zero [8] {t} ptr mem) + // cond: t.Alignment()%8 == 0 + // result: (MOVDstore ptr (MOVDconst [0]) mem) for { if auxIntToInt64(v.AuxInt) != 8 { break } + t := auxToType(v.Aux) ptr := v_0 mem := v_1 + if !(t.Alignment()%8 == 0) { + break + } v.reset(OpRISCV64MOVDstore) v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64) + v0.AuxInt = int64ToAuxInt(0) v.AddArg3(ptr, v0, mem) return true } + // match: (Zero [8] {t} ptr mem) + // cond: t.Alignment()%4 == 0 + // result: (MOVWstore [4] ptr (MOVWconst [0]) (MOVWstore ptr (MOVWconst [0]) mem)) + for { + if auxIntToInt64(v.AuxInt) != 8 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%4 == 0) { + break + } + v.reset(OpRISCV64MOVWstore) + v.AuxInt = int32ToAuxInt(4) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32) + v0.AuxInt = int32ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem) + v1.AddArg3(ptr, v0, mem) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [8] {t} ptr mem) + // cond: t.Alignment()%2 == 0 + // result: (MOVHstore [6] ptr (MOVHconst [0]) (MOVHstore [4] ptr (MOVHconst [0]) (MOVHstore [2] ptr (MOVHconst [0]) (MOVHstore ptr (MOVHconst [0]) mem)))) + for { + if auxIntToInt64(v.AuxInt) != 8 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v.AuxInt = int32ToAuxInt(6) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16) + v0.AuxInt = int16ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(4) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v2.AuxInt = int32ToAuxInt(2) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v3.AddArg3(ptr, v0, mem) + v2.AddArg3(ptr, v0, v3) + v1.AddArg3(ptr, v0, v2) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [3] ptr mem) + // result: (MOVBstore [2] ptr (MOVBconst [0]) (MOVBstore [1] ptr (MOVBconst [0]) (MOVBstore ptr (MOVBconst [0]) mem))) + for { + if auxIntToInt64(v.AuxInt) != 3 { + break + } + ptr := v_0 + mem := v_1 + v.reset(OpRISCV64MOVBstore) + v.AuxInt = int32ToAuxInt(2) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVBconst, typ.UInt8) + v0.AuxInt = int8ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(1) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVBstore, types.TypeMem) + v2.AddArg3(ptr, v0, mem) + v1.AddArg3(ptr, v0, v2) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [6] {t} ptr mem) + // cond: t.Alignment()%2 == 0 + // result: (MOVHstore [4] ptr (MOVHconst [0]) (MOVHstore [2] ptr (MOVHconst [0]) (MOVHstore ptr (MOVHconst [0]) mem))) + for { + if auxIntToInt64(v.AuxInt) != 6 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%2 == 0) { + break + } + v.reset(OpRISCV64MOVHstore) + v.AuxInt = int32ToAuxInt(4) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVHconst, typ.UInt16) + v0.AuxInt = int16ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(2) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVHstore, types.TypeMem) + v2.AddArg3(ptr, v0, mem) + v1.AddArg3(ptr, v0, v2) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [12] {t} ptr mem) + // cond: t.Alignment()%4 == 0 + // result: (MOVWstore [8] ptr (MOVWconst [0]) (MOVWstore [4] ptr (MOVWconst [0]) (MOVWstore ptr (MOVWconst [0]) mem))) + for { + if auxIntToInt64(v.AuxInt) != 12 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%4 == 0) { + break + } + v.reset(OpRISCV64MOVWstore) + v.AuxInt = int32ToAuxInt(8) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVWconst, typ.UInt32) + v0.AuxInt = int32ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(4) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVWstore, types.TypeMem) + v2.AddArg3(ptr, v0, mem) + v1.AddArg3(ptr, v0, v2) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [16] {t} ptr mem) + // cond: t.Alignment()%8 == 0 + // result: (MOVDstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem)) + for { + if auxIntToInt64(v.AuxInt) != 16 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%8 == 0) { + break + } + v.reset(OpRISCV64MOVDstore) + v.AuxInt = int32ToAuxInt(8) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64) + v0.AuxInt = int64ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v1.AddArg3(ptr, v0, mem) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [24] {t} ptr mem) + // cond: t.Alignment()%8 == 0 + // result: (MOVDstore [16] ptr (MOVDconst [0]) (MOVDstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem))) + for { + if auxIntToInt64(v.AuxInt) != 24 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%8 == 0) { + break + } + v.reset(OpRISCV64MOVDstore) + v.AuxInt = int32ToAuxInt(16) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64) + v0.AuxInt = int64ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(8) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v2.AddArg3(ptr, v0, mem) + v1.AddArg3(ptr, v0, v2) + v.AddArg3(ptr, v0, v1) + return true + } + // match: (Zero [32] {t} ptr mem) + // cond: t.Alignment()%8 == 0 + // result: (MOVDstore [24] ptr (MOVDconst [0]) (MOVDstore [16] ptr (MOVDconst [0]) (MOVDstore [8] ptr (MOVDconst [0]) (MOVDstore ptr (MOVDconst [0]) mem)))) + for { + if auxIntToInt64(v.AuxInt) != 32 { + break + } + t := auxToType(v.Aux) + ptr := v_0 + mem := v_1 + if !(t.Alignment()%8 == 0) { + break + } + v.reset(OpRISCV64MOVDstore) + v.AuxInt = int32ToAuxInt(24) + v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64) + v0.AuxInt = int64ToAuxInt(0) + v1 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v1.AuxInt = int32ToAuxInt(16) + v2 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v2.AuxInt = int32ToAuxInt(8) + v3 := b.NewValue0(v.Pos, OpRISCV64MOVDstore, types.TypeMem) + v3.AddArg3(ptr, v0, mem) + v2.AddArg3(ptr, v0, v3) + v1.AddArg3(ptr, v0, v2) + v.AddArg3(ptr, v0, v1) + return true + } // match: (Zero [s] {t} ptr mem) - // cond: s%8 == 0 && s >= 16 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice + // cond: s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice // result: (DUFFZERO [8 * (128 - s/8)] ptr mem) for { s := auxIntToInt64(v.AuxInt) t := auxToType(v.Aux) ptr := v_0 mem := v_1 - if !(s%8 == 0 && s >= 16 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice) { + if !(s%8 == 0 && s <= 8*128 && t.Alignment()%8 == 0 && !config.noDuffDevice) { break } v.reset(OpRISCV64DUFFZERO) From 333d2010ec98aaea244b65b7bc4d7d80c71e21b1 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Sun, 1 Nov 2020 06:54:21 +0000 Subject: [PATCH 314/403] cmd/go: revert "support cgo files in overlays" This reverts CL 262618 (commit 48be3ed1394d85af5a7e1a6313fa9cab4d1b7cf9). Reason for revert: breaks longtest builders. Change-Id: Iec1e236ba793f24394442d04eb846f8a73ab2e68 Reviewed-on: https://go-review.googlesource.com/c/go/+/267037 Trust: Dmitri Shuralyov Trust: Alberto Donizetti Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Alberto Donizetti --- src/cmd/go/internal/work/exec.go | 48 ++--------- src/cmd/go/internal/work/gc.go | 9 +- src/cmd/go/testdata/script/build_overlay.txt | 83 +------------------ .../go/testdata/script/build_trimpath_cgo.txt | 28 ------- 4 files changed, 12 insertions(+), 156 deletions(-) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index a1a357e2acc..838b00a00d2 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -8,7 +8,6 @@ package work import ( "bytes" - "cmd/go/internal/fsys" "context" "encoding/json" "errors" @@ -2243,6 +2242,8 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s // when -trimpath is enabled. if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") { if cfg.BuildTrimpath { + // TODO(#39958): handle overlays + // Keep in sync with Action.trimpath. // The trimmed paths are a little different, but we need to trim in the // same situations. @@ -2312,8 +2313,7 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag cmdargs := []interface{}{cmd, "-o", outfile, objs, flags} dir := p.Dir - out, err := b.runOut(a, base.Cwd, b.cCompilerEnv(), cmdargs...) - + out, err := b.runOut(a, dir, b.cCompilerEnv(), cmdargs...) if len(out) > 0 { // Filter out useless linker warnings caused by bugs outside Go. // See also cmd/link/internal/ld's hostlink method. @@ -2641,8 +2641,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...) } - // Allows including _cgo_export.h, as well as the user's .h files, - // from .[ch] files in the package. + // Allows including _cgo_export.h from .[ch] files in the package. cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", objdir) // cgo @@ -2655,8 +2654,6 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cfiles = append(cfiles, f+".cgo2.c") } - hfiles := append([]string{}, p.HFiles...) - // TODO: make cgo not depend on $GOARCH? cgoflags := []string{} @@ -2701,38 +2698,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h") } - execdir := p.Dir - - // If any of the Cgo, C, or H files are overlaid, copy them all to - // objdir to ensure that they refer to the right header files. - // TODO(#39958): Ideally, we'd always do this, but this could - // subtly break some cgo files that include .h files across directory - // boundaries, even though they shouldn't. - hasOverlay := false - cgoFileLists := [][]string{cgofiles, gccfiles, gxxfiles, mfiles, ffiles, hfiles} -OverlayLoop: - for _, fs := range cgoFileLists { - for _, f := range fs { - if _, ok := fsys.OverlayPath(mkAbs(p.Dir, f)); ok { - hasOverlay = true - break OverlayLoop - } - } - } - if hasOverlay { - execdir = objdir - for _, fs := range cgoFileLists { - for i := range fs { - opath, _ := fsys.OverlayPath(mkAbs(p.Dir, fs[i])) - fs[i] = objdir + filepath.Base(fs[i]) - if err := b.copyFile(fs[i], opath, 0666, false); err != nil { - return nil, nil, err - } - } - } - } - - if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { + if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { return nil, nil, err } outGo = append(outGo, gofiles...) @@ -2826,7 +2792,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe return err } - linkobj := str.StringList(ofile, outObj, mkAbsFiles(p.Dir, p.SysoFiles)) + linkobj := str.StringList(ofile, outObj, p.SysoFiles) dynobj := objdir + "_cgo_.o" // we need to use -pie for Linux/ARM to get accurate imported sym @@ -2851,7 +2817,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = []string{"-dynlinker"} // record path to dynamic linker } - return b.run(a, base.Cwd, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) } // Run SWIG on all SWIG input files. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 4ba9be78296..e79173485db 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -262,7 +262,7 @@ func (a *Action) trimpath() string { if len(objdir) > 1 && objdir[len(objdir)-1] == filepath.Separator { objdir = objdir[:len(objdir)-1] } - rewrite := "" + rewrite := objdir + "=>" rewriteDir := a.Package.Dir if cfg.BuildTrimpath { @@ -271,7 +271,7 @@ func (a *Action) trimpath() string { } else { rewriteDir = a.Package.ImportPath } - rewrite += a.Package.Dir + "=>" + rewriteDir + ";" + rewrite += ";" + a.Package.Dir + "=>" + rewriteDir } // Add rewrites for overlays. The 'from' and 'to' paths in overlays don't need to have @@ -280,14 +280,11 @@ func (a *Action) trimpath() string { if fsys.OverlayFile != "" { for _, filename := range a.Package.AllFiles() { overlayPath, ok := fsys.OverlayPath(filepath.Join(a.Package.Dir, filename)) - rewrite += filepath.Join(objdir, filename) + "=>" + filepath.Join(rewriteDir, filename) + ";" if !ok { continue } - rewrite += overlayPath + "=>" + filepath.Join(rewriteDir, filename) + ";" + rewrite += ";" + overlayPath + "=>" + filepath.Join(rewriteDir, filename) } - } else { - rewrite += objdir + "=>" } return rewrite diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt index 3af10083af6..0602e706e9e 100644 --- a/src/cmd/go/testdata/script/build_overlay.txt +++ b/src/cmd/go/testdata/script/build_overlay.txt @@ -1,11 +1,9 @@ [short] skip # Test building in overlays. -# TODO(#39958): add a test case where the destination file in the replace map +# TODO(matloob): add a test case where the destination file in the replace map # isn't a go file. Either completely exclude that case in fs.IsDirWithGoFiles # if the compiler doesn't allow it, or test that it works all the way. -# TODO(#39958): add a test that both gc and gccgo assembly files can include .h -# files. # The main package (m) is contained in an overlay. It imports m/dir2 which has one # file in an overlay and one file outside the overlay, which in turn imports m/dir, @@ -31,18 +29,6 @@ exec ./print_trimpath_two_files$GOEXE stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go -go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace -exec ./main_cgo_replace$GOEXE -stdout '^hello cgo$' - -go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote -exec ./main_cgo_quote$GOEXE -stdout '^hello cgo$' - -go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle -exec ./main_cgo_angle$GOEXE -stdout '^hello cgo$' - # Run same tests but with gccgo. env GO111MODULE=off [!exec:gccgo] stop @@ -60,19 +46,6 @@ go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -tr exec ./print_trimpath_gccgo$GOEXE stdout ^\.[/\\]printpath[/\\]main.go - -go build -compiler=gccgo -overlay overlay.json -o main_cgo_replace_gccgo$GOEXE ./cgo_hello_replace -exec ./main_cgo_replace_gccgo$GOEXE -stdout '^hello cgo$' - -go build -compiler=gccgo -overlay overlay.json -o main_cgo_quote_gccgo$GOEXE ./cgo_hello_quote -exec ./main_cgo_quote_gccgo$GOEXE -stdout '^hello cgo$' - -go build -compiler=gccgo -overlay overlay.json -o main_cgo_angle_gccgo$GOEXE ./cgo_hello_angle -exec ./main_cgo_angle_gccgo$GOEXE -stdout '^hello cgo$' - -- m/go.mod -- // TODO(matloob): how do overlays work with go.mod (especially if mod=readonly) module m @@ -98,32 +71,9 @@ the actual code is in the overlay "dir/g.go": "overlay/dir_g.go", "dir2/i.go": "overlay/dir2_i.go", "printpath/main.go": "overlay/printpath.go", - "printpath/other.go": "overlay2/printpath2.go", - "cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h", - "cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go", - "cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h", - "cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go", - "cgo_hello_angle/cgo_header.h": "overlay/cgo_head.h" + "printpath/other.go": "overlay2/printpath2.go" } } --- m/cgo_hello_replace/cgo_hello_replace.go -- -package main - -// #include "cgo_header.h" -import "C" - -func main() { - C.say_hello() -} --- m/cgo_hello_replace/cgo_header.h -- - // Test that this header is replaced with one that has the proper declaration. -void say_goodbye(); - --- m/cgo_hello_replace/goodbye.c -- -#include - -void say_hello() { puts("hello cgo\n"); } - -- m/overlay/f.go -- package main @@ -178,32 +128,3 @@ import "m/dir" func printMessage() { dir.PrintMessage() } --- m/overlay/cgo_hello_quote.go -- -package main - -// #include "cgo_header.h" -import "C" - -func main() { - C.say_hello() -} --- m/overlay/cgo_hello_angle.go -- -package main - -// #include -import "C" - -func main() { - C.say_hello() -} --- m/overlay/cgo_head.h -- -void say_hello(); --- m/cgo_hello_quote/hello.c -- -#include - -void say_hello() { puts("hello cgo\n"); } --- m/cgo_hello_angle/hello.c -- -#include - -void say_hello() { puts("hello cgo\n"); } - diff --git a/src/cmd/go/testdata/script/build_trimpath_cgo.txt b/src/cmd/go/testdata/script/build_trimpath_cgo.txt index 3187b4d6439..4608d9ac6bf 100644 --- a/src/cmd/go/testdata/script/build_trimpath_cgo.txt +++ b/src/cmd/go/testdata/script/build_trimpath_cgo.txt @@ -20,38 +20,10 @@ go build -trimpath -o hello.exe . go run ./list-dwarf hello.exe ! stdout gopath/src - -# Do the above, with the cgo (but not .c) sources in an overlay -# Check that the source path appears when -trimpath is not used. -mkdir $WORK/overlay -cp hello.go $WORK/overlay/hello.go -mkdir hello_overlay -cp hello.c hello_overlay/hello.c -go build -overlay overlay.json -o hello_overlay.exe ./hello_overlay -grep -q gopath[/\\]src hello_overlay.exe -! grep -q $WORK[/\\]overlay hello_overlay.exe -go run ./list-dwarf hello_overlay.exe -stdout gopath[/\\]src -! stdout $WORK[/\\]overlay - -# Check that the source path does not appear when -trimpath is used. -go build -overlay overlay.json -trimpath -o hello_overlay.exe ./hello_overlay -! grep -q gopath[/\\]src hello_overlay.exe -! grep -q $WORK[/\\]overlay hello_overlay.exe -go run ./list-dwarf hello_overlay.exe -! stdout gopath/src -! stdout $WORK[/\\]overlay - -- go.mod -- module m go 1.14 --- overlay.json -- -{ - "Replace": { - "hello_overlay/hello.go": "../../overlay/hello.go" - } -} -- hello.c -- #include From e463c28cc116fb1f40a4e203bddf93b6ef52c8d9 Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Thu, 22 Oct 2020 22:32:20 +0200 Subject: [PATCH 315/403] cmd/link: avoid exporting all symbols on windows buildmode=pie Marking one functions with __declspec(dllexport) forces mingw to create .reloc section without having to export all symbols. See https://insights.sei.cmu.edu/cert/2018/08/when-aslr-is-not-really-aslr---the-case-of-incorrect-assumptions-and-bad-defaults.html for more info. This change cuts 73kb of a "hello world" pie binary. Updates #6853 Fixes #40795 Change-Id: I3cc57c3b64f61187550bc8751dfa085f106c8475 Reviewed-on: https://go-review.googlesource.com/c/go/+/264459 Trust: Alex Brainman Run-TryBot: Alex Brainman TryBot-Result: Go Bot Reviewed-by: Alex Brainman Reviewed-by: Austin Clements --- misc/cgo/testcshared/cshared_test.go | 9 ++++---- src/cmd/go/go_test.go | 33 ++++++++++++++++++++++++++++ src/cmd/link/internal/ld/lib.go | 3 --- src/runtime/cgo/gcc_windows_386.c | 1 + src/runtime/cgo/gcc_windows_amd64.c | 1 + src/runtime/cgo/libcgo_windows.h | 12 ++++++++++ 6 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 src/runtime/cgo/libcgo_windows.h diff --git a/misc/cgo/testcshared/cshared_test.go b/misc/cgo/testcshared/cshared_test.go index e1835afa513..3a4886cf30a 100644 --- a/misc/cgo/testcshared/cshared_test.go +++ b/misc/cgo/testcshared/cshared_test.go @@ -401,7 +401,7 @@ func main() { defer f.Close() section := f.Section(".edata") if section == nil { - t.Error(".edata section is not present") + t.Fatalf(".edata section is not present") } // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go @@ -418,7 +418,8 @@ func main() { t.Fatalf("binary.Read failed: %v", err) } - expectedNumber := uint32(2) + // Only the two exported functions and _cgo_dummy_export should be exported + expectedNumber := uint32(3) if exportAllSymbols { if e.NumberOfFunctions <= expectedNumber { @@ -429,10 +430,10 @@ func main() { } } else { if e.NumberOfFunctions != expectedNumber { - t.Fatalf("too many exported functions: %v", e.NumberOfFunctions) + t.Fatalf("got %d exported functions; want %d", e.NumberOfFunctions, expectedNumber) } if e.NumberOfNames != expectedNumber { - t.Fatalf("too many exported names: %v", e.NumberOfNames) + t.Fatalf("got %d exported names; want %d", e.NumberOfNames, expectedNumber) } } } diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 1fb1325519d..7bbadd39746 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -9,6 +9,7 @@ import ( "debug/elf" "debug/macho" "debug/pe" + "encoding/binary" "flag" "fmt" "go/format" @@ -2129,6 +2130,38 @@ func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) { if (dc & pe.IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE) == 0 { t.Error("IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag is not set") } + if useCgo { + // Test that only one symbol is exported (#40795). + // PIE binaries don´t require .edata section but unfortunately + // binutils doesn´t generate a .reloc section unless there is + // at least one symbol exported. + // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 + section := f.Section(".edata") + if section == nil { + t.Fatalf(".edata section is not present") + } + // TODO: deduplicate this struct from cmd/link/internal/ld/pe.go + type IMAGE_EXPORT_DIRECTORY struct { + _ [2]uint32 + _ [2]uint16 + _ [2]uint32 + NumberOfFunctions uint32 + NumberOfNames uint32 + _ [3]uint32 + } + var e IMAGE_EXPORT_DIRECTORY + if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil { + t.Fatalf("binary.Read failed: %v", err) + } + + // Only _cgo_dummy_export should be exported + if e.NumberOfFunctions != 1 { + t.Fatalf("got %d exported functions; want 1", e.NumberOfFunctions) + } + if e.NumberOfNames != 1 { + t.Fatalf("got %d exported names; want 1", e.NumberOfNames) + } + } default: panic("unreachable") } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 73e0b35bc04..735b84d37d3 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1320,9 +1320,6 @@ func (ctxt *Link) hostlink() { case objabi.Hdarwin, objabi.Haix: case objabi.Hwindows: argv = addASLRargs(argv) - // Work around binutils limitation that strips relocation table for dynamicbase. - // See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 - argv = append(argv, "-Wl,--export-all-symbols") default: // ELF. if ctxt.UseRelro() { diff --git a/src/runtime/cgo/gcc_windows_386.c b/src/runtime/cgo/gcc_windows_386.c index 9184b91393f..60cb011bf24 100644 --- a/src/runtime/cgo/gcc_windows_386.c +++ b/src/runtime/cgo/gcc_windows_386.c @@ -9,6 +9,7 @@ #include #include #include "libcgo.h" +#include "libcgo_windows.h" static void threadentry(void*); diff --git a/src/runtime/cgo/gcc_windows_amd64.c b/src/runtime/cgo/gcc_windows_amd64.c index 7192a246315..0f8c817f0e4 100644 --- a/src/runtime/cgo/gcc_windows_amd64.c +++ b/src/runtime/cgo/gcc_windows_amd64.c @@ -9,6 +9,7 @@ #include #include #include "libcgo.h" +#include "libcgo_windows.h" static void threadentry(void*); diff --git a/src/runtime/cgo/libcgo_windows.h b/src/runtime/cgo/libcgo_windows.h new file mode 100644 index 00000000000..0013f06baeb --- /dev/null +++ b/src/runtime/cgo/libcgo_windows.h @@ -0,0 +1,12 @@ +// Copyright 2020 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. + +// Ensure there's one symbol marked __declspec(dllexport). +// If there are no exported symbols, the unfortunate behavior of +// the binutils linker is to also strip the relocations table, +// resulting in non-PIE binary. The other option is the +// --export-all-symbols flag, but we don't need to export all symbols +// and this may overflow the export table (#40795). +// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011 +__declspec(dllexport) int _cgo_dummy_export; From fdba080220f0642b2b3926cbc062c775f6224e5d Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 30 Oct 2020 18:36:41 -0400 Subject: [PATCH 316/403] cmd: remove Go115AMD64 Always do aligned jumps now. Change-Id: If68a16fe93c9173c83323a9063465c9bd166eeb8 Reviewed-on: https://go-review.googlesource.com/c/go/+/266857 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/asm/internal/asm/endtoend_test.go | 7 +------ src/cmd/internal/obj/x86/asm6.go | 11 +++-------- src/cmd/internal/objabi/util.go | 9 +-------- src/cmd/link/internal/amd64/l.go | 2 +- src/cmd/link/internal/amd64/obj.go | 7 +------ 5 files changed, 7 insertions(+), 29 deletions(-) diff --git a/src/cmd/asm/internal/asm/endtoend_test.go b/src/cmd/asm/internal/asm/endtoend_test.go index 989b7a54054..7472507caf1 100644 --- a/src/cmd/asm/internal/asm/endtoend_test.go +++ b/src/cmd/asm/internal/asm/endtoend_test.go @@ -390,12 +390,7 @@ func TestARM64Errors(t *testing.T) { } func TestAMD64EndToEnd(t *testing.T) { - defer func(old string) { objabi.GOAMD64 = old }(objabi.GOAMD64) - for _, goamd64 := range []string{"normaljumps", "alignedjumps"} { - t.Logf("GOAMD64=%s", goamd64) - objabi.GOAMD64 = goamd64 - testEndToEnd(t, "amd64", "amd64") - } + testEndToEnd(t, "amd64", "amd64") } func Test386Encoder(t *testing.T) { diff --git a/src/cmd/internal/obj/x86/asm6.go b/src/cmd/internal/obj/x86/asm6.go index 94aed448712..a6b85ac4a06 100644 --- a/src/cmd/internal/obj/x86/asm6.go +++ b/src/cmd/internal/obj/x86/asm6.go @@ -1851,9 +1851,9 @@ func spadjop(ctxt *obj.Link, l, q obj.As) obj.As { return q } -// If the environment variable GOAMD64=alignedjumps the assembler will ensure that -// no standalone or macro-fused jump will straddle or end on a 32 byte boundary -// by inserting NOPs before the jumps +// isJump returns whether p is a jump instruction. +// It is used to ensure that no standalone or macro-fused jump will straddle +// or end on a 32 byte boundary by inserting NOPs before the jumps. func isJump(p *obj.Prog) bool { return p.To.Target() != nil || p.As == obj.AJMP || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO @@ -1987,11 +1987,6 @@ func makePjcCtx(ctxt *obj.Link) padJumpsCtx { return padJumpsCtx(0) } - if objabi.GOAMD64 != "alignedjumps" { - return padJumpsCtx(0) - - } - return padJumpsCtx(32) } diff --git a/src/cmd/internal/objabi/util.go b/src/cmd/internal/objabi/util.go index b81b73a0223..9479ab2cd9f 100644 --- a/src/cmd/internal/objabi/util.go +++ b/src/cmd/internal/objabi/util.go @@ -25,7 +25,6 @@ var ( GOARCH = envOr("GOARCH", defaultGOARCH) GOOS = envOr("GOOS", defaultGOOS) GO386 = envOr("GO386", defaultGO386) - GOAMD64 = goamd64() GOARM = goarm() GOMIPS = gomips() GOMIPS64 = gomips64() @@ -37,15 +36,9 @@ var ( const ( ElfRelocOffset = 256 - MachoRelocOffset = 2048 // reserve enough space for ELF relocations - Go115AMD64 = "alignedjumps" // Should be "alignedjumps" or "normaljumps"; this replaces environment variable introduced in CL 219357. + MachoRelocOffset = 2048 // reserve enough space for ELF relocations ) -// TODO(1.16): assuming no issues in 1.15 release, remove this and related constant. -func goamd64() string { - return Go115AMD64 -} - func goarm() int { switch v := envOr("GOARM", defaultGOARM); v { case "5": diff --git a/src/cmd/link/internal/amd64/l.go b/src/cmd/link/internal/amd64/l.go index a9afb3a39f8..c9ea90a9c81 100644 --- a/src/cmd/link/internal/amd64/l.go +++ b/src/cmd/link/internal/amd64/l.go @@ -33,7 +33,7 @@ package amd64 const ( maxAlign = 32 // max data alignment minAlign = 1 // min data alignment - funcAlign = 16 + funcAlign = 32 ) /* Used by ../internal/ld/dwarf.go */ diff --git a/src/cmd/link/internal/amd64/obj.go b/src/cmd/link/internal/amd64/obj.go index 777f99dbe26..d09c90ea280 100644 --- a/src/cmd/link/internal/amd64/obj.go +++ b/src/cmd/link/internal/amd64/obj.go @@ -39,13 +39,8 @@ import ( func Init() (*sys.Arch, ld.Arch) { arch := sys.ArchAMD64 - fa := funcAlign - if objabi.GOAMD64 == "alignedjumps" { - fa = 32 - } - theArch := ld.Arch{ - Funcalign: fa, + Funcalign: funcAlign, Maxalign: maxAlign, Minalign: minAlign, Dwarfregsp: dwarfRegSP, From 0387bedadf8ec0ec4139af7c1361abaa47a6c03a Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sun, 1 Nov 2020 17:05:32 -0500 Subject: [PATCH 317/403] cmd/compile: remove racefuncenterfp when it is not needed We already remove racefuncenter and racefuncexit if they are not needed (i.e. the function doesn't have any other race calls). racefuncenterfp is like racefuncenter but used on LR machines. Remove unnecessary racefuncenterfp as well. Change-Id: I65edb00e19c6d9ab55a204cbbb93e9fb710559f1 Reviewed-on: https://go-review.googlesource.com/c/go/+/267099 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/rewrite.go | 6 +++--- test/codegen/race.go | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 974c5ac8c30..39aa63d9475 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1573,18 +1573,18 @@ func needRaceCleanup(sym *AuxCall, v *Value) bool { if !f.Config.Race { return false } - if !isSameCall(sym, "runtime.racefuncenter") && !isSameCall(sym, "runtime.racefuncexit") { + if !isSameCall(sym, "runtime.racefuncenter") && !isSameCall(sym, "runtime.racefuncenterfp") && !isSameCall(sym, "runtime.racefuncexit") { return false } for _, b := range f.Blocks { for _, v := range b.Values { switch v.Op { case OpStaticCall: - // Check for racefuncenter will encounter racefuncexit and vice versa. + // Check for racefuncenter/racefuncenterfp will encounter racefuncexit and vice versa. // Allow calls to panic* s := v.Aux.(*AuxCall).Fn.String() switch s { - case "runtime.racefuncenter", "runtime.racefuncexit", + case "runtime.racefuncenter", "runtime.racefuncenterfp", "runtime.racefuncexit", "runtime.panicdivide", "runtime.panicwrap", "runtime.panicshift": continue diff --git a/test/codegen/race.go b/test/codegen/race.go index ed6706f8807..b9778239069 100644 --- a/test/codegen/race.go +++ b/test/codegen/race.go @@ -10,6 +10,8 @@ package codegen // functions with no calls (but which might panic // in various ways). See issue 31219. // amd64:-"CALL.*racefuncenter.*" +// arm64:-"CALL.*racefuncenter.*" +// ppc64le:-"CALL.*racefuncenter.*" func RaceMightPanic(a []int, i, j, k, s int) { var b [4]int _ = b[i] // panicIndex From f2ee58b6bb3d8312dad2ed7826c1a0e67aea8483 Mon Sep 17 00:00:00 2001 From: David Chase Date: Thu, 13 Aug 2020 20:43:39 -0400 Subject: [PATCH 318/403] cmd/compile: using new calls, optimize runtime.memequal(x,constant,1) Proof of concept; also an actual optimization that fires 180 times in the Go source base. Change-Id: I5cb87474be764264cde6e4cbcb471ef109306f08 Reviewed-on: https://go-review.googlesource.com/c/go/+/248404 Trust: David Chase Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- .../compile/internal/ssa/gen/generic.rules | 14 +++- .../compile/internal/ssa/gen/genericOps.go | 5 +- src/cmd/compile/internal/ssa/opGen.go | 6 ++ .../compile/internal/ssa/rewritegeneric.go | 70 +++++++++++++++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/ssa/gen/generic.rules b/src/cmd/compile/internal/ssa/gen/generic.rules index de0ef9349d1..81568b7b7af 100644 --- a/src/cmd/compile/internal/ssa/gen/generic.rules +++ b/src/cmd/compile/internal/ssa/gen/generic.rules @@ -2001,7 +2001,12 @@ && warnRule(fe.Debug_checknil(), v, "removed nil check") => (Invalid) -// for late-expanded calls +// for rewriting results of some late-expanded rewrites (below) +(SelectN [0] (MakeResult a ___)) => a +(SelectN [1] (MakeResult a b ___)) => b +(SelectN [2] (MakeResult a b c ___)) => c + +// for late-expanded calls, recognize newobject and remove zeroing and nilchecks (Zero (SelectN [0] call:(StaticLECall _ _)) mem:(SelectN [1] call)) && isSameCall(call.Aux, "runtime.newobject") => mem @@ -2026,6 +2031,13 @@ && warnRule(fe.Debug_checknil(), v, "removed nil check") => (Invalid) +// for late-expanded calls, recognize memequal applied to a single constant byte +// TODO figure out breakeven number of bytes for this optimization. +(StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [1]) mem) + && isSameCall(callAux, "runtime.memequal") + && symIsRO(scon) + => (MakeResult (Eq8 (Load sptr mem) (Const8 [int8(read8(scon,0))])) mem) + // Evaluate constant address comparisons. (EqPtr x x) => (ConstBool [true]) (NeqPtr x x) => (ConstBool [false]) diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index 23bd4af2cd4..db8d7ba0cf0 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -538,8 +538,9 @@ var genericOps = []opData{ // pseudo-ops for breaking Tuple {name: "Select0", argLength: 1, zeroWidth: true}, // the first component of a tuple {name: "Select1", argLength: 1, zeroWidth: true}, // the second component of a tuple - {name: "SelectN", argLength: 1, aux: "Int64"}, // arg0=tuple, auxint=field index. Returns the auxint'th member. - {name: "SelectNAddr", argLength: 1, aux: "Int64"}, // arg0=tuple, auxint=field index. Returns the address of auxint'th member. Used for un-SSA-able result types. + {name: "SelectN", argLength: 1, aux: "Int64"}, // arg0=result, auxint=field index. Returns the auxint'th member. + {name: "SelectNAddr", argLength: 1, aux: "Int64"}, // arg0=result, auxint=field index. Returns the address of auxint'th member. Used for un-SSA-able result types. + {name: "MakeResult", argLength: -1}, // arg0 .. are components of a "Result" (like the result from a Call). The last arg should be memory (like the result from a call). // Atomic operations used for semantically inlining sync/atomic and // runtime/internal/atomic. Atomic loads return a new memory so that diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 96aa3adedd9..25c1df12eed 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2855,6 +2855,7 @@ const ( OpSelect1 OpSelectN OpSelectNAddr + OpMakeResult OpAtomicLoad8 OpAtomicLoad32 OpAtomicLoad64 @@ -35724,6 +35725,11 @@ var opcodeTable = [...]opInfo{ argLen: 1, generic: true, }, + { + name: "MakeResult", + argLen: -1, + generic: true, + }, { name: "AtomicLoad8", argLen: 2, diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index c9b8f70424f..4cb9a8f3287 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -394,6 +394,8 @@ func rewriteValuegeneric(v *Value) bool { return rewriteValuegeneric_OpSqrt(v) case OpStaticCall: return rewriteValuegeneric_OpStaticCall(v) + case OpStaticLECall: + return rewriteValuegeneric_OpStaticLECall(v) case OpStore: return rewriteValuegeneric_OpStore(v) case OpStringLen: @@ -20767,6 +20769,36 @@ func rewriteValuegeneric_OpSelectN(v *Value) bool { v_0 := v.Args[0] b := v.Block config := b.Func.Config + // match: (SelectN [0] (MakeResult a ___)) + // result: a + for { + if auxIntToInt64(v.AuxInt) != 0 || v_0.Op != OpMakeResult || len(v_0.Args) < 1 { + break + } + a := v_0.Args[0] + v.copyOf(a) + return true + } + // match: (SelectN [1] (MakeResult a b ___)) + // result: b + for { + if auxIntToInt64(v.AuxInt) != 1 || v_0.Op != OpMakeResult || len(v_0.Args) < 2 { + break + } + b := v_0.Args[1] + v.copyOf(b) + return true + } + // match: (SelectN [2] (MakeResult a b c ___)) + // result: c + for { + if auxIntToInt64(v.AuxInt) != 2 || v_0.Op != OpMakeResult || len(v_0.Args) < 3 { + break + } + c := v_0.Args[2] + v.copyOf(c) + return true + } // match: (SelectN [0] call:(StaticLECall {sym} dst src (Const64 [sz]) mem)) // cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call) // result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem) @@ -21367,6 +21399,44 @@ func rewriteValuegeneric_OpStaticCall(v *Value) bool { } return false } +func rewriteValuegeneric_OpStaticLECall(v *Value) bool { + b := v.Block + typ := &b.Func.Config.Types + // match: (StaticLECall {callAux} sptr (Addr {scon} (SB)) (Const64 [1]) mem) + // cond: isSameCall(callAux, "runtime.memequal") && symIsRO(scon) + // result: (MakeResult (Eq8 (Load sptr mem) (Const8 [int8(read8(scon,0))])) mem) + for { + if len(v.Args) != 4 { + break + } + callAux := auxToCall(v.Aux) + mem := v.Args[3] + sptr := v.Args[0] + v_1 := v.Args[1] + if v_1.Op != OpAddr { + break + } + scon := auxToSym(v_1.Aux) + v_1_0 := v_1.Args[0] + if v_1_0.Op != OpSB { + break + } + v_2 := v.Args[2] + if v_2.Op != OpConst64 || auxIntToInt64(v_2.AuxInt) != 1 || !(isSameCall(callAux, "runtime.memequal") && symIsRO(scon)) { + break + } + v.reset(OpMakeResult) + v0 := b.NewValue0(v.Pos, OpEq8, typ.Bool) + v1 := b.NewValue0(v.Pos, OpLoad, typ.Int8) + v1.AddArg2(sptr, mem) + v2 := b.NewValue0(v.Pos, OpConst8, typ.Int8) + v2.AuxInt = int8ToAuxInt(int8(read8(scon, 0))) + v0.AddArg2(v1, v2) + v.AddArg2(v0, mem) + return true + } + return false +} func rewriteValuegeneric_OpStore(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] From 7be8358f70ff858f28b9aefe11986da25f1762bc Mon Sep 17 00:00:00 2001 From: Richard Musiol Date: Thu, 29 Oct 2020 00:07:04 +0100 Subject: [PATCH 319/403] misc/wasm: check type of argument to Go.run This results in a nicer error message if the argument to Go.run is omitted or of the wrong type. Fixes #37000 Change-Id: I7f36d007f41a79b2cea1cebf5cce127786341202 Reviewed-on: https://go-review.googlesource.com/c/go/+/266117 Trust: Richard Musiol Run-TryBot: Richard Musiol TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- misc/wasm/wasm_exec.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/misc/wasm/wasm_exec.js b/misc/wasm/wasm_exec.js index 3ea03c45b7e..82041e6bb90 100644 --- a/misc/wasm/wasm_exec.js +++ b/misc/wasm/wasm_exec.js @@ -503,6 +503,9 @@ } async run(instance) { + if (!(instance instanceof WebAssembly.Instance)) { + throw new Error("Go.run: WebAssembly.Instance expected"); + } this._inst = instance; this.mem = new DataView(this._inst.exports.mem.buffer); this._values = [ // JS values that Go currently has references to, indexed by reference id From d5388e23b5c75bf8189b173051d24a0176a5a303 Mon Sep 17 00:00:00 2001 From: Jonathan Swinney Date: Fri, 30 Oct 2020 18:46:23 +0000 Subject: [PATCH 320/403] runtime: improve memmove performance on arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the memmove implementation for moves of 17 bytes or larger with an implementation from ARM optimized software. The moves of 16 bytes or fewer are unchanged, but the registers used are updated to match the rest of the implementation. This implementation makes use of new optimizations: - software pipelined loop for large (>128 byte) moves - medium size moves (17..128 bytes) have a new implementation - address realignment when src or dst is unaligned - preference for aligned src (loads) or dst (stores) depending on CPU To support preference for aligned loads or aligned stores, a new CPU flag is added. This flag indicates that the detected micro architecture performs better with aligned loads. Some tested CPUs did not exhibit a significant difference and are left with the default behavior of realigning based on the destination address (stores). Neoverse N1 (Tested on Graviton 2) name old time/op new time/op delta Memmove/0-4 1.88ns ± 1% 1.87ns ± 1% -0.58% (p=0.020 n=10+10) Memmove/1-4 4.40ns ± 0% 4.40ns ± 0% ~ (all equal) Memmove/8-4 3.88ns ± 3% 3.80ns ± 0% -1.97% (p=0.001 n=10+9) Memmove/16-4 3.90ns ± 3% 3.80ns ± 0% -2.49% (p=0.000 n=10+9) Memmove/32-4 4.80ns ± 0% 4.40ns ± 0% -8.33% (p=0.000 n=9+8) Memmove/64-4 5.86ns ± 0% 5.00ns ± 0% -14.76% (p=0.000 n=8+8) Memmove/128-4 8.46ns ± 0% 8.06ns ± 0% -4.62% (p=0.000 n=10+10) Memmove/256-4 12.4ns ± 0% 12.2ns ± 0% -1.61% (p=0.000 n=10+10) Memmove/512-4 19.5ns ± 0% 19.1ns ± 0% -2.05% (p=0.000 n=10+10) Memmove/1024-4 33.7ns ± 0% 33.5ns ± 0% -0.59% (p=0.000 n=10+10) Memmove/2048-4 62.1ns ± 0% 59.0ns ± 0% -4.99% (p=0.000 n=10+10) Memmove/4096-4 117ns ± 1% 110ns ± 0% -5.66% (p=0.000 n=10+10) MemmoveUnalignedDst/64-4 6.41ns ± 0% 5.62ns ± 0% -12.32% (p=0.000 n=10+7) MemmoveUnalignedDst/128-4 9.40ns ± 0% 8.34ns ± 0% -11.24% (p=0.000 n=10+10) MemmoveUnalignedDst/256-4 12.8ns ± 0% 12.8ns ± 0% ~ (all equal) MemmoveUnalignedDst/512-4 20.4ns ± 0% 19.7ns ± 0% -3.43% (p=0.000 n=9+10) MemmoveUnalignedDst/1024-4 34.1ns ± 0% 35.1ns ± 0% +2.93% (p=0.000 n=9+9) MemmoveUnalignedDst/2048-4 61.5ns ± 0% 60.4ns ± 0% -1.77% (p=0.000 n=10+10) MemmoveUnalignedDst/4096-4 122ns ± 0% 113ns ± 0% -7.38% (p=0.002 n=8+10) MemmoveUnalignedSrc/64-4 7.25ns ± 1% 6.26ns ± 0% -13.64% (p=0.000 n=9+9) MemmoveUnalignedSrc/128-4 10.5ns ± 0% 9.7ns ± 0% -7.52% (p=0.000 n=10+10) MemmoveUnalignedSrc/256-4 17.1ns ± 0% 17.3ns ± 0% +1.17% (p=0.000 n=10+10) MemmoveUnalignedSrc/512-4 27.0ns ± 0% 27.0ns ± 0% ~ (all equal) MemmoveUnalignedSrc/1024-4 46.7ns ± 0% 35.7ns ± 0% -23.55% (p=0.000 n=10+9) MemmoveUnalignedSrc/2048-4 85.2ns ± 0% 61.2ns ± 0% -28.17% (p=0.000 n=10+8) MemmoveUnalignedSrc/4096-4 162ns ± 0% 113ns ± 0% -30.25% (p=0.000 n=10+10) name old speed new speed delta Memmove/4096-4 35.2GB/s ± 0% 37.1GB/s ± 0% +5.56% (p=0.000 n=10+9) MemmoveUnalignedSrc/1024-4 21.9GB/s ± 0% 28.7GB/s ± 0% +30.90% (p=0.000 n=10+10) MemmoveUnalignedSrc/2048-4 24.0GB/s ± 0% 33.5GB/s ± 0% +39.18% (p=0.000 n=10+9) MemmoveUnalignedSrc/4096-4 25.3GB/s ± 0% 36.2GB/s ± 0% +43.50% (p=0.000 n=10+7) Cortex-A72 (Graviton 1) name old time/op new time/op delta Memmove/0-4 3.06ns ± 3% 3.08ns ± 1% ~ (p=0.958 n=10+9) Memmove/1-4 8.72ns ± 0% 7.85ns ± 0% -9.98% (p=0.002 n=8+10) Memmove/8-4 8.29ns ± 0% 8.29ns ± 0% ~ (all equal) Memmove/16-4 8.29ns ± 0% 8.29ns ± 0% ~ (all equal) Memmove/32-4 8.19ns ± 2% 8.29ns ± 0% ~ (p=0.114 n=10+10) Memmove/64-4 18.3ns ± 4% 10.0ns ± 0% -45.36% (p=0.000 n=10+10) Memmove/128-4 14.8ns ± 0% 17.4ns ± 0% +17.77% (p=0.000 n=10+10) Memmove/256-4 21.8ns ± 0% 23.1ns ± 0% +5.96% (p=0.000 n=10+10) Memmove/512-4 35.8ns ± 0% 37.2ns ± 0% +3.91% (p=0.000 n=10+10) Memmove/1024-4 63.7ns ± 0% 67.2ns ± 0% +5.49% (p=0.000 n=10+10) Memmove/2048-4 126ns ± 0% 123ns ± 0% -2.38% (p=0.000 n=10+10) Memmove/4096-4 238ns ± 1% 243ns ± 1% +1.93% (p=0.000 n=10+10) MemmoveUnalignedDst/64-4 19.3ns ± 1% 12.0ns ± 1% -37.49% (p=0.000 n=10+10) MemmoveUnalignedDst/128-4 17.2ns ± 0% 17.4ns ± 0% +1.16% (p=0.000 n=10+10) MemmoveUnalignedDst/256-4 28.2ns ± 8% 29.2ns ± 0% ~ (p=0.352 n=10+10) MemmoveUnalignedDst/512-4 49.8ns ± 3% 48.9ns ± 0% ~ (p=1.000 n=10+10) MemmoveUnalignedDst/1024-4 89.5ns ± 0% 80.5ns ± 1% -10.02% (p=0.000 n=10+10) MemmoveUnalignedDst/2048-4 180ns ± 0% 127ns ± 0% -29.44% (p=0.000 n=9+10) MemmoveUnalignedDst/4096-4 347ns ± 0% 244ns ± 0% -29.59% (p=0.000 n=10+9) MemmoveUnalignedSrc/128-4 16.1ns ± 0% 21.8ns ± 0% +35.40% (p=0.000 n=10+10) MemmoveUnalignedSrc/256-4 24.9ns ± 8% 26.6ns ± 0% +6.70% (p=0.015 n=10+10) MemmoveUnalignedSrc/512-4 39.4ns ± 6% 40.6ns ± 0% ~ (p=0.352 n=10+10) MemmoveUnalignedSrc/1024-4 72.5ns ± 0% 83.0ns ± 1% +14.44% (p=0.000 n=9+10) MemmoveUnalignedSrc/2048-4 129ns ± 1% 128ns ± 1% ~ (p=0.179 n=10+10) MemmoveUnalignedSrc/4096-4 241ns ± 0% 253ns ± 1% +4.99% (p=0.000 n=9+9) Cortex-A53 (Raspberry Pi 3) name old time/op new time/op delta Memmove/0-4 11.0ns ± 0% 11.0ns ± 1% ~ (p=0.294 n=8+10) Memmove/1-4 29.6ns ± 0% 28.0ns ± 1% -5.41% (p=0.000 n=9+10) Memmove/8-4 23.5ns ± 0% 22.1ns ± 0% -6.11% (p=0.000 n=8+8) Memmove/16-4 23.7ns ± 1% 22.1ns ± 0% -6.59% (p=0.000 n=10+8) Memmove/32-4 27.9ns ± 0% 27.1ns ± 0% -3.13% (p=0.000 n=8+8) Memmove/64-4 33.8ns ± 0% 31.5ns ± 1% -6.99% (p=0.000 n=8+10) Memmove/128-4 45.6ns ± 0% 44.2ns ± 1% -3.23% (p=0.000 n=9+10) Memmove/256-4 69.3ns ± 0% 69.3ns ± 0% ~ (p=0.072 n=8+8) Memmove/512-4 127ns ± 0% 110ns ± 0% -13.39% (p=0.000 n=8+8) Memmove/1024-4 222ns ± 0% 205ns ± 1% -7.66% (p=0.000 n=7+10) Memmove/2048-4 411ns ± 0% 366ns ± 0% -10.98% (p=0.000 n=8+9) Memmove/4096-4 795ns ± 1% 695ns ± 1% -12.63% (p=0.000 n=10+10) MemmoveUnalignedDst/64-4 44.0ns ± 0% 40.5ns ± 0% -7.93% (p=0.000 n=8+8) MemmoveUnalignedDst/128-4 59.6ns ± 0% 54.9ns ± 0% -7.85% (p=0.000 n=9+9) MemmoveUnalignedDst/256-4 98.2ns ±11% 90.0ns ± 1% ~ (p=0.130 n=10+10) MemmoveUnalignedDst/512-4 161ns ± 2% 145ns ± 1% -9.96% (p=0.000 n=10+10) MemmoveUnalignedDst/1024-4 281ns ± 0% 265ns ± 0% -5.65% (p=0.000 n=9+8) MemmoveUnalignedDst/2048-4 528ns ± 0% 482ns ± 0% -8.73% (p=0.000 n=8+9) MemmoveUnalignedDst/4096-4 1.02µs ± 1% 0.92µs ± 0% -10.00% (p=0.000 n=10+8) MemmoveUnalignedSrc/64-4 42.4ns ± 1% 40.5ns ± 0% -4.39% (p=0.000 n=10+8) MemmoveUnalignedSrc/128-4 57.4ns ± 0% 57.0ns ± 1% -0.75% (p=0.048 n=9+10) MemmoveUnalignedSrc/256-4 88.1ns ± 1% 89.6ns ± 0% +1.70% (p=0.000 n=9+8) MemmoveUnalignedSrc/512-4 160ns ± 2% 144ns ± 0% -9.89% (p=0.000 n=10+8) MemmoveUnalignedSrc/1024-4 286ns ± 0% 266ns ± 1% -6.69% (p=0.000 n=8+10) MemmoveUnalignedSrc/2048-4 525ns ± 0% 483ns ± 1% -7.96% (p=0.000 n=9+10) MemmoveUnalignedSrc/4096-4 1.01µs ± 0% 0.92µs ± 1% -9.40% (p=0.000 n=8+10) Change-Id: Ia1144e9d4dfafdece6e167c5e576bf80f254c8ab Reviewed-on: https://go-review.googlesource.com/c/go/+/243357 TryBot-Result: Go Bot Reviewed-by: Martin Möhrmann Reviewed-by: eric fang Reviewed-by: Cherry Zhang --- src/internal/cpu/cpu.go | 54 +++--- src/internal/cpu/cpu_arm64.go | 25 +++ src/internal/cpu/cpu_arm64.s | 6 + src/runtime/cpuflags_arm64.go | 17 ++ src/runtime/memmove_arm64.s | 332 +++++++++++++++++++++------------- src/runtime/memmove_test.go | 30 +++ 6 files changed, 314 insertions(+), 150 deletions(-) create mode 100644 src/runtime/cpuflags_arm64.go diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index 2829945af0b..0ceedcd7d22 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -56,32 +56,34 @@ var ARM struct { // The booleans in ARM64 contain the correspondingly named cpu feature bit. // The struct is padded to avoid false sharing. var ARM64 struct { - _ CacheLinePad - HasFP bool - HasASIMD bool - HasEVTSTRM bool - HasAES bool - HasPMULL bool - HasSHA1 bool - HasSHA2 bool - HasCRC32 bool - HasATOMICS bool - HasFPHP bool - HasASIMDHP bool - HasCPUID bool - HasASIMDRDM bool - HasJSCVT bool - HasFCMA bool - HasLRCPC bool - HasDCPOP bool - HasSHA3 bool - HasSM3 bool - HasSM4 bool - HasASIMDDP bool - HasSHA512 bool - HasSVE bool - HasASIMDFHM bool - _ CacheLinePad + _ CacheLinePad + HasFP bool + HasASIMD bool + HasEVTSTRM bool + HasAES bool + HasPMULL bool + HasSHA1 bool + HasSHA2 bool + HasCRC32 bool + HasATOMICS bool + HasFPHP bool + HasASIMDHP bool + HasCPUID bool + HasASIMDRDM bool + HasJSCVT bool + HasFCMA bool + HasLRCPC bool + HasDCPOP bool + HasSHA3 bool + HasSM3 bool + HasSM4 bool + HasASIMDDP bool + HasSHA512 bool + HasSVE bool + HasASIMDFHM bool + IsNeoverseN1 bool + IsZeus bool + _ CacheLinePad } var MIPS64X struct { diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index 533bea24700..8fde39f03e1 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -18,6 +18,7 @@ const ( hwcap_SHA2 = 1 << 6 hwcap_CRC32 = 1 << 7 hwcap_ATOMICS = 1 << 8 + hwcap_CPUID = 1 << 11 ) func doinit() { @@ -28,6 +29,8 @@ func doinit() { {Name: "sha2", Feature: &ARM64.HasSHA2}, {Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "atomics", Feature: &ARM64.HasATOMICS}, + {Name: "isNeoverseN1", Feature: &ARM64.IsNeoverseN1}, + {Name: "isZeus", Feature: &ARM64.IsZeus}, } switch GOOS { @@ -40,12 +43,32 @@ func doinit() { ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) + ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID) // The Samsung S9+ kernel reports support for atomics, but not all cores // actually support them, resulting in SIGILL. See issue #28431. // TODO(elias.naur): Only disable the optimization on bad chipsets on android. ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && GOOS != "android" + // Check to see if executing on a NeoverseN1 and in order to do that, + // check the AUXV for the CPUID bit. The getMIDR function executes an + // instruction which would normally be an illegal instruction, but it's + // trapped by the kernel, the value sanitized and then returned. Without + // the CPUID bit the kernel will not trap the instruction and the process + // will be terminated with SIGILL. + if ARM64.HasCPUID { + midr := getMIDR() + part_num := uint16((midr >> 4) & 0xfff) + implementor := byte((midr >> 24) & 0xff) + + if implementor == 'A' && part_num == 0xd0c { + ARM64.IsNeoverseN1 = true + } + if implementor == 'A' && part_num == 0xd40 { + ARM64.IsZeus = true + } + } + case "freebsd": // Retrieve info from system register ID_AA64ISAR0_EL1. isar0 := getisar0() @@ -93,3 +116,5 @@ func isSet(hwc uint, value uint) bool { } func getisar0() uint64 + +func getMIDR() uint64 diff --git a/src/internal/cpu/cpu_arm64.s b/src/internal/cpu/cpu_arm64.s index d85914973f9..d6e7f443739 100644 --- a/src/internal/cpu/cpu_arm64.s +++ b/src/internal/cpu/cpu_arm64.s @@ -10,3 +10,9 @@ TEXT ·getisar0(SB),NOSPLIT,$0 MRS ID_AA64ISAR0_EL1, R0 MOVD R0, ret+0(FP) RET + +// func getMIDR() uint64 +TEXT ·getMIDR(SB), NOSPLIT, $0-8 + MRS MIDR_EL1, R0 + MOVD R0, ret+0(FP) + RET diff --git a/src/runtime/cpuflags_arm64.go b/src/runtime/cpuflags_arm64.go new file mode 100644 index 00000000000..7576bef4a75 --- /dev/null +++ b/src/runtime/cpuflags_arm64.go @@ -0,0 +1,17 @@ +// Copyright 2020 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 runtime + +import ( + "internal/cpu" +) + +var arm64UseAlignedLoads bool + +func init() { + if cpu.ARM64.IsNeoverseN1 || cpu.ARM64.IsZeus { + arm64UseAlignedLoads = true + } +} diff --git a/src/runtime/memmove_arm64.s b/src/runtime/memmove_arm64.s index dbb7e9a28a0..43d27629e5b 100644 --- a/src/runtime/memmove_arm64.s +++ b/src/runtime/memmove_arm64.s @@ -6,152 +6,236 @@ // See memmove Go doc for important implementation constraints. +// Register map +// +// dstin R0 +// src R1 +// count R2 +// dst R3 (same as R0, but gets modified in unaligned cases) +// srcend R4 +// dstend R5 +// data R6-R17 +// tmp1 R14 + +// Copies are split into 3 main cases: small copies of up to 32 bytes, medium +// copies of up to 128 bytes, and large copies. The overhead of the overlap +// check is negligible since it is only required for large copies. +// +// Large copies use a software pipelined loop processing 64 bytes per iteration. +// The destination pointer is 16-byte aligned to minimize unaligned accesses. +// The loop tail is handled by always copying 64 bytes from the end. + // func memmove(to, from unsafe.Pointer, n uintptr) TEXT runtime·memmove(SB), NOSPLIT|NOFRAME, $0-24 - MOVD to+0(FP), R3 - MOVD from+8(FP), R4 - MOVD n+16(FP), R5 - CBNZ R5, check - RET + MOVD to+0(FP), R0 + MOVD from+8(FP), R1 + MOVD n+16(FP), R2 + CBZ R2, copy0 -check: - CMP $16, R5 + // Small copies: 1..16 bytes + CMP $16, R2 BLE copy16 - AND $~31, R5, R7 // R7 is N&~31 - SUB R7, R5, R6 // R6 is N&31 + // Large copies + CMP $128, R2 + BHI copy_long + CMP $32, R2 + BHI copy32_128 - CMP R3, R4 - BLT backward - - // Copying forward proceeds by copying R7/32 quadwords then R6 <= 31 tail bytes. - // R3 and R4 are advanced as we copy. - - // (There may be implementations of armv8 where copying by bytes until - // at least one of source or dest is word aligned is a worthwhile - // optimization, but the on the one tested so far (xgene) it did not - // make a significance difference.) - - CBZ R7, noforwardlarge // Do we need to do any quadword copying? - - ADD R3, R7, R9 // R9 points just past where we copy by word - -forwardlargeloop: - // Copy 32 bytes at a time. - LDP.P 32(R4), (R8, R10) - STP.P (R8, R10), 32(R3) - LDP -16(R4), (R11, R12) - STP (R11, R12), -16(R3) - SUB $32, R7, R7 - CBNZ R7, forwardlargeloop - -noforwardlarge: - CBNZ R6, forwardtail // Do we need to copy any tail bytes? + // Small copies: 17..32 bytes. + LDP (R1), (R6, R7) + ADD R1, R2, R4 // R4 points just past the last source byte + LDP -16(R4), (R12, R13) + STP (R6, R7), (R0) + ADD R0, R2, R5 // R5 points just past the last destination byte + STP (R12, R13), -16(R5) RET -forwardtail: - // There are R6 <= 31 bytes remaining to copy. - // This is large enough to still contain pointers, - // which must be copied atomically. - // Copy the next 16 bytes, then 8 bytes, then any remaining bytes. - TBZ $4, R6, 3(PC) // write 16 bytes if R6&16 != 0 - LDP.P 16(R4), (R8, R10) - STP.P (R8, R10), 16(R3) - - TBZ $3, R6, 3(PC) // write 8 bytes if R6&8 != 0 - MOVD.P 8(R4), R8 - MOVD.P R8, 8(R3) - - AND $7, R6 - CBNZ R6, 2(PC) - RET - - ADD R3, R6, R9 // R9 points just past the destination memory - -forwardtailloop: - MOVBU.P 1(R4), R8 - MOVBU.P R8, 1(R3) - CMP R3, R9 - BNE forwardtailloop - RET - - // Small copies: 1..16 bytes. +// Small copies: 1..16 bytes. copy16: - ADD R4, R5, R8 // R8 points just past the last source byte - ADD R3, R5, R9 // R9 points just past the last destination byte - CMP $8, R5 + ADD R1, R2, R4 // R4 points just past the last source byte + ADD R0, R2, R5 // R5 points just past the last destination byte + CMP $8, R2 BLT copy7 - MOVD (R4), R6 - MOVD -8(R8), R7 - MOVD R6, (R3) - MOVD R7, -8(R9) + MOVD (R1), R6 + MOVD -8(R4), R7 + MOVD R6, (R0) + MOVD R7, -8(R5) RET copy7: - TBZ $2, R5, copy3 - MOVWU (R4), R6 - MOVWU -4(R8), R7 - MOVW R6, (R3) - MOVW R7, -4(R9) + TBZ $2, R2, copy3 + MOVWU (R1), R6 + MOVWU -4(R4), R7 + MOVW R6, (R0) + MOVW R7, -4(R5) RET copy3: - TBZ $1, R5, copy1 - MOVHU (R4), R6 - MOVHU -2(R8), R7 - MOVH R6, (R3) - MOVH R7, -2(R9) + TBZ $1, R2, copy1 + MOVHU (R1), R6 + MOVHU -2(R4), R7 + MOVH R6, (R0) + MOVH R7, -2(R5) RET copy1: - MOVBU (R4), R6 - MOVB R6, (R3) + MOVBU (R1), R6 + MOVB R6, (R0) + +copy0: RET -backward: - // Copying backwards first copies R6 <= 31 tail bytes, then R7/32 quadwords. - // R3 and R4 are advanced to the end of the destination/source buffers - // respectively and moved back as we copy. - - ADD R4, R5, R4 // R4 points just past the last source byte - ADD R3, R5, R3 // R3 points just past the last destination byte - - CBZ R6, nobackwardtail // Do we need to do any byte-by-byte copying? - - AND $7, R6, R12 - CBZ R12, backwardtaillarge - - SUB R12, R3, R9 // R9 points at the lowest destination byte that should be copied by byte. -backwardtailloop: - // Copy sub-pointer-size tail. - MOVBU.W -1(R4), R8 - MOVBU.W R8, -1(R3) - CMP R9, R3 - BNE backwardtailloop - -backwardtaillarge: - // Do 8/16-byte write if possible. - // See comment at forwardtail. - TBZ $3, R6, 3(PC) - MOVD.W -8(R4), R8 - MOVD.W R8, -8(R3) - - TBZ $4, R6, 3(PC) - LDP.W -16(R4), (R8, R10) - STP.W (R8, R10), -16(R3) - -nobackwardtail: - CBNZ R7, backwardlarge // Do we need to do any doubleword-by-doubleword copying? + // Medium copies: 33..128 bytes. +copy32_128: + ADD R1, R2, R4 // R4 points just past the last source byte + ADD R0, R2, R5 // R5 points just past the last destination byte + LDP (R1), (R6, R7) + LDP 16(R1), (R8, R9) + LDP -32(R4), (R10, R11) + LDP -16(R4), (R12, R13) + CMP $64, R2 + BHI copy128 + STP (R6, R7), (R0) + STP (R8, R9), 16(R0) + STP (R10, R11), -32(R5) + STP (R12, R13), -16(R5) RET -backwardlarge: - SUB R7, R3, R9 // R9 points at the lowest destination byte + // Copy 65..128 bytes. +copy128: + LDP 32(R1), (R14, R15) + LDP 48(R1), (R16, R17) + CMP $96, R2 + BLS copy96 + LDP -64(R4), (R2, R3) + LDP -48(R4), (R1, R4) + STP (R2, R3), -64(R5) + STP (R1, R4), -48(R5) -backwardlargeloop: - LDP -16(R4), (R8, R10) - STP (R8, R10), -16(R3) - LDP.W -32(R4), (R11, R12) - STP.W (R11, R12), -32(R3) - CMP R9, R3 - BNE backwardlargeloop +copy96: + STP (R6, R7), (R0) + STP (R8, R9), 16(R0) + STP (R14, R15), 32(R0) + STP (R16, R17), 48(R0) + STP (R10, R11), -32(R5) + STP (R12, R13), -16(R5) + RET + + // Copy more than 128 bytes. +copy_long: + ADD R1, R2, R4 // R4 points just past the last source byte + ADD R0, R2, R5 // R5 points just past the last destination byte + MOVD ZR, R7 + MOVD ZR, R8 + + CMP $1024, R2 + BLT backward_check + // feature detect to decide how to align + MOVBU runtime·arm64UseAlignedLoads(SB), R6 + CBNZ R6, use_aligned_loads + MOVD R0, R7 + MOVD R5, R8 + B backward_check +use_aligned_loads: + MOVD R1, R7 + MOVD R4, R8 + // R7 and R8 are used here for the realignment calculation. In + // the use_aligned_loads case, R7 is the src pointer and R8 is + // srcend pointer, which is used in the backward copy case. + // When doing aligned stores, R7 is the dst pointer and R8 is + // the dstend pointer. + +backward_check: + // Use backward copy if there is an overlap. + SUB R1, R0, R14 + CBZ R14, copy0 + CMP R2, R14 + BCC copy_long_backward + + // Copy 16 bytes and then align src (R1) or dst (R0) to 16-byte alignment. + LDP (R1), (R12, R13) // Load A + AND $15, R7, R14 // Calculate the realignment offset + SUB R14, R1, R1 + SUB R14, R0, R3 // move dst back same amount as src + ADD R14, R2, R2 + LDP 16(R1), (R6, R7) // Load B + STP (R12, R13), (R0) // Store A + LDP 32(R1), (R8, R9) // Load C + LDP 48(R1), (R10, R11) // Load D + LDP.W 64(R1), (R12, R13) // Load E + // 80 bytes have been loaded; if less than 80+64 bytes remain, copy from the end + SUBS $144, R2, R2 + BLS copy64_from_end + +loop64: + STP (R6, R7), 16(R3) // Store B + LDP 16(R1), (R6, R7) // Load B (next iteration) + STP (R8, R9), 32(R3) // Store C + LDP 32(R1), (R8, R9) // Load C + STP (R10, R11), 48(R3) // Store D + LDP 48(R1), (R10, R11) // Load D + STP.W (R12, R13), 64(R3) // Store E + LDP.W 64(R1), (R12, R13) // Load E + SUBS $64, R2, R2 + BHI loop64 + + // Write the last iteration and copy 64 bytes from the end. +copy64_from_end: + LDP -64(R4), (R14, R15) // Load F + STP (R6, R7), 16(R3) // Store B + LDP -48(R4), (R6, R7) // Load G + STP (R8, R9), 32(R3) // Store C + LDP -32(R4), (R8, R9) // Load H + STP (R10, R11), 48(R3) // Store D + LDP -16(R4), (R10, R11) // Load I + STP (R12, R13), 64(R3) // Store E + STP (R14, R15), -64(R5) // Store F + STP (R6, R7), -48(R5) // Store G + STP (R8, R9), -32(R5) // Store H + STP (R10, R11), -16(R5) // Store I + RET + + // Large backward copy for overlapping copies. + // Copy 16 bytes and then align srcend (R4) or dstend (R5) to 16-byte alignment. +copy_long_backward: + LDP -16(R4), (R12, R13) + AND $15, R8, R14 + SUB R14, R4, R4 + SUB R14, R2, R2 + LDP -16(R4), (R6, R7) + STP (R12, R13), -16(R5) + LDP -32(R4), (R8, R9) + LDP -48(R4), (R10, R11) + LDP.W -64(R4), (R12, R13) + SUB R14, R5, R5 + SUBS $128, R2, R2 + BLS copy64_from_start + +loop64_backward: + STP (R6, R7), -16(R5) + LDP -16(R4), (R6, R7) + STP (R8, R9), -32(R5) + LDP -32(R4), (R8, R9) + STP (R10, R11), -48(R5) + LDP -48(R4), (R10, R11) + STP.W (R12, R13), -64(R5) + LDP.W -64(R4), (R12, R13) + SUBS $64, R2, R2 + BHI loop64_backward + + // Write the last iteration and copy 64 bytes from the start. +copy64_from_start: + LDP 48(R1), (R2, R3) + STP (R6, R7), -16(R5) + LDP 32(R1), (R6, R7) + STP (R8, R9), -32(R5) + LDP 16(R1), (R8, R9) + STP (R10, R11), -48(R5) + LDP (R1), (R10, R11) + STP (R12, R13), -64(R5) + STP (R2, R3), 48(R0) + STP (R6, R7), 32(R0) + STP (R8, R9), 16(R0) + STP (R10, R11), (R0) RET diff --git a/src/runtime/memmove_test.go b/src/runtime/memmove_test.go index b549433f71c..7c9d2ada45f 100644 --- a/src/runtime/memmove_test.go +++ b/src/runtime/memmove_test.go @@ -286,6 +286,9 @@ var bufSizes = []int{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, } +var bufSizesOverlap = []int{ + 32, 64, 128, 256, 512, 1024, 2048, 4096, +} func BenchmarkMemmove(b *testing.B) { benchmarkSizes(b, bufSizes, func(b *testing.B, n int) { @@ -297,6 +300,15 @@ func BenchmarkMemmove(b *testing.B) { }) } +func BenchmarkMemmoveOverlap(b *testing.B) { + benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) { + x := make([]byte, n+16) + for i := 0; i < b.N; i++ { + copy(x[16:n+16], x[:n]) + } + }) +} + func BenchmarkMemmoveUnalignedDst(b *testing.B) { benchmarkSizes(b, bufSizes, func(b *testing.B, n int) { x := make([]byte, n+1) @@ -307,6 +319,15 @@ func BenchmarkMemmoveUnalignedDst(b *testing.B) { }) } +func BenchmarkMemmoveUnalignedDstOverlap(b *testing.B) { + benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) { + x := make([]byte, n+16) + for i := 0; i < b.N; i++ { + copy(x[16:n+16], x[1:n+1]) + } + }) +} + func BenchmarkMemmoveUnalignedSrc(b *testing.B) { benchmarkSizes(b, bufSizes, func(b *testing.B, n int) { x := make([]byte, n) @@ -317,6 +338,15 @@ func BenchmarkMemmoveUnalignedSrc(b *testing.B) { }) } +func BenchmarkMemmoveUnalignedSrcOverlap(b *testing.B) { + benchmarkSizes(b, bufSizesOverlap, func(b *testing.B, n int) { + x := make([]byte, n+1) + for i := 0; i < b.N; i++ { + copy(x[1:n+1], x[:n]) + } + }) +} + func TestMemclr(t *testing.T) { size := 512 if testing.Short() { From cb65c8d58ac76abdaa6d14cc0742ca23d00ff524 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 12 Oct 2020 10:51:34 -0400 Subject: [PATCH 321/403] syscall: switch go:generate directives back to mksyscall_windows.go Adjust mksyscall_windows.go to activate module mode and set -mod=readonly, and to suppress its own deprecation warning when run from within GOROOT/src. We can't vendor the mkwinsyscall tool in to the std module directly, because std-vendored dependencies (unlike the dependencies of all other modules) turn into actual, distinct packages in 'std' when viewed from outside the 'std' module. We don't want to introduce a binary in the 'std' meta-pattern, but we also don't particularly want to add more special-cases to the 'go' command right now when we have an existing wrapper program that can do the job. I also regenerated the affected packages to ensure that they are consistent with the current version of mksyscall, which produced some declaration-order changes in internal/syscall/windows/zsyscall_windows.go. Fixes #41916 Updates #25922 Change-Id: If6e6f8ba3dd372a7ecd6820ee6c0ca38d55f0f35 Reviewed-on: https://go-review.googlesource.com/c/go/+/261499 Trust: Bryan C. Mills Trust: Alex Brainman Reviewed-by: Dmitri Shuralyov Reviewed-by: Alex Brainman --- src/internal/syscall/windows/mksyscall.go | 2 +- .../syscall/windows/registry/mksyscall.go | 2 +- .../syscall/windows/zsyscall_windows.go | 28 ++++++------- src/syscall/mksyscall_windows.go | 40 +++++++++++++++++-- src/syscall/syscall.go | 2 +- 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/internal/syscall/windows/mksyscall.go b/src/internal/syscall/windows/mksyscall.go index 95e36f7aa3c..599f07601bd 100644 --- a/src/internal/syscall/windows/mksyscall.go +++ b/src/internal/syscall/windows/mksyscall.go @@ -6,4 +6,4 @@ package windows -//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go symlink_windows.go +//go:generate go run ../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go security_windows.go psapi_windows.go symlink_windows.go diff --git a/src/internal/syscall/windows/registry/mksyscall.go b/src/internal/syscall/windows/registry/mksyscall.go index cb4906a7b26..320abf7fc69 100644 --- a/src/internal/syscall/windows/registry/mksyscall.go +++ b/src/internal/syscall/windows/registry/mksyscall.go @@ -6,4 +6,4 @@ package registry -//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall.go +//go:generate go run ../../../../syscall/mksyscall_windows.go -output zsyscall_windows.go syscall.go diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go index 0840dc283ae..1eb8c2dfd21 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -40,14 +40,15 @@ var ( modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll")) modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) - modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll")) + modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll")) procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") procMoveFileExW = modkernel32.NewProc("MoveFileExW") procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") + procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") procWSASocketW = modws2_32.NewProc("WSASocketW") procLockFileEx = modkernel32.NewProc("LockFileEx") procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") @@ -71,7 +72,6 @@ var ( procNetUserGetLocalGroups = modnetapi32.NewProc("NetUserGetLocalGroups") procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") - procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") ) func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { @@ -82,18 +82,6 @@ func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapter return } -func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) if r1 == 0 { @@ -131,6 +119,18 @@ func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, return } +func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) { r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protinfo)), uintptr(group), uintptr(flags)) handle = syscall.Handle(r0) diff --git a/src/syscall/mksyscall_windows.go b/src/syscall/mksyscall_windows.go index d66bf7865ff..240254b2c76 100644 --- a/src/syscall/mksyscall_windows.go +++ b/src/syscall/mksyscall_windows.go @@ -4,9 +4,11 @@ // +build ignore +// mksyscall_windows wraps golang.org/x/sys/windows/mkwinsyscall. package main import ( + "bytes" "os" "os/exec" "path/filepath" @@ -14,11 +16,43 @@ import ( ) func main() { - os.Stderr.WriteString("WARNING: Please switch from using:\n go run $GOROOT/src/syscall/mksyscall_windows.go\nto using:\n go run golang.org/x/sys/windows/mkwinsyscall\n") - args := append([]string{"run", "golang.org/x/sys/windows/mkwinsyscall"}, os.Args[1:]...) - cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...) + goTool := filepath.Join(runtime.GOROOT(), "bin", "go") + + listCmd := exec.Command(goTool, "list", "-m") + listCmd.Env = append(os.Environ(), "GO111MODULE=on") + + var ( + cmdEnv []string + modArgs []string + ) + if out, err := listCmd.Output(); err == nil && string(bytes.TrimSpace(out)) == "std" { + // Force module mode to use mkwinsyscall at the same version as the x/sys + // module vendored into the standard library. + cmdEnv = append(os.Environ(), "GO111MODULE=on") + + // Force -mod=readonly instead of the default -mod=vendor. + // + // mkwinsyscall is not itself vendored into the standard library, and it is + // not feasible to do so at the moment: std-vendored libraries are included + // in the "std" meta-pattern (because in general they *are* linked into + // users binaries separately from the original import paths), and we can't + // allow a binary in the "std" meta-pattern. + modArgs = []string{"-mod=readonly"} + } else { + // Nobody outside the standard library should be using this wrapper: other + // modules can vendor in the mkwinsyscall tool directly (as described in + // https://golang.org/issue/25922), so they don't need this wrapper to + // set module mode and -mod=readonly explicitly. + os.Stderr.WriteString("WARNING: Please switch from using:\n go run $GOROOT/src/syscall/mksyscall_windows.go\nto using:\n go run golang.org/x/sys/windows/mkwinsyscall\n") + } + + args := append([]string{"run"}, modArgs...) + args = append(args, "golang.org/x/sys/windows/mkwinsyscall") + args = append(args, os.Args[1:]...) + cmd := exec.Command(goTool, args...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr + cmd.Env = cmdEnv err := cmd.Run() if err != nil { os.Exit(1) diff --git a/src/syscall/syscall.go b/src/syscall/syscall.go index 980ef9d27fa..2e7a3ae5f26 100644 --- a/src/syscall/syscall.go +++ b/src/syscall/syscall.go @@ -26,7 +26,7 @@ // package syscall -//go:generate go run golang.org/x/sys/windows/mkwinsyscall -systemdll -output zsyscall_windows.go syscall_windows.go security_windows.go +//go:generate go run ./mksyscall_windows.go -systemdll -output zsyscall_windows.go syscall_windows.go security_windows.go // StringByteSlice converts a string to a NUL-terminated []byte, // If s contains a NUL byte this function panics instead of From 202aa085abfc2aa7f3095102b9d47c83e177fb84 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sat, 31 Oct 2020 17:21:40 -0400 Subject: [PATCH 322/403] runtime: use indexed load/store in ARM64 assembly Minor optimization. Spotted while working on that code. Change-Id: Ia02dee10d74bce79a0bef1eaba7fac1bfc27df38 Reviewed-on: https://go-review.googlesource.com/c/go/+/266899 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: fannie zhang Reviewed-by: David Chase --- src/runtime/race_arm64.s | 3 +-- src/runtime/tls_arm64.s | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index 5b1a1cb89a1..6bc389f69f4 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -38,8 +38,7 @@ MRS_TPIDR_R0 \ TP_ALIGN \ MOVD runtime·tls_g(SB), R11 \ - ADD R11, R0 \ - MOVD 0(R0), g + MOVD (R0)(R11), g // func runtime·raceread(addr uintptr) // Called from instrumented code. diff --git a/src/runtime/tls_arm64.s b/src/runtime/tls_arm64.s index 701abae105d..3f02974d5b7 100644 --- a/src/runtime/tls_arm64.s +++ b/src/runtime/tls_arm64.s @@ -20,8 +20,7 @@ TEXT runtime·load_g(SB),NOSPLIT,$0 AND $0xfffffffffffffff8, R0 #endif MOVD runtime·tls_g(SB), R27 - ADD R27, R0 - MOVD 0(R0), g + MOVD (R0)(R27), g nocgo: RET @@ -38,8 +37,7 @@ TEXT runtime·save_g(SB),NOSPLIT,$0 AND $0xfffffffffffffff8, R0 #endif MOVD runtime·tls_g(SB), R27 - ADD R27, R0 - MOVD g, 0(R0) + MOVD g, (R0)(R27) nocgo: RET From 33d9251530eb368850cc2066adab7c0cb380f052 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 2 Nov 2020 09:12:28 -0500 Subject: [PATCH 323/403] all: update dependency on golang.org/x/sys and regenerate Windows syscalls Steps run: $ cd $(go env GOROOT)/src $ go get -d golang.org/x/sys $ go mod tidy $ go mod vendor $ go generate syscall/... internal/syscall/... $ cd cmd $ go get -d golang.org/x/sys $ go mod tidy $ go mod vendor $ cd .. $ git add . This change subsumes CL 260860. For #36905 Change-Id: I7c677c6aa1ad61b9cbd8cf9ed208ed5a30f29c87 Reviewed-on: https://go-review.googlesource.com/c/go/+/267103 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../x/sys/unix/fcntl_linux_32bit.go | 4 +- src/cmd/vendor/golang.org/x/sys/unix/gccgo.go | 2 - .../vendor/golang.org/x/sys/unix/gccgo_c.c | 6 + .../vendor/golang.org/x/sys/unix/mkerrors.sh | 11 +- .../x/sys/unix/sockcmsg_unix_other.go | 4 + .../vendor/golang.org/x/sys/unix/syscall.go | 43 +- .../golang.org/x/sys/unix/syscall_aix.go | 16 + .../golang.org/x/sys/unix/syscall_bsd.go | 17 +- .../golang.org/x/sys/unix/syscall_darwin.go | 135 +- .../x/sys/unix/syscall_darwin_386.go | 7 +- .../x/sys/unix/syscall_darwin_amd64.go | 7 +- .../x/sys/unix/syscall_darwin_arm.go | 4 +- .../x/sys/unix/syscall_darwin_arm64.go | 9 +- .../x/sys/unix/syscall_dragonfly.go | 19 +- .../golang.org/x/sys/unix/syscall_freebsd.go | 19 +- .../golang.org/x/sys/unix/syscall_linux.go | 28 +- .../x/sys/unix/syscall_linux_386.go | 3 - .../golang.org/x/sys/unix/syscall_netbsd.go | 19 +- .../golang.org/x/sys/unix/syscall_openbsd.go | 19 +- .../golang.org/x/sys/unix/syscall_solaris.go | 7 +- .../x/sys/unix/zerrors_darwin_386.go | 2 + .../x/sys/unix/zerrors_darwin_amd64.go | 2 + .../x/sys/unix/zerrors_darwin_arm.go | 2 + .../x/sys/unix/zerrors_darwin_arm64.go | 2 + .../x/sys/unix/zerrors_dragonfly_amd64.go | 138 +- .../golang.org/x/sys/unix/zerrors_linux.go | 113 +- .../x/sys/unix/zerrors_solaris_amd64.go | 22 +- .../x/sys/unix/zsyscall_darwin_386.go | 67 +- .../x/sys/unix/zsyscall_darwin_386.s | 8 +- .../x/sys/unix/zsyscall_darwin_amd64.go | 67 +- .../x/sys/unix/zsyscall_darwin_amd64.s | 8 +- .../x/sys/unix/zsyscall_darwin_arm.go | 37 +- .../x/sys/unix/zsyscall_darwin_arm.s | 4 +- .../x/sys/unix/zsyscall_darwin_arm64.go | 52 +- .../x/sys/unix/zsyscall_darwin_arm64.s | 6 +- .../x/sys/unix/zsyscall_dragonfly_amd64.go | 32 +- .../x/sys/unix/zsysnum_darwin_386.go | 437 ++ .../x/sys/unix/zsysnum_darwin_amd64.go | 439 ++ .../x/sys/unix/zsysnum_darwin_arm.go | 437 ++ .../x/sys/unix/zsysnum_darwin_arm64.go | 437 ++ .../x/sys/unix/zsysnum_dragonfly_amd64.go | 255 +- .../x/sys/unix/zsysnum_linux_386.go | 1 + .../x/sys/unix/zsysnum_linux_amd64.go | 1 + .../x/sys/unix/zsysnum_linux_arm.go | 1 + .../x/sys/unix/zsysnum_linux_arm64.go | 1 + .../x/sys/unix/zsysnum_linux_mips.go | 1 + .../x/sys/unix/zsysnum_linux_mips64.go | 1 + .../x/sys/unix/zsysnum_linux_mips64le.go | 1 + .../x/sys/unix/zsysnum_linux_mipsle.go | 1 + .../x/sys/unix/zsysnum_linux_ppc64.go | 1 + .../x/sys/unix/zsysnum_linux_ppc64le.go | 1 + .../x/sys/unix/zsysnum_linux_riscv64.go | 1 + .../x/sys/unix/zsysnum_linux_s390x.go | 1 + .../x/sys/unix/zsysnum_linux_sparc64.go | 1 + .../x/sys/unix/ztypes_darwin_386.go | 32 +- .../x/sys/unix/ztypes_darwin_amd64.go | 43 +- .../x/sys/unix/ztypes_darwin_arm.go | 39 +- .../x/sys/unix/ztypes_darwin_arm64.go | 43 +- .../x/sys/unix/ztypes_dragonfly_amd64.go | 46 +- .../golang.org/x/sys/unix/ztypes_linux.go | 964 ++- .../golang.org/x/sys/unix/ztypes_linux_386.go | 15 + .../x/sys/unix/ztypes_linux_amd64.go | 16 + .../golang.org/x/sys/unix/ztypes_linux_arm.go | 16 + .../x/sys/unix/ztypes_linux_arm64.go | 16 + .../x/sys/unix/ztypes_linux_mips.go | 16 + .../x/sys/unix/ztypes_linux_mips64.go | 16 + .../x/sys/unix/ztypes_linux_mips64le.go | 16 + .../x/sys/unix/ztypes_linux_mipsle.go | 16 + .../x/sys/unix/ztypes_linux_ppc64.go | 16 + .../x/sys/unix/ztypes_linux_ppc64le.go | 16 + .../x/sys/unix/ztypes_linux_riscv64.go | 16 + .../x/sys/unix/ztypes_linux_s390x.go | 16 + .../x/sys/unix/ztypes_linux_sparc64.go | 16 + .../x/sys/unix/ztypes_solaris_amd64.go | 31 +- .../golang.org/x/sys/windows/syscall.go | 46 +- .../x/sys/windows/syscall_windows.go | 27 +- .../x/sys/windows/zsyscall_windows.go | 6233 +++++++---------- src/cmd/vendor/modules.txt | 3 +- src/go.mod | 2 +- src/go.sum | 4 +- .../windows/registry/zsyscall_windows.go | 25 +- .../syscall/windows/zsyscall_windows.go | 497 +- src/syscall/zsyscall_windows.go | 2857 ++++---- src/vendor/golang.org/x/sys/cpu/cpu.go | 60 +- src/vendor/golang.org/x/sys/cpu/cpu_arm64.go | 39 +- .../golang.org/x/sys/cpu/cpu_linux_s390x.go | 121 +- .../golang.org/x/sys/cpu/cpu_netbsd_arm64.go | 173 + .../golang.org/x/sys/cpu/cpu_other_arm64.go | 3 +- .../golang.org/x/sys/cpu/cpu_other_mips64x.go | 12 + src/vendor/golang.org/x/sys/cpu/cpu_s390x.go | 150 +- src/vendor/golang.org/x/sys/cpu/cpu_x86.go | 51 +- src/vendor/golang.org/x/sys/cpu/cpu_zos.go | 10 + .../golang.org/x/sys/cpu/cpu_zos_s390x.go | 25 + src/vendor/modules.txt | 2 +- 96 files changed, 8085 insertions(+), 6625 deletions(-) create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go create mode 100644 src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_zos.go create mode 100644 src/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index f79b238a1de..9d47f8bcff3 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -8,6 +8,6 @@ require ( golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 - golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect + golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 // indirect golang.org/x/tools v0.0.0-20201014170642-d1624618ad65 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 6eff8a2c57b..f7621ad4368 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -26,8 +26,8 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201014170642-d1624618ad65 h1:q80OtYaeeySe8Kqg0vjXehHwj5fUTqe3xOvnbi5w3Gg= diff --git a/src/cmd/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go b/src/cmd/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go index fc0e50e0372..8db48e5e062 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/fcntl_linux_32bit.go @@ -1,9 +1,9 @@ -// +build linux,386 linux,arm linux,mips linux,mipsle - // Copyright 2014 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. +// +build linux,386 linux,arm linux,mips linux,mipsle + package unix func init() { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/gccgo.go b/src/cmd/vendor/golang.org/x/sys/unix/gccgo.go index cd6f5a6133f..86032c11ef3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/gccgo.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/gccgo.go @@ -12,10 +12,8 @@ import "syscall" // We can't use the gc-syntax .s files for gccgo. On the plus side // much of the functionality can be written directly in Go. -//extern gccgoRealSyscallNoError func realSyscallNoError(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r uintptr) -//extern gccgoRealSyscall func realSyscall(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r, errno uintptr) func SyscallNoError(trap, a1, a2, a3 uintptr) (r1, r2 uintptr) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/gccgo_c.c b/src/cmd/vendor/golang.org/x/sys/unix/gccgo_c.c index c44730c5e99..2cb1fefac64 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/gccgo_c.c +++ b/src/cmd/vendor/golang.org/x/sys/unix/gccgo_c.c @@ -21,6 +21,9 @@ struct ret { uintptr_t err; }; +struct ret gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) + __asm__(GOSYM_PREFIX GOPKGPATH ".realSyscall"); + struct ret gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) { @@ -32,6 +35,9 @@ gccgoRealSyscall(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintp return r; } +uintptr_t gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) + __asm__(GOSYM_PREFIX GOPKGPATH ".realSyscallNoError"); + uintptr_t gccgoRealSyscallNoError(uintptr_t trap, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh index 1bef7148d2a..0c9a5c44bbe 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -59,12 +59,14 @@ includes_Darwin=' #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -94,6 +96,7 @@ includes_DragonFly=' #include #include #include +#include #include #include #include @@ -230,6 +233,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -372,6 +376,7 @@ includes_SunOS=' #include #include #include +#include #include #include #include @@ -496,6 +501,7 @@ ccflags="$@" $2 !~ "NLA_TYPE_MASK" && $2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ && $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ || + $2 ~ /^FIORDCHK$/ || $2 ~ /^SIOC/ || $2 ~ /^TIOC/ || $2 ~ /^TCGET/ || @@ -516,6 +522,7 @@ ccflags="$@" $2 ~ /^CAP_/ || $2 ~ /^CP_/ || $2 ~ /^CPUSTATES$/ || + $2 ~ /^CTLIOCGINFO$/ || $2 ~ /^ALG_/ || $2 ~ /^FI(CLONE|DEDUPERANGE)/ || $2 ~ /^FS_(POLICY_FLAGS|KEY_DESC|ENCRYPTION_MODE|[A-Z0-9_]+_KEY_SIZE)/ || @@ -527,7 +534,7 @@ ccflags="$@" $2 ~ /^RND/ || $2 ~ /^KEY_(SPEC|REQKEY_DEFL)_/ || $2 ~ /^KEYCTL_/ || - $2 ~ /^PERF_EVENT_IOC_/ || + $2 ~ /^PERF_/ || $2 ~ /^SECCOMP_MODE_/ || $2 ~ /^SPLICE_/ || $2 ~ /^SYNC_FILE_RANGE_/ || @@ -546,7 +553,7 @@ ccflags="$@" $2 ~ /^XATTR_(CREATE|REPLACE|NO(DEFAULT|FOLLOW|SECURITY)|SHOWCOMPRESSION)/ || $2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ || $2 ~ /^FSOPT_/ || - $2 ~ /^WDIOC_/ || + $2 ~ /^WDIO[CFS]_/ || $2 ~ /^NFN/ || $2 ~ /^XDP_/ || $2 ~ /^RWF_/ || diff --git a/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go b/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go index abdedcf1d56..57a0021da55 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/sockcmsg_unix_other.go @@ -32,6 +32,10 @@ func cmsgAlignOf(salen int) int { if runtime.GOARCH == "arm" { salign = 8 } + // NetBSD aarch64 requires 128-bit alignment. + if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm64" { + salign = 16 + } } return (salen + salign - 1) & ^(salign - 1) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall.go index fd4ee8ebeb7..ab75ef9cc62 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall.go @@ -24,7 +24,13 @@ // holds a value of type syscall.Errno. package unix // import "golang.org/x/sys/unix" -import "strings" +import ( + "bytes" + "strings" + "unsafe" + + "golang.org/x/sys/internal/unsafeheader" +) // ByteSliceFromString returns a NUL-terminated slice of bytes // containing the text of s. If s contains a NUL byte at any @@ -49,5 +55,40 @@ func BytePtrFromString(s string) (*byte, error) { return &a[0], nil } +// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any +// bytes after the NUL removed. +func ByteSliceToString(s []byte) string { + if i := bytes.IndexByte(s, 0); i != -1 { + s = s[:i] + } + return string(s) +} + +// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string. +// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated +// at a zero byte; if the zero byte is not present, the program may crash. +func BytePtrToString(p *byte) string { + if p == nil { + return "" + } + if *p == 0 { + return "" + } + + // Find NUL terminator. + n := 0 + for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { + ptr = unsafe.Pointer(uintptr(ptr) + 1) + } + + var s []byte + h := (*unsafeheader.Slice)(unsafe.Pointer(&s)) + h.Data = unsafe.Pointer(p) + h.Len = n + h.Cap = n + + return string(s) +} + // Single-word zero for use when we need a valid pointer to 0 bytes. var _zero uintptr diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go index 9ad8a0d4a56..4408153822d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_aix.go @@ -19,6 +19,22 @@ import "unsafe" * Wrapped */ +func Access(path string, mode uint32) (err error) { + return Faccessat(AT_FDCWD, path, mode, 0) +} + +func Chmod(path string, mode uint32) (err error) { + return Fchmodat(AT_FDCWD, path, mode, 0) +} + +func Chown(path string, uid int, gid int) (err error) { + return Fchownat(AT_FDCWD, path, uid, gid, 0) +} + +func Creat(path string, mode uint32) (fd int, err error) { + return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) +} + //sys utimes(path string, times *[2]Timeval) (err error) func Utimes(path string, tv []Timeval) error { if len(tv) != 2 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go index 9ebe92e4da6..bc634a280a0 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_bsd.go @@ -18,6 +18,21 @@ import ( "unsafe" ) +const ImplementsGetwd = true + +func Getwd() (string, error) { + var buf [PathMax]byte + _, err := Getcwd(buf[0:]) + if err != nil { + return "", err + } + n := clen(buf[:]) + if n < 1 { + return "", EINVAL + } + return string(buf[:n]), nil +} + /* * Wrapped */ @@ -262,7 +277,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { } return sa, nil } - return nil, EAFNOSUPPORT + return anyToSockaddrGOOS(fd, rsa) } func Accept(fd int) (nfd int, sa Sockaddr, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go index eddcf3a911a..b6257389008 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -13,29 +13,11 @@ package unix import ( - "errors" + "runtime" "syscall" "unsafe" ) -const ImplementsGetwd = true - -func Getwd() (string, error) { - buf := make([]byte, 2048) - attrs, err := getAttrList(".", attrList{CommonAttr: attrCmnFullpath}, buf, 0) - if err == nil && len(attrs) == 1 && len(attrs[0]) >= 2 { - wd := string(attrs[0]) - // Sanity check that it's an absolute path and ends - // in a null byte, which we then strip. - if wd[0] == '/' && wd[len(wd)-1] == 0 { - return wd[:len(wd)-1], nil - } - } - // If pkg/os/getwd.go gets ENOTSUP, it will fall back to the - // slow algorithm. - return "", ENOTSUP -} - // SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets. type SockaddrDatalink struct { Len uint8 @@ -49,10 +31,40 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +// SockaddrCtl implements the Sockaddr interface for AF_SYSTEM type sockets. +type SockaddrCtl struct { + ID uint32 + Unit uint32 + raw RawSockaddrCtl +} + +func (sa *SockaddrCtl) sockaddr() (unsafe.Pointer, _Socklen, error) { + sa.raw.Sc_len = SizeofSockaddrCtl + sa.raw.Sc_family = AF_SYSTEM + sa.raw.Ss_sysaddr = AF_SYS_CONTROL + sa.raw.Sc_id = sa.ID + sa.raw.Sc_unit = sa.Unit + return unsafe.Pointer(&sa.raw), SizeofSockaddrCtl, nil +} + +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + switch rsa.Addr.Family { + case AF_SYSTEM: + pp := (*RawSockaddrCtl)(unsafe.Pointer(rsa)) + if pp.Ss_sysaddr == AF_SYS_CONTROL { + sa := new(SockaddrCtl) + sa.ID = pp.Sc_id + sa.Unit = pp.Sc_unit + return sa, nil + } + } + return nil, EAFNOSUPPORT +} + // Some external packages rely on SYS___SYSCTL being defined to implement their // own sysctl wrappers. Provide it here, even though direct syscalls are no // longer supported on darwin. -const SYS___SYSCTL = 202 +const SYS___SYSCTL = SYS_SYSCTL // Translate "kern.hostname" to []_C_int{0,1,2,3}. func nametomib(name string) (mib []_C_int, err error) { @@ -97,11 +109,6 @@ func direntNamlen(buf []byte) (uint64, bool) { func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) } func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) } -const ( - attrBitMapCount = 5 - attrCmnFullpath = 0x08000000 -) - type attrList struct { bitmapCount uint16 _ uint16 @@ -112,54 +119,6 @@ type attrList struct { Forkattr uint32 } -func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (attrs [][]byte, err error) { - if len(attrBuf) < 4 { - return nil, errors.New("attrBuf too small") - } - attrList.bitmapCount = attrBitMapCount - - var _p0 *byte - _p0, err = BytePtrFromString(path) - if err != nil { - return nil, err - } - - if err := getattrlist(_p0, unsafe.Pointer(&attrList), unsafe.Pointer(&attrBuf[0]), uintptr(len(attrBuf)), int(options)); err != nil { - return nil, err - } - size := *(*uint32)(unsafe.Pointer(&attrBuf[0])) - - // dat is the section of attrBuf that contains valid data, - // without the 4 byte length header. All attribute offsets - // are relative to dat. - dat := attrBuf - if int(size) < len(attrBuf) { - dat = dat[:size] - } - dat = dat[4:] // remove length prefix - - for i := uint32(0); int(i) < len(dat); { - header := dat[i:] - if len(header) < 8 { - return attrs, errors.New("truncated attribute header") - } - datOff := *(*int32)(unsafe.Pointer(&header[0])) - attrLen := *(*uint32)(unsafe.Pointer(&header[4])) - if datOff < 0 || uint32(datOff)+attrLen > uint32(len(dat)) { - return attrs, errors.New("truncated results; attrBuf too small") - } - end := uint32(datOff) + attrLen - attrs = append(attrs, dat[datOff:end]) - i = end - if r := i % 4; r != 0 { - i += (4 - r) - } - } - return -} - -//sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) - //sysnb pipe() (r int, w int, err error) func Pipe(p []int) (err error) { @@ -329,6 +288,35 @@ func Kill(pid int, signum syscall.Signal) (err error) { return kill(pid, int(sig //sys ioctl(fd int, req uint, arg uintptr) (err error) +func IoctlCtlInfo(fd int, ctlInfo *CtlInfo) error { + err := ioctl(fd, CTLIOCGINFO, uintptr(unsafe.Pointer(ctlInfo))) + runtime.KeepAlive(ctlInfo) + return err +} + +// IfreqMTU is struct ifreq used to get or set a network device's MTU. +type IfreqMTU struct { + Name [IFNAMSIZ]byte + MTU int32 +} + +// IoctlGetIfreqMTU performs the SIOCGIFMTU ioctl operation on fd to get the MTU +// of the network device specified by ifname. +func IoctlGetIfreqMTU(fd int, ifname string) (*IfreqMTU, error) { + var ifreq IfreqMTU + copy(ifreq.Name[:], ifname) + err := ioctl(fd, SIOCGIFMTU, uintptr(unsafe.Pointer(&ifreq))) + return &ifreq, err +} + +// IoctlSetIfreqMTU performs the SIOCSIFMTU ioctl operation on fd to set the MTU +// of the network device specified by ifreq.Name. +func IoctlSetIfreqMTU(fd int, ifreq *IfreqMTU) error { + err := ioctl(fd, SIOCSIFMTU, uintptr(unsafe.Pointer(ifreq))) + runtime.KeepAlive(ifreq) + return err +} + //sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS_SYSCTL func Uname(uname *Utsname) error { @@ -419,6 +407,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Fpathconf(fd int, name int) (val int, err error) //sys Fsync(fd int) (err error) //sys Ftruncate(fd int, length int64) (err error) +//sys Getcwd(buf []byte) (n int, err error) //sys Getdtablesize() (size int) //sysnb Getegid() (egid int) //sysnb Geteuid() (uid int) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go index ea0be1e9291..6c1f4ab95b4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go @@ -6,11 +6,7 @@ package unix -import ( - "syscall" -) - -//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) +import "syscall" func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: int32(sec), Nsec: int32(nsec)} @@ -49,5 +45,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go index 58624044843..0582ae256ef 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go @@ -6,11 +6,7 @@ package unix -import ( - "syscall" -) - -//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) +import "syscall" func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} @@ -49,5 +45,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64 //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64 //sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64 +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) //sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64 //sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go index b8b31418191..c6a9733b4cb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm.go @@ -4,9 +4,7 @@ package unix -import ( - "syscall" -) +import "syscall" func ptrace(request int, pid int, addr uintptr, data uintptr) error { return ENOTSUP diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go index 67413983735..253afa4de55 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_arm64.go @@ -6,13 +6,7 @@ package unix -import ( - "syscall" -) - -func ptrace(request int, pid int, addr uintptr, data uintptr) error { - return ENOTSUP -} +import "syscall" func setTimespec(sec, nsec int64) Timespec { return Timespec{Sec: sec, Nsec: nsec} @@ -51,5 +45,6 @@ func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, //sys Fstatfs(fd int, stat *Statfs_t) (err error) //sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT //sys Lstat(path string, stat *Stat_t) (err error) +//sys ptrace(request int, pid int, addr uintptr, data uintptr) (err error) //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 8a195ae586c..842ab5acde8 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -47,6 +47,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + // Translate "kern.hostname" to []_C_int{0,1,2,3}. func nametomib(name string) (mib []_C_int, err error) { const siz = unsafe.Sizeof(mib[0]) @@ -129,23 +133,8 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { var _p0 unsafe.Pointer var bufsize uintptr diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go index 6932e7c2c1a..acc00c2e6a1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -54,6 +54,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + // Translate "kern.hostname" to []_C_int{0,1,2,3}. func nametomib(name string) (mib []_C_int, err error) { const siz = unsafe.Sizeof(mib[0]) @@ -140,23 +144,8 @@ func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { var ( _p0 unsafe.Pointer diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go index 94dafa4e528..84a9e5277ac 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -106,15 +106,24 @@ func IoctlGetRTCTime(fd int) (*RTCTime, error) { return &value, err } +// IoctlGetWatchdogInfo fetches information about a watchdog device from the +// Linux watchdog API. For more information, see: +// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. +func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) { + var value WatchdogInfo + err := ioctl(fd, WDIOC_GETSUPPORT, uintptr(unsafe.Pointer(&value))) + return &value, err +} + func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) { var value RTCWkAlrm err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value))) return &value, err } -// IoctlFileClone performs an FICLONERANGE ioctl operation to clone the range of -// data conveyed in value to the file associated with the file descriptor -// destFd. See the ioctl_ficlonerange(2) man page for details. +// IoctlFileCloneRange performs an FICLONERANGE ioctl operation to clone the +// range of data conveyed in value to the file associated with the file +// descriptor destFd. See the ioctl_ficlonerange(2) man page for details. func IoctlFileCloneRange(destFd int, value *FileCloneRange) error { err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) @@ -128,15 +137,22 @@ func IoctlFileClone(destFd, srcFd int) error { return ioctl(destFd, FICLONE, uintptr(srcFd)) } -// IoctlFileClone performs an FIDEDUPERANGE ioctl operation to share the range of -// data conveyed in value with the file associated with the file descriptor -// destFd. See the ioctl_fideduperange(2) man page for details. +// IoctlFileDedupeRange performs an FIDEDUPERANGE ioctl operation to share the +// range of data conveyed in value with the file associated with the file +// descriptor destFd. See the ioctl_fideduperange(2) man page for details. func IoctlFileDedupeRange(destFd int, value *FileDedupeRange) error { err := ioctl(destFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(value))) runtime.KeepAlive(value) return err } +// IoctlWatchdogKeepalive issues a keepalive ioctl to a watchdog device. For +// more information, see: +// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html. +func IoctlWatchdogKeepalive(fd int) error { + return ioctl(fd, WDIOC_KEEPALIVE, 0) +} + //sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) func Link(oldpath string, newpath string) (err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go index 048d18e3c81..c97c2ee53e5 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// TODO(rsc): Rewrite all nn(SP) references into name+(nn-8)(FP) -// so that go vet can check that they are correct. - // +build 386,linux package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 45b50a6105e..1e6843b4c3d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -31,6 +31,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) { @@ -141,23 +145,8 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - // TODO func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { return -1, ENOSYS diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go index a266e92a9b1..6a50b50bd69 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -31,6 +31,10 @@ type SockaddrDatalink struct { raw RawSockaddrDatalink } +func anyToSockaddrGOOS(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { + return nil, EAFNOSUPPORT +} + func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno) func nametomib(name string) (mib []_C_int, err error) { @@ -114,23 +118,8 @@ func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) { return } -const ImplementsGetwd = true - //sys Getcwd(buf []byte) (n int, err error) = SYS___GETCWD -func Getwd() (string, error) { - var buf [PathMax]byte - _, err := Getcwd(buf[0:]) - if err != nil { - return "", err - } - n := clen(buf[:]) - if n < 1 { - return "", EINVAL - } - return string(buf[:n]), nil -} - func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) { if raceenabled { raceReleaseMerge(unsafe.Pointer(&ioSync)) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go index 0e2a696ad36..fee6e995289 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -13,6 +13,7 @@ package unix import ( + "runtime" "syscall" "unsafe" ) @@ -553,8 +554,10 @@ func Minor(dev uint64) uint32 { //sys ioctl(fd int, req uint, arg uintptr) (err error) -func IoctlSetTermio(fd int, req uint, value *Termio) (err error) { - return ioctl(fd, req, uintptr(unsafe.Pointer(value))) +func IoctlSetTermio(fd int, req uint, value *Termio) error { + err := ioctl(fd, req, uintptr(unsafe.Pointer(value))) + runtime.KeepAlive(value) + return err } func IoctlGetTermio(fd int, req uint) (*Termio, error) { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go index 6f333594bbd..ec376f51bc4 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_386.go @@ -45,6 +45,7 @@ const ( AF_SIP = 0x18 AF_SNA = 0xb AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 AF_UNIX = 0x1 AF_UNSPEC = 0x0 AF_UTUN = 0x26 @@ -251,6 +252,7 @@ const ( CSTOP = 0x13 CSTOPB = 0x400 CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 CTL_HW = 0x6 CTL_KERN = 0x1 CTL_MAXNAME = 0xc diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go index db767eb257f..fea5dfaadb9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go @@ -45,6 +45,7 @@ const ( AF_SIP = 0x18 AF_SNA = 0xb AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 AF_UNIX = 0x1 AF_UNSPEC = 0x0 AF_UTUN = 0x26 @@ -251,6 +252,7 @@ const ( CSTOP = 0x13 CSTOPB = 0x400 CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 CTL_HW = 0x6 CTL_KERN = 0x1 CTL_MAXNAME = 0xc diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go index ddc5d001b69..03feefbf8c9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm.go @@ -45,6 +45,7 @@ const ( AF_SIP = 0x18 AF_SNA = 0xb AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 AF_UNIX = 0x1 AF_UNSPEC = 0x0 AF_UTUN = 0x26 @@ -251,6 +252,7 @@ const ( CSTOP = 0x13 CSTOPB = 0x400 CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 CTL_HW = 0x6 CTL_KERN = 0x1 CTL_MAXNAME = 0xc diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go index 0614d26d01e..b40fb1f6967 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go @@ -45,6 +45,7 @@ const ( AF_SIP = 0x18 AF_SNA = 0xb AF_SYSTEM = 0x20 + AF_SYS_CONTROL = 0x2 AF_UNIX = 0x1 AF_UNSPEC = 0x0 AF_UTUN = 0x26 @@ -251,6 +252,7 @@ const ( CSTOP = 0x13 CSTOPB = 0x400 CSUSP = 0x1a + CTLIOCGINFO = 0xc0644e03 CTL_HW = 0x6 CTL_KERN = 0x1 CTL_MAXNAME = 0xc diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go index 6130471748a..f5e91b7abaa 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_dragonfly_amd64.go @@ -62,6 +62,7 @@ const ( B28800 = 0x7080 B300 = 0x12c B38400 = 0x9600 + B460800 = 0x70800 B4800 = 0x12c0 B50 = 0x32 B57600 = 0xe100 @@ -69,12 +70,15 @@ const ( B7200 = 0x1c20 B75 = 0x4b B76800 = 0x12c00 + B921600 = 0xe1000 B9600 = 0x2580 + BIOCFEEDBACK = 0x8004427d BIOCFLUSH = 0x20004268 BIOCGBLEN = 0x40044266 BIOCGDLT = 0x4004426a BIOCGDLTLIST = 0xc0104279 BIOCGETIF = 0x4020426b + BIOCGFEEDBACK = 0x4004427c BIOCGHDRCMPLT = 0x40044274 BIOCGRSIG = 0x40044272 BIOCGRTIMEOUT = 0x4010426e @@ -88,6 +92,7 @@ const ( BIOCSETF = 0x80104267 BIOCSETIF = 0x8020426c BIOCSETWF = 0x8010427b + BIOCSFEEDBACK = 0x8004427d BIOCSHDRCMPLT = 0x80044275 BIOCSRSIG = 0x80044273 BIOCSRTIMEOUT = 0x8010426d @@ -125,6 +130,7 @@ const ( BPF_MINBUFSIZE = 0x20 BPF_MINOR_VERSION = 0x1 BPF_MISC = 0x7 + BPF_MOD = 0x90 BPF_MSH = 0xa0 BPF_MUL = 0x20 BPF_NEG = 0x80 @@ -139,6 +145,7 @@ const ( BPF_TXA = 0x80 BPF_W = 0x0 BPF_X = 0x8 + BPF_XOR = 0xa0 BRKINT = 0x2 CFLUSH = 0xf CLOCAL = 0x8000 @@ -156,6 +163,12 @@ const ( CLOCK_UPTIME_FAST = 0x8 CLOCK_UPTIME_PRECISE = 0x7 CLOCK_VIRTUAL = 0x1 + CPUSTATES = 0x5 + CP_IDLE = 0x4 + CP_INTR = 0x3 + CP_NICE = 0x1 + CP_SYS = 0x2 + CP_USER = 0x0 CREAD = 0x800 CRTSCTS = 0x30000 CS5 = 0x0 @@ -175,6 +188,7 @@ const ( DLT_A429 = 0xb8 DLT_A653_ICM = 0xb9 DLT_AIRONET_HEADER = 0x78 + DLT_AOS = 0xde DLT_APPLE_IP_OVER_IEEE1394 = 0x8a DLT_ARCNET = 0x7 DLT_ARCNET_LINUX = 0x81 @@ -184,22 +198,33 @@ const ( DLT_AX25 = 0x3 DLT_AX25_KISS = 0xca DLT_BACNET_MS_TP = 0xa5 + DLT_BLUETOOTH_BREDR_BB = 0xff DLT_BLUETOOTH_HCI_H4 = 0xbb DLT_BLUETOOTH_HCI_H4_WITH_PHDR = 0xc9 + DLT_BLUETOOTH_LE_LL = 0xfb + DLT_BLUETOOTH_LE_LL_WITH_PHDR = 0x100 + DLT_BLUETOOTH_LINUX_MONITOR = 0xfe DLT_CAN20B = 0xbe + DLT_CAN_SOCKETCAN = 0xe3 DLT_CHAOS = 0x5 DLT_CHDLC = 0x68 DLT_CISCO_IOS = 0x76 DLT_C_HDLC = 0x68 DLT_C_HDLC_WITH_DIR = 0xcd + DLT_DBUS = 0xe7 + DLT_DECT = 0xdd DLT_DOCSIS = 0x8f + DLT_DVB_CI = 0xeb DLT_ECONET = 0x73 DLT_EN10MB = 0x1 DLT_EN3MB = 0x2 DLT_ENC = 0x6d + DLT_EPON = 0x103 DLT_ERF = 0xc5 DLT_ERF_ETH = 0xaf DLT_ERF_POS = 0xb0 + DLT_FC_2 = 0xe0 + DLT_FC_2_WITH_FRAME_DELIMS = 0xe1 DLT_FDDI = 0xa DLT_FLEXRAY = 0xd2 DLT_FRELAY = 0x6b @@ -209,6 +234,8 @@ const ( DLT_GPF_F = 0xab DLT_GPF_T = 0xaa DLT_GPRS_LLC = 0xa9 + DLT_GSMTAP_ABIS = 0xda + DLT_GSMTAP_UM = 0xd9 DLT_HHDLC = 0x79 DLT_IBM_SN = 0x92 DLT_IBM_SP = 0x91 @@ -218,18 +245,28 @@ const ( DLT_IEEE802_11_RADIO_AVS = 0xa3 DLT_IEEE802_15_4 = 0xc3 DLT_IEEE802_15_4_LINUX = 0xbf + DLT_IEEE802_15_4_NOFCS = 0xe6 DLT_IEEE802_15_4_NONASK_PHY = 0xd7 DLT_IEEE802_16_MAC_CPS = 0xbc DLT_IEEE802_16_MAC_CPS_RADIO = 0xc1 + DLT_INFINIBAND = 0xf7 DLT_IPFILTER = 0x74 DLT_IPMB = 0xc7 DLT_IPMB_LINUX = 0xd1 + DLT_IPMI_HPM_2 = 0x104 + DLT_IPNET = 0xe2 + DLT_IPOIB = 0xf2 + DLT_IPV4 = 0xe4 + DLT_IPV6 = 0xe5 DLT_IP_OVER_FC = 0x7a + DLT_ISO_14443 = 0x108 DLT_JUNIPER_ATM1 = 0x89 DLT_JUNIPER_ATM2 = 0x87 + DLT_JUNIPER_ATM_CEMIC = 0xee DLT_JUNIPER_CHDLC = 0xb5 DLT_JUNIPER_ES = 0x84 DLT_JUNIPER_ETHER = 0xb2 + DLT_JUNIPER_FIBRECHANNEL = 0xea DLT_JUNIPER_FRELAY = 0xb4 DLT_JUNIPER_GGSN = 0x85 DLT_JUNIPER_ISM = 0xc2 @@ -242,25 +279,40 @@ const ( DLT_JUNIPER_PPPOE = 0xa7 DLT_JUNIPER_PPPOE_ATM = 0xa8 DLT_JUNIPER_SERVICES = 0x88 + DLT_JUNIPER_SRX_E2E = 0xe9 DLT_JUNIPER_ST = 0xc8 DLT_JUNIPER_VP = 0xb7 + DLT_JUNIPER_VS = 0xe8 DLT_LAPB_WITH_DIR = 0xcf DLT_LAPD = 0xcb DLT_LIN = 0xd4 + DLT_LINUX_EVDEV = 0xd8 DLT_LINUX_IRDA = 0x90 DLT_LINUX_LAPD = 0xb1 DLT_LINUX_SLL = 0x71 DLT_LOOP = 0x6c DLT_LTALK = 0x72 + DLT_MATCHING_MAX = 0x109 + DLT_MATCHING_MIN = 0x68 DLT_MFR = 0xb6 DLT_MOST = 0xd3 + DLT_MPEG_2_TS = 0xf3 + DLT_MPLS = 0xdb DLT_MTP2 = 0x8c DLT_MTP2_WITH_PHDR = 0x8b DLT_MTP3 = 0x8d + DLT_MUX27010 = 0xec + DLT_NETANALYZER = 0xf0 + DLT_NETANALYZER_TRANSPARENT = 0xf1 + DLT_NETLINK = 0xfd + DLT_NFC_LLCP = 0xf5 + DLT_NFLOG = 0xef + DLT_NG40 = 0xf4 DLT_NULL = 0x0 DLT_PCI_EXP = 0x7d DLT_PFLOG = 0x75 DLT_PFSYNC = 0x12 + DLT_PKTAP = 0x102 DLT_PPI = 0xc0 DLT_PPP = 0x9 DLT_PPP_BSDOS = 0x10 @@ -269,22 +321,51 @@ const ( DLT_PPP_SERIAL = 0x32 DLT_PPP_WITH_DIR = 0xcc DLT_PRISM_HEADER = 0x77 + DLT_PROFIBUS_DL = 0x101 DLT_PRONET = 0x4 DLT_RAIF1 = 0xc6 DLT_RAW = 0xc + DLT_RDS = 0x109 DLT_REDBACK_SMARTEDGE = 0x20 DLT_RIO = 0x7c + DLT_RTAC_SERIAL = 0xfa DLT_SCCP = 0x8e + DLT_SCTP = 0xf8 DLT_SITA = 0xc4 DLT_SLIP = 0x8 DLT_SLIP_BSDOS = 0xf + DLT_STANAG_5066_D_PDU = 0xed DLT_SUNATM = 0x7b DLT_SYMANTEC_FIREWALL = 0x63 DLT_TZSP = 0x80 DLT_USB = 0xba + DLT_USBPCAP = 0xf9 + DLT_USB_FREEBSD = 0xba DLT_USB_LINUX = 0xbd + DLT_USB_LINUX_MMAPPED = 0xdc + DLT_USER0 = 0x93 + DLT_USER1 = 0x94 + DLT_USER10 = 0x9d + DLT_USER11 = 0x9e + DLT_USER12 = 0x9f + DLT_USER13 = 0xa0 + DLT_USER14 = 0xa1 + DLT_USER15 = 0xa2 + DLT_USER2 = 0x95 + DLT_USER3 = 0x96 + DLT_USER4 = 0x97 + DLT_USER5 = 0x98 + DLT_USER6 = 0x99 + DLT_USER7 = 0x9a + DLT_USER8 = 0x9b + DLT_USER9 = 0x9c + DLT_WATTSTOPPER_DLM = 0x107 + DLT_WIHART = 0xdf + DLT_WIRESHARK_UPPER_PDU = 0xfc DLT_X2E_SERIAL = 0xd5 DLT_X2E_XORAYA = 0xd6 + DLT_ZWAVE_R1_R2 = 0x105 + DLT_ZWAVE_R3 = 0x106 DT_BLK = 0x6 DT_CHR = 0x2 DT_DBF = 0xf @@ -323,10 +404,11 @@ const ( EV_EOF = 0x8000 EV_ERROR = 0x4000 EV_FLAG1 = 0x2000 + EV_HUP = 0x800 EV_NODATA = 0x1000 EV_ONESHOT = 0x10 EV_RECEIPT = 0x40 - EV_SYSFLAGS = 0xf000 + EV_SYSFLAGS = 0xf800 EXTA = 0x4b00 EXTB = 0x9600 EXTEXIT_LWP = 0x10000 @@ -365,8 +447,9 @@ const ( IFF_ALLMULTI = 0x200 IFF_ALTPHYS = 0x4000 IFF_BROADCAST = 0x2 - IFF_CANTCHANGE = 0x118e72 + IFF_CANTCHANGE = 0x318e72 IFF_DEBUG = 0x4 + IFF_IDIRECT = 0x200000 IFF_LINK0 = 0x1000 IFF_LINK1 = 0x2000 IFF_LINK2 = 0x4000 @@ -441,7 +524,6 @@ const ( IFT_EPLRS = 0x57 IFT_ESCON = 0x49 IFT_ETHER = 0x6 - IFT_FAITH = 0xf2 IFT_FAST = 0x7d IFT_FASTETHER = 0x3e IFT_FASTETHERFX = 0x45 @@ -614,6 +696,7 @@ const ( IN_CLASSD_NET = 0xf0000000 IN_CLASSD_NSHIFT = 0x1c IN_LOOPBACKNET = 0x7f + IN_RFC3021_MASK = 0xfffffffe IPPROTO_3PC = 0x22 IPPROTO_ADFS = 0x44 IPPROTO_AH = 0x33 @@ -735,7 +818,6 @@ const ( IPV6_DEFHLIM = 0x40 IPV6_DONTFRAG = 0x3e IPV6_DSTOPTS = 0x32 - IPV6_FAITH = 0x1d IPV6_FLOWINFO_MASK = 0xffffff0f IPV6_FLOWLABEL_MASK = 0xffff0f00 IPV6_FRAGTTL = 0x78 @@ -747,7 +829,6 @@ const ( IPV6_HLIMDEC = 0x1 IPV6_HOPLIMIT = 0x2f IPV6_HOPOPTS = 0x31 - IPV6_IPSEC_POLICY = 0x1c IPV6_JOIN_GROUP = 0xc IPV6_LEAVE_GROUP = 0xd IPV6_MAXHLIM = 0xff @@ -795,16 +876,22 @@ const ( IP_DUMMYNET_DEL = 0x3d IP_DUMMYNET_FLUSH = 0x3e IP_DUMMYNET_GET = 0x40 - IP_FAITH = 0x16 IP_FW_ADD = 0x32 IP_FW_DEL = 0x33 IP_FW_FLUSH = 0x34 IP_FW_GET = 0x36 IP_FW_RESETLOG = 0x37 + IP_FW_TBL_ADD = 0x2a + IP_FW_TBL_CREATE = 0x28 + IP_FW_TBL_DEL = 0x2b + IP_FW_TBL_DESTROY = 0x29 + IP_FW_TBL_EXPIRE = 0x2f + IP_FW_TBL_FLUSH = 0x2c + IP_FW_TBL_GET = 0x2d + IP_FW_TBL_ZERO = 0x2e IP_FW_X = 0x31 IP_FW_ZERO = 0x35 IP_HDRINCL = 0x2 - IP_IPSEC_POLICY = 0x15 IP_MAXPACKET = 0xffff IP_MAX_MEMBERSHIPS = 0x14 IP_MF = 0x2000 @@ -1080,12 +1167,10 @@ const ( RTM_MISS = 0x7 RTM_NEWADDR = 0xc RTM_NEWMADDR = 0xf - RTM_OLDADD = 0x9 - RTM_OLDDEL = 0xa RTM_REDIRECT = 0x6 RTM_RESOLVE = 0xb RTM_RTTUNIT = 0xf4240 - RTM_VERSION = 0x6 + RTM_VERSION = 0x7 RTV_EXPIRE = 0x4 RTV_HOPCOUNT = 0x2 RTV_IWCAPSEGS = 0x400 @@ -1106,13 +1191,13 @@ const ( SHUT_RDWR = 0x2 SHUT_WR = 0x1 SIOCADDMULTI = 0x80206931 - SIOCADDRT = 0x8040720a SIOCAIFADDR = 0x8040691a + SIOCAIFGROUP = 0x80286987 SIOCALIFADDR = 0x8118691b SIOCATMARK = 0x40047307 SIOCDELMULTI = 0x80206932 - SIOCDELRT = 0x8040720b SIOCDIFADDR = 0x80206919 + SIOCDIFGROUP = 0x80286989 SIOCDIFPHYADDR = 0x80206949 SIOCDLIFADDR = 0x8118691d SIOCGDRVSPEC = 0xc028697b @@ -1120,6 +1205,7 @@ const ( SIOCGETVIFCNT = 0xc028720f SIOCGHIWAT = 0x40047301 SIOCGIFADDR = 0xc0206921 + SIOCGIFALIAS = 0xc0406929 SIOCGIFBRDADDR = 0xc0206923 SIOCGIFCAP = 0xc020691f SIOCGIFCONF = 0xc0106924 @@ -1128,6 +1214,7 @@ const ( SIOCGIFFLAGS = 0xc0206911 SIOCGIFGENERIC = 0xc020693a SIOCGIFGMEMB = 0xc028698a + SIOCGIFGROUP = 0xc0286988 SIOCGIFINDEX = 0xc0206920 SIOCGIFMEDIA = 0xc0306938 SIOCGIFMETRIC = 0xc0206917 @@ -1194,6 +1281,7 @@ const ( SO_RCVBUF = 0x1002 SO_RCVLOWAT = 0x1004 SO_RCVTIMEO = 0x1006 + SO_RERROR = 0x2000 SO_REUSEADDR = 0x4 SO_REUSEPORT = 0x200 SO_SNDBUF = 0x1001 @@ -1233,6 +1321,9 @@ const ( S_IXGRP = 0x8 S_IXOTH = 0x1 S_IXUSR = 0x40 + TAB0 = 0x0 + TAB3 = 0x4 + TABDLY = 0x4 TCIFLUSH = 0x1 TCIOFF = 0x3 TCIOFLUSH = 0x3 @@ -1259,6 +1350,8 @@ const ( TCP_NOPUSH = 0x4 TCP_SIGNATURE_ENABLE = 0x10 TCSAFLUSH = 0x2 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOCCBRK = 0x2000747a TIOCCDTR = 0x20007478 TIOCCONS = 0x80047462 @@ -1272,7 +1365,6 @@ const ( TIOCGETD = 0x4004741a TIOCGPGRP = 0x40047477 TIOCGSID = 0x40047463 - TIOCGSIZE = 0x40087468 TIOCGWINSZ = 0x40087468 TIOCISPTMASTER = 0x20007455 TIOCMBIC = 0x8004746b @@ -1317,7 +1409,6 @@ const ( TIOCSETD = 0x8004741b TIOCSIG = 0x2000745f TIOCSPGRP = 0x80047476 - TIOCSSIZE = 0x80087467 TIOCSTART = 0x2000746e TIOCSTAT = 0x20007465 TIOCSTI = 0x80017472 @@ -1326,6 +1417,8 @@ const ( TIOCTIMESTAMP = 0x40107459 TIOCUCNTL = 0x80047466 TOSTOP = 0x400000 + UTIME_NOW = -0x1 + UTIME_OMIT = -0x2 VCHECKPT = 0x13 VDISCARD = 0xf VDSUSP = 0xb @@ -1350,9 +1443,12 @@ const ( VWERASE = 0x4 WCONTINUED = 0x4 WCOREFLAG = 0x80 + WEXITED = 0x10 WLINUXCLONE = 0x80000000 WNOHANG = 0x1 - WSTOPPED = 0x7f + WNOWAIT = 0x8 + WSTOPPED = 0x2 + WTRAPPED = 0x20 WUNTRACED = 0x2 ) @@ -1452,11 +1548,6 @@ const ( ETIMEDOUT = syscall.Errno(0x3c) ETOOMANYREFS = syscall.Errno(0x3b) ETXTBSY = syscall.Errno(0x1a) - EUNUSED94 = syscall.Errno(0x5e) - EUNUSED95 = syscall.Errno(0x5f) - EUNUSED96 = syscall.Errno(0x60) - EUNUSED97 = syscall.Errno(0x61) - EUNUSED98 = syscall.Errno(0x62) EUSERS = syscall.Errno(0x44) EWOULDBLOCK = syscall.Errno(0x23) EXDEV = syscall.Errno(0x12) @@ -1600,12 +1691,7 @@ var errorList = [...]struct { {91, "ENOLINK", "link has been severed"}, {92, "EPROTO", "protocol error"}, {93, "ENOMEDIUM", "no medium found"}, - {94, "EUNUSED94", "unknown error: 94"}, - {95, "EUNUSED95", "unknown error: 95"}, - {96, "EUNUSED96", "unknown error: 96"}, - {97, "EUNUSED97", "unknown error: 97"}, - {98, "EUNUSED98", "unknown error: 98"}, - {99, "ELAST", "unknown error: 99"}, + {99, "EASYNC", "unknown error: 99"}, } // Signal table diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go index 79e032f4fb7..2069fb861d1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -324,6 +324,7 @@ const ( CAP_AUDIT_WRITE = 0x1d CAP_BLOCK_SUSPEND = 0x24 CAP_BPF = 0x27 + CAP_CHECKPOINT_RESTORE = 0x28 CAP_CHOWN = 0x0 CAP_DAC_OVERRIDE = 0x1 CAP_DAC_READ_SEARCH = 0x2 @@ -332,7 +333,7 @@ const ( CAP_IPC_LOCK = 0xe CAP_IPC_OWNER = 0xf CAP_KILL = 0x5 - CAP_LAST_CAP = 0x27 + CAP_LAST_CAP = 0x28 CAP_LEASE = 0x1c CAP_LINUX_IMMUTABLE = 0x9 CAP_MAC_ADMIN = 0x21 @@ -650,8 +651,8 @@ const ( FAN_DELETE = 0x200 FAN_DELETE_SELF = 0x400 FAN_DENY = 0x2 - FAN_DIR_MODIFY = 0x80000 FAN_ENABLE_AUDIT = 0x40 + FAN_EVENT_INFO_TYPE_DFID = 0x3 FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2 FAN_EVENT_INFO_TYPE_FID = 0x1 FAN_EVENT_METADATA_LEN = 0x18 @@ -679,7 +680,10 @@ const ( FAN_OPEN_EXEC_PERM = 0x40000 FAN_OPEN_PERM = 0x10000 FAN_Q_OVERFLOW = 0x4000 + FAN_REPORT_DFID_NAME = 0xc00 + FAN_REPORT_DIR_FID = 0x400 FAN_REPORT_FID = 0x200 + FAN_REPORT_NAME = 0x800 FAN_REPORT_TID = 0x100 FAN_UNLIMITED_MARKS = 0x20 FAN_UNLIMITED_QUEUE = 0x10 @@ -1508,6 +1512,92 @@ const ( PARITY_DEFAULT = 0x0 PARITY_NONE = 0x1 PARMRK = 0x8 + PERF_ATTR_SIZE_VER0 = 0x40 + PERF_ATTR_SIZE_VER1 = 0x48 + PERF_ATTR_SIZE_VER2 = 0x50 + PERF_ATTR_SIZE_VER3 = 0x60 + PERF_ATTR_SIZE_VER4 = 0x68 + PERF_ATTR_SIZE_VER5 = 0x70 + PERF_ATTR_SIZE_VER6 = 0x78 + PERF_AUX_FLAG_COLLISION = 0x8 + PERF_AUX_FLAG_OVERWRITE = 0x2 + PERF_AUX_FLAG_PARTIAL = 0x4 + PERF_AUX_FLAG_TRUNCATED = 0x1 + PERF_FLAG_FD_CLOEXEC = 0x8 + PERF_FLAG_FD_NO_GROUP = 0x1 + PERF_FLAG_FD_OUTPUT = 0x2 + PERF_FLAG_PID_CGROUP = 0x4 + PERF_MAX_CONTEXTS_PER_STACK = 0x8 + PERF_MAX_STACK_DEPTH = 0x7f + PERF_MEM_LOCK_LOCKED = 0x2 + PERF_MEM_LOCK_NA = 0x1 + PERF_MEM_LOCK_SHIFT = 0x18 + PERF_MEM_LVLNUM_ANY_CACHE = 0xb + PERF_MEM_LVLNUM_L1 = 0x1 + PERF_MEM_LVLNUM_L2 = 0x2 + PERF_MEM_LVLNUM_L3 = 0x3 + PERF_MEM_LVLNUM_L4 = 0x4 + PERF_MEM_LVLNUM_LFB = 0xc + PERF_MEM_LVLNUM_NA = 0xf + PERF_MEM_LVLNUM_PMEM = 0xe + PERF_MEM_LVLNUM_RAM = 0xd + PERF_MEM_LVLNUM_SHIFT = 0x21 + PERF_MEM_LVL_HIT = 0x2 + PERF_MEM_LVL_IO = 0x1000 + PERF_MEM_LVL_L1 = 0x8 + PERF_MEM_LVL_L2 = 0x20 + PERF_MEM_LVL_L3 = 0x40 + PERF_MEM_LVL_LFB = 0x10 + PERF_MEM_LVL_LOC_RAM = 0x80 + PERF_MEM_LVL_MISS = 0x4 + PERF_MEM_LVL_NA = 0x1 + PERF_MEM_LVL_REM_CCE1 = 0x400 + PERF_MEM_LVL_REM_CCE2 = 0x800 + PERF_MEM_LVL_REM_RAM1 = 0x100 + PERF_MEM_LVL_REM_RAM2 = 0x200 + PERF_MEM_LVL_SHIFT = 0x5 + PERF_MEM_LVL_UNC = 0x2000 + PERF_MEM_OP_EXEC = 0x10 + PERF_MEM_OP_LOAD = 0x2 + PERF_MEM_OP_NA = 0x1 + PERF_MEM_OP_PFETCH = 0x8 + PERF_MEM_OP_SHIFT = 0x0 + PERF_MEM_OP_STORE = 0x4 + PERF_MEM_REMOTE_REMOTE = 0x1 + PERF_MEM_REMOTE_SHIFT = 0x25 + PERF_MEM_SNOOPX_FWD = 0x1 + PERF_MEM_SNOOPX_SHIFT = 0x25 + PERF_MEM_SNOOP_HIT = 0x4 + PERF_MEM_SNOOP_HITM = 0x10 + PERF_MEM_SNOOP_MISS = 0x8 + PERF_MEM_SNOOP_NA = 0x1 + PERF_MEM_SNOOP_NONE = 0x2 + PERF_MEM_SNOOP_SHIFT = 0x13 + PERF_MEM_TLB_HIT = 0x2 + PERF_MEM_TLB_L1 = 0x8 + PERF_MEM_TLB_L2 = 0x10 + PERF_MEM_TLB_MISS = 0x4 + PERF_MEM_TLB_NA = 0x1 + PERF_MEM_TLB_OS = 0x40 + PERF_MEM_TLB_SHIFT = 0x1a + PERF_MEM_TLB_WK = 0x20 + PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER = 0x1 + PERF_RECORD_MISC_COMM_EXEC = 0x2000 + PERF_RECORD_MISC_CPUMODE_MASK = 0x7 + PERF_RECORD_MISC_CPUMODE_UNKNOWN = 0x0 + PERF_RECORD_MISC_EXACT_IP = 0x4000 + PERF_RECORD_MISC_EXT_RESERVED = 0x8000 + PERF_RECORD_MISC_FORK_EXEC = 0x2000 + PERF_RECORD_MISC_GUEST_KERNEL = 0x4 + PERF_RECORD_MISC_GUEST_USER = 0x5 + PERF_RECORD_MISC_HYPERVISOR = 0x3 + PERF_RECORD_MISC_KERNEL = 0x1 + PERF_RECORD_MISC_MMAP_DATA = 0x2000 + PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT = 0x1000 + PERF_RECORD_MISC_SWITCH_OUT = 0x2000 + PERF_RECORD_MISC_SWITCH_OUT_PREEMPT = 0x4000 + PERF_RECORD_MISC_USER = 0x2 + PERF_SAMPLE_BRANCH_PLM_ALL = 0x7 PIPEFS_MAGIC = 0x50495045 PPC_CMM_MAGIC = 0xc7571590 PPPIOCGNPMODE = 0xc008744c @@ -1894,6 +1984,7 @@ const ( RTPROT_EIGRP = 0xc0 RTPROT_GATED = 0x8 RTPROT_ISIS = 0xbb + RTPROT_KEEPALIVED = 0x12 RTPROT_KERNEL = 0x2 RTPROT_MROUTED = 0x11 RTPROT_MRT = 0xa @@ -2084,6 +2175,7 @@ const ( SO_EE_ORIGIN_TXSTATUS = 0x4 SO_EE_ORIGIN_TXTIME = 0x6 SO_EE_ORIGIN_ZEROCOPY = 0x5 + SO_EE_RFC4884_FLAG_INVALID = 0x1 SO_GET_FILTER = 0x1a SO_NO_CHECK = 0xb SO_PEERNAME = 0x1c @@ -2357,6 +2449,23 @@ const ( WCONTINUED = 0x8 WDIOC_SETPRETIMEOUT = 0xc0045708 WDIOC_SETTIMEOUT = 0xc0045706 + WDIOF_ALARMONLY = 0x400 + WDIOF_CARDRESET = 0x20 + WDIOF_EXTERN1 = 0x4 + WDIOF_EXTERN2 = 0x8 + WDIOF_FANFAULT = 0x2 + WDIOF_KEEPALIVEPING = 0x8000 + WDIOF_MAGICCLOSE = 0x100 + WDIOF_OVERHEAT = 0x1 + WDIOF_POWEROVER = 0x40 + WDIOF_POWERUNDER = 0x10 + WDIOF_PRETIMEOUT = 0x200 + WDIOF_SETTIMEOUT = 0x80 + WDIOF_UNKNOWN = -0x1 + WDIOS_DISABLECARD = 0x1 + WDIOS_ENABLECARD = 0x2 + WDIOS_TEMPPANIC = 0x4 + WDIOS_UNKNOWN = -0x1 WEXITED = 0x4 WIN_ACKMEDIACHANGE = 0xdb WIN_CHECKPOWERMODE1 = 0xe5 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go index 46e054ccb0e..5312c36cc82 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_solaris_amd64.go @@ -192,6 +192,12 @@ const ( CSTOPB = 0x40 CSUSP = 0x1a CSWTCH = 0x1a + DIOC = 0x6400 + DIOCGETB = 0x6402 + DIOCGETC = 0x6401 + DIOCGETP = 0x6408 + DIOCSETE = 0x6403 + DIOCSETP = 0x6409 DLT_AIRONET_HEADER = 0x78 DLT_APPLE_IP_OVER_IEEE1394 = 0x8a DLT_ARCNET = 0x7 @@ -290,6 +296,7 @@ const ( FF0 = 0x0 FF1 = 0x8000 FFDLY = 0x8000 + FIORDCHK = 0x6603 FLUSHALL = 0x1 FLUSHDATA = 0x0 FLUSHO = 0x2000 @@ -645,6 +652,14 @@ const ( MAP_SHARED = 0x1 MAP_TEXT = 0x400 MAP_TYPE = 0xf + MCAST_BLOCK_SOURCE = 0x2b + MCAST_EXCLUDE = 0x2 + MCAST_INCLUDE = 0x1 + MCAST_JOIN_GROUP = 0x29 + MCAST_JOIN_SOURCE_GROUP = 0x2d + MCAST_LEAVE_GROUP = 0x2a + MCAST_LEAVE_SOURCE_GROUP = 0x2e + MCAST_UNBLOCK_SOURCE = 0x2c MCL_CURRENT = 0x1 MCL_FUTURE = 0x2 MSG_CTRUNC = 0x10 @@ -653,6 +668,7 @@ const ( MSG_DUPCTRL = 0x800 MSG_EOR = 0x8 MSG_MAXIOVLEN = 0x10 + MSG_NOSIGNAL = 0x200 MSG_NOTIFICATION = 0x100 MSG_OOB = 0x1 MSG_PEEK = 0x2 @@ -687,6 +703,7 @@ const ( O_APPEND = 0x8 O_CLOEXEC = 0x800000 O_CREAT = 0x100 + O_DIRECTORY = 0x1000000 O_DSYNC = 0x40 O_EXCL = 0x400 O_EXEC = 0x400000 @@ -725,7 +742,7 @@ const ( RLIMIT_FSIZE = 0x1 RLIMIT_NOFILE = 0x5 RLIMIT_STACK = 0x3 - RLIM_INFINITY = -0x3 + RLIM_INFINITY = 0xfffffffffffffffd RTAX_AUTHOR = 0x6 RTAX_BRD = 0x7 RTAX_DST = 0x0 @@ -1047,6 +1064,7 @@ const ( TCOON = 0x1 TCP_ABORT_THRESHOLD = 0x11 TCP_ANONPRIVBIND = 0x20 + TCP_CONGESTION = 0x25 TCP_CONN_ABORT_THRESHOLD = 0x13 TCP_CONN_NOTIFY_THRESHOLD = 0x12 TCP_CORK = 0x18 @@ -1076,6 +1094,8 @@ const ( TCSETSF = 0x5410 TCSETSW = 0x540f TCXONC = 0x5406 + TIMER_ABSTIME = 0x1 + TIMER_RELTIME = 0x0 TIOC = 0x5400 TIOCCBRK = 0x747a TIOCCDTR = 0x7478 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go index 3976147201c..6eb45798323 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go @@ -490,21 +490,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getattrlist_trampoline() - -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe() (r int, w int, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) r = int(r0) @@ -1277,6 +1262,28 @@ func libc_ftruncate_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_getcwd_trampoline() + +//go:linkname libc_getcwd libc_getcwd +//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdtablesize() (size int) { r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) size = int(r0) @@ -2427,21 +2434,6 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { @@ -2528,6 +2520,21 @@ func libc_lstat64_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_ptrace_trampoline() + +//go:linkname libc_ptrace libc_ptrace +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Stat(path string, stat *Stat_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s index 961058db86e..1c53979a101 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s @@ -60,8 +60,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 @@ -146,6 +144,8 @@ TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 JMP libc_fsync(SB) TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 JMP libc_ftruncate(SB) +TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 JMP libc_getdtablesize(SB) TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 @@ -272,8 +272,6 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_fstat64(SB) TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0 @@ -284,6 +282,8 @@ TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_getfsstat64(SB) TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_lstat64(SB) +TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) TEXT ·libc_stat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_stat64(SB) TEXT ·libc_statfs64_trampoline(SB),NOSPLIT,$0-0 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index e253f438721..889c14059e9 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -490,21 +490,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getattrlist_trampoline() - -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe() (r int, w int, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) r = int(r0) @@ -1277,6 +1262,28 @@ func libc_ftruncate_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_getcwd_trampoline() + +//go:linkname libc_getcwd libc_getcwd +//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdtablesize() (size int) { r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) size = int(r0) @@ -2427,21 +2434,6 @@ func writelen(fd int, buf *byte, nbuf int) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_ptrace_trampoline() - -//go:linkname libc_ptrace libc_ptrace -//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := syscall_syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { @@ -2528,6 +2520,21 @@ func libc_lstat64_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_ptrace_trampoline() + +//go:linkname libc_ptrace libc_ptrace +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Stat(path string, stat *Stat_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index b8be24c6bb6..c77bd6e20bd 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -60,8 +60,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 @@ -146,6 +144,8 @@ TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 JMP libc_fsync(SB) TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 JMP libc_ftruncate(SB) +TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 JMP libc_getdtablesize(SB) TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 @@ -272,8 +272,6 @@ TEXT ·libc_mmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_mmap(SB) TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0 JMP libc_munmap(SB) -TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 - JMP libc_ptrace(SB) TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_fstat64(SB) TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0 @@ -284,6 +282,8 @@ TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_getfsstat64(SB) TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_lstat64(SB) +TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) TEXT ·libc_stat64_trampoline(SB),NOSPLIT,$0-0 JMP libc_stat64(SB) TEXT ·libc_statfs64_trampoline(SB),NOSPLIT,$0-0 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go index be2e28311d2..d6b5249c2f2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.go @@ -490,21 +490,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getattrlist_trampoline() - -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe() (r int, w int, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) r = int(r0) @@ -1277,6 +1262,28 @@ func libc_ftruncate_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_getcwd_trampoline() + +//go:linkname libc_getcwd libc_getcwd +//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdtablesize() (size int) { r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) size = int(r0) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s index 403c21f06b4..5eec5f1d953 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm.s @@ -60,8 +60,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 @@ -146,6 +144,8 @@ TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 JMP libc_fsync(SB) TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 JMP libc_ftruncate(SB) +TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 JMP libc_getdtablesize(SB) TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 34976a4c222..23b65a5301a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -490,21 +490,6 @@ func libc_munlockall_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error) { - _, _, e1 := syscall_syscall6(funcPC(libc_getattrlist_trampoline), uintptr(unsafe.Pointer(path)), uintptr(list), uintptr(buf), uintptr(size), uintptr(options), 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -func libc_getattrlist_trampoline() - -//go:linkname libc_getattrlist libc_getattrlist -//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func pipe() (r int, w int, err error) { r0, r1, e1 := syscall_rawSyscall(funcPC(libc_pipe_trampoline), 0, 0, 0) r = int(r0) @@ -1277,6 +1262,28 @@ func libc_ftruncate_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getcwd(buf []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_getcwd_trampoline() + +//go:linkname libc_getcwd libc_getcwd +//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Getdtablesize() (size int) { r0, _, _ := syscall_syscall(funcPC(libc_getdtablesize_trampoline), 0, 0, 0) size = int(r0) @@ -2513,6 +2520,21 @@ func libc_lstat_trampoline() // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ptrace(request int, pid int, addr uintptr, data uintptr) (err error) { + _, _, e1 := syscall_syscall6(funcPC(libc_ptrace_trampoline), uintptr(request), uintptr(pid), uintptr(addr), uintptr(data), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +func libc_ptrace_trampoline() + +//go:linkname libc_ptrace libc_ptrace +//go:cgo_import_dynamic libc_ptrace ptrace "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Stat(path string, stat *Stat_t) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index abe7b6edf9a..53c402bf68b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -60,8 +60,6 @@ TEXT ·libc_munlock_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlock(SB) TEXT ·libc_munlockall_trampoline(SB),NOSPLIT,$0-0 JMP libc_munlockall(SB) -TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0 - JMP libc_getattrlist(SB) TEXT ·libc_pipe_trampoline(SB),NOSPLIT,$0-0 JMP libc_pipe(SB) TEXT ·libc_getxattr_trampoline(SB),NOSPLIT,$0-0 @@ -146,6 +144,8 @@ TEXT ·libc_fsync_trampoline(SB),NOSPLIT,$0-0 JMP libc_fsync(SB) TEXT ·libc_ftruncate_trampoline(SB),NOSPLIT,$0-0 JMP libc_ftruncate(SB) +TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0 + JMP libc_getcwd(SB) TEXT ·libc_getdtablesize_trampoline(SB),NOSPLIT,$0-0 JMP libc_getdtablesize(SB) TEXT ·libc_getegid_trampoline(SB),NOSPLIT,$0-0 @@ -282,6 +282,8 @@ TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0 JMP libc_getfsstat(SB) TEXT ·libc_lstat_trampoline(SB),NOSPLIT,$0-0 JMP libc_lstat(SB) +TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0 + JMP libc_ptrace(SB) TEXT ·libc_stat_trampoline(SB),NOSPLIT,$0-0 JMP libc_stat(SB) TEXT ·libc_statfs_trampoline(SB),NOSPLIT,$0-0 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index fe1fdd78d70..aebfe511ad5 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -214,22 +214,6 @@ func kevent(kq int, change unsafe.Pointer, nchange int, event unsafe.Pointer, ne // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { - var _p0 unsafe.Pointer - if len(mib) > 0 { - _p0 = unsafe.Pointer(&mib[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func utimes(path string, timeval *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -439,6 +423,22 @@ func ioctl(fd int, req uint, arg uintptr) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, e1 := Syscall6(SYS___SYSCTL, uintptr(_p0), uintptr(len(mib)), uintptr(unsafe.Pointer(old)), uintptr(unsafe.Pointer(oldlen)), uintptr(unsafe.Pointer(new)), uintptr(newlen)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Access(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go new file mode 100644 index 00000000000..ad62324c7c1 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_386.go @@ -0,0 +1,437 @@ +// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include/sys/syscall.h +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build 386,darwin + +package unix + +// Deprecated: Use libSystem wrappers instead of direct syscalls. +const ( + SYS_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAIT4 = 7 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_CHDIR = 12 + SYS_FCHDIR = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_CHOWN = 16 + SYS_GETFSSTAT = 18 + SYS_GETPID = 20 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_GETEUID = 25 + SYS_PTRACE = 26 + SYS_RECVMSG = 27 + SYS_SENDMSG = 28 + SYS_RECVFROM = 29 + SYS_ACCEPT = 30 + SYS_GETPEERNAME = 31 + SYS_GETSOCKNAME = 32 + SYS_ACCESS = 33 + SYS_CHFLAGS = 34 + SYS_FCHFLAGS = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_GETPPID = 39 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_GETEGID = 43 + SYS_SIGACTION = 46 + SYS_GETGID = 47 + SYS_SIGPROCMASK = 48 + SYS_GETLOGIN = 49 + SYS_SETLOGIN = 50 + SYS_ACCT = 51 + SYS_SIGPENDING = 52 + SYS_SIGALTSTACK = 53 + SYS_IOCTL = 54 + SYS_REBOOT = 55 + SYS_REVOKE = 56 + SYS_SYMLINK = 57 + SYS_READLINK = 58 + SYS_EXECVE = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_MSYNC = 65 + SYS_VFORK = 66 + SYS_MUNMAP = 73 + SYS_MPROTECT = 74 + SYS_MADVISE = 75 + SYS_MINCORE = 78 + SYS_GETGROUPS = 79 + SYS_SETGROUPS = 80 + SYS_GETPGRP = 81 + SYS_SETPGID = 82 + SYS_SETITIMER = 83 + SYS_SWAPON = 85 + SYS_GETITIMER = 86 + SYS_GETDTABLESIZE = 89 + SYS_DUP2 = 90 + SYS_FCNTL = 92 + SYS_SELECT = 93 + SYS_FSYNC = 95 + SYS_SETPRIORITY = 96 + SYS_SOCKET = 97 + SYS_CONNECT = 98 + SYS_GETPRIORITY = 100 + SYS_BIND = 104 + SYS_SETSOCKOPT = 105 + SYS_LISTEN = 106 + SYS_SIGSUSPEND = 111 + SYS_GETTIMEOFDAY = 116 + SYS_GETRUSAGE = 117 + SYS_GETSOCKOPT = 118 + SYS_READV = 120 + SYS_WRITEV = 121 + SYS_SETTIMEOFDAY = 122 + SYS_FCHOWN = 123 + SYS_FCHMOD = 124 + SYS_SETREUID = 126 + SYS_SETREGID = 127 + SYS_RENAME = 128 + SYS_FLOCK = 131 + SYS_MKFIFO = 132 + SYS_SENDTO = 133 + SYS_SHUTDOWN = 134 + SYS_SOCKETPAIR = 135 + SYS_MKDIR = 136 + SYS_RMDIR = 137 + SYS_UTIMES = 138 + SYS_FUTIMES = 139 + SYS_ADJTIME = 140 + SYS_GETHOSTUUID = 142 + SYS_SETSID = 147 + SYS_GETPGID = 151 + SYS_SETPRIVEXEC = 152 + SYS_PREAD = 153 + SYS_PWRITE = 154 + SYS_NFSSVC = 155 + SYS_STATFS = 157 + SYS_FSTATFS = 158 + SYS_UNMOUNT = 159 + SYS_GETFH = 161 + SYS_QUOTACTL = 165 + SYS_MOUNT = 167 + SYS_CSOPS = 169 + SYS_CSOPS_AUDITTOKEN = 170 + SYS_WAITID = 173 + SYS_KDEBUG_TYPEFILTER = 177 + SYS_KDEBUG_TRACE_STRING = 178 + SYS_KDEBUG_TRACE64 = 179 + SYS_KDEBUG_TRACE = 180 + SYS_SETGID = 181 + SYS_SETEGID = 182 + SYS_SETEUID = 183 + SYS_SIGRETURN = 184 + SYS_THREAD_SELFCOUNTS = 186 + SYS_FDATASYNC = 187 + SYS_STAT = 188 + SYS_FSTAT = 189 + SYS_LSTAT = 190 + SYS_PATHCONF = 191 + SYS_FPATHCONF = 192 + SYS_GETRLIMIT = 194 + SYS_SETRLIMIT = 195 + SYS_GETDIRENTRIES = 196 + SYS_MMAP = 197 + SYS_LSEEK = 199 + SYS_TRUNCATE = 200 + SYS_FTRUNCATE = 201 + SYS_SYSCTL = 202 + SYS_MLOCK = 203 + SYS_MUNLOCK = 204 + SYS_UNDELETE = 205 + SYS_OPEN_DPROTECTED_NP = 216 + SYS_GETATTRLIST = 220 + SYS_SETATTRLIST = 221 + SYS_GETDIRENTRIESATTR = 222 + SYS_EXCHANGEDATA = 223 + SYS_SEARCHFS = 225 + SYS_DELETE = 226 + SYS_COPYFILE = 227 + SYS_FGETATTRLIST = 228 + SYS_FSETATTRLIST = 229 + SYS_POLL = 230 + SYS_WATCHEVENT = 231 + SYS_WAITEVENT = 232 + SYS_MODWATCH = 233 + SYS_GETXATTR = 234 + SYS_FGETXATTR = 235 + SYS_SETXATTR = 236 + SYS_FSETXATTR = 237 + SYS_REMOVEXATTR = 238 + SYS_FREMOVEXATTR = 239 + SYS_LISTXATTR = 240 + SYS_FLISTXATTR = 241 + SYS_FSCTL = 242 + SYS_INITGROUPS = 243 + SYS_POSIX_SPAWN = 244 + SYS_FFSCTL = 245 + SYS_NFSCLNT = 247 + SYS_FHOPEN = 248 + SYS_MINHERIT = 250 + SYS_SEMSYS = 251 + SYS_MSGSYS = 252 + SYS_SHMSYS = 253 + SYS_SEMCTL = 254 + SYS_SEMGET = 255 + SYS_SEMOP = 256 + SYS_MSGCTL = 258 + SYS_MSGGET = 259 + SYS_MSGSND = 260 + SYS_MSGRCV = 261 + SYS_SHMAT = 262 + SYS_SHMCTL = 263 + SYS_SHMDT = 264 + SYS_SHMGET = 265 + SYS_SHM_OPEN = 266 + SYS_SHM_UNLINK = 267 + SYS_SEM_OPEN = 268 + SYS_SEM_CLOSE = 269 + SYS_SEM_UNLINK = 270 + SYS_SEM_WAIT = 271 + SYS_SEM_TRYWAIT = 272 + SYS_SEM_POST = 273 + SYS_SYSCTLBYNAME = 274 + SYS_OPEN_EXTENDED = 277 + SYS_UMASK_EXTENDED = 278 + SYS_STAT_EXTENDED = 279 + SYS_LSTAT_EXTENDED = 280 + SYS_FSTAT_EXTENDED = 281 + SYS_CHMOD_EXTENDED = 282 + SYS_FCHMOD_EXTENDED = 283 + SYS_ACCESS_EXTENDED = 284 + SYS_SETTID = 285 + SYS_GETTID = 286 + SYS_SETSGROUPS = 287 + SYS_GETSGROUPS = 288 + SYS_SETWGROUPS = 289 + SYS_GETWGROUPS = 290 + SYS_MKFIFO_EXTENDED = 291 + SYS_MKDIR_EXTENDED = 292 + SYS_IDENTITYSVC = 293 + SYS_SHARED_REGION_CHECK_NP = 294 + SYS_VM_PRESSURE_MONITOR = 296 + SYS_PSYNCH_RW_LONGRDLOCK = 297 + SYS_PSYNCH_RW_YIELDWRLOCK = 298 + SYS_PSYNCH_RW_DOWNGRADE = 299 + SYS_PSYNCH_RW_UPGRADE = 300 + SYS_PSYNCH_MUTEXWAIT = 301 + SYS_PSYNCH_MUTEXDROP = 302 + SYS_PSYNCH_CVBROAD = 303 + SYS_PSYNCH_CVSIGNAL = 304 + SYS_PSYNCH_CVWAIT = 305 + SYS_PSYNCH_RW_RDLOCK = 306 + SYS_PSYNCH_RW_WRLOCK = 307 + SYS_PSYNCH_RW_UNLOCK = 308 + SYS_PSYNCH_RW_UNLOCK2 = 309 + SYS_GETSID = 310 + SYS_SETTID_WITH_PID = 311 + SYS_PSYNCH_CVCLRPREPOST = 312 + SYS_AIO_FSYNC = 313 + SYS_AIO_RETURN = 314 + SYS_AIO_SUSPEND = 315 + SYS_AIO_CANCEL = 316 + SYS_AIO_ERROR = 317 + SYS_AIO_READ = 318 + SYS_AIO_WRITE = 319 + SYS_LIO_LISTIO = 320 + SYS_IOPOLICYSYS = 322 + SYS_PROCESS_POLICY = 323 + SYS_MLOCKALL = 324 + SYS_MUNLOCKALL = 325 + SYS_ISSETUGID = 327 + SYS___PTHREAD_KILL = 328 + SYS___PTHREAD_SIGMASK = 329 + SYS___SIGWAIT = 330 + SYS___DISABLE_THREADSIGNAL = 331 + SYS___PTHREAD_MARKCANCEL = 332 + SYS___PTHREAD_CANCELED = 333 + SYS___SEMWAIT_SIGNAL = 334 + SYS_PROC_INFO = 336 + SYS_SENDFILE = 337 + SYS_STAT64 = 338 + SYS_FSTAT64 = 339 + SYS_LSTAT64 = 340 + SYS_STAT64_EXTENDED = 341 + SYS_LSTAT64_EXTENDED = 342 + SYS_FSTAT64_EXTENDED = 343 + SYS_GETDIRENTRIES64 = 344 + SYS_STATFS64 = 345 + SYS_FSTATFS64 = 346 + SYS_GETFSSTAT64 = 347 + SYS___PTHREAD_CHDIR = 348 + SYS___PTHREAD_FCHDIR = 349 + SYS_AUDIT = 350 + SYS_AUDITON = 351 + SYS_GETAUID = 353 + SYS_SETAUID = 354 + SYS_GETAUDIT_ADDR = 357 + SYS_SETAUDIT_ADDR = 358 + SYS_AUDITCTL = 359 + SYS_BSDTHREAD_CREATE = 360 + SYS_BSDTHREAD_TERMINATE = 361 + SYS_KQUEUE = 362 + SYS_KEVENT = 363 + SYS_LCHOWN = 364 + SYS_BSDTHREAD_REGISTER = 366 + SYS_WORKQ_OPEN = 367 + SYS_WORKQ_KERNRETURN = 368 + SYS_KEVENT64 = 369 + SYS___OLD_SEMWAIT_SIGNAL = 370 + SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 + SYS_THREAD_SELFID = 372 + SYS_LEDGER = 373 + SYS_KEVENT_QOS = 374 + SYS_KEVENT_ID = 375 + SYS___MAC_EXECVE = 380 + SYS___MAC_SYSCALL = 381 + SYS___MAC_GET_FILE = 382 + SYS___MAC_SET_FILE = 383 + SYS___MAC_GET_LINK = 384 + SYS___MAC_SET_LINK = 385 + SYS___MAC_GET_PROC = 386 + SYS___MAC_SET_PROC = 387 + SYS___MAC_GET_FD = 388 + SYS___MAC_SET_FD = 389 + SYS___MAC_GET_PID = 390 + SYS_PSELECT = 394 + SYS_PSELECT_NOCANCEL = 395 + SYS_READ_NOCANCEL = 396 + SYS_WRITE_NOCANCEL = 397 + SYS_OPEN_NOCANCEL = 398 + SYS_CLOSE_NOCANCEL = 399 + SYS_WAIT4_NOCANCEL = 400 + SYS_RECVMSG_NOCANCEL = 401 + SYS_SENDMSG_NOCANCEL = 402 + SYS_RECVFROM_NOCANCEL = 403 + SYS_ACCEPT_NOCANCEL = 404 + SYS_MSYNC_NOCANCEL = 405 + SYS_FCNTL_NOCANCEL = 406 + SYS_SELECT_NOCANCEL = 407 + SYS_FSYNC_NOCANCEL = 408 + SYS_CONNECT_NOCANCEL = 409 + SYS_SIGSUSPEND_NOCANCEL = 410 + SYS_READV_NOCANCEL = 411 + SYS_WRITEV_NOCANCEL = 412 + SYS_SENDTO_NOCANCEL = 413 + SYS_PREAD_NOCANCEL = 414 + SYS_PWRITE_NOCANCEL = 415 + SYS_WAITID_NOCANCEL = 416 + SYS_POLL_NOCANCEL = 417 + SYS_MSGSND_NOCANCEL = 418 + SYS_MSGRCV_NOCANCEL = 419 + SYS_SEM_WAIT_NOCANCEL = 420 + SYS_AIO_SUSPEND_NOCANCEL = 421 + SYS___SIGWAIT_NOCANCEL = 422 + SYS___SEMWAIT_SIGNAL_NOCANCEL = 423 + SYS___MAC_MOUNT = 424 + SYS___MAC_GET_MOUNT = 425 + SYS___MAC_GETFSSTAT = 426 + SYS_FSGETPATH = 427 + SYS_AUDIT_SESSION_SELF = 428 + SYS_AUDIT_SESSION_JOIN = 429 + SYS_FILEPORT_MAKEPORT = 430 + SYS_FILEPORT_MAKEFD = 431 + SYS_AUDIT_SESSION_PORT = 432 + SYS_PID_SUSPEND = 433 + SYS_PID_RESUME = 434 + SYS_PID_HIBERNATE = 435 + SYS_PID_SHUTDOWN_SOCKETS = 436 + SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438 + SYS_KAS_INFO = 439 + SYS_MEMORYSTATUS_CONTROL = 440 + SYS_GUARDED_OPEN_NP = 441 + SYS_GUARDED_CLOSE_NP = 442 + SYS_GUARDED_KQUEUE_NP = 443 + SYS_CHANGE_FDGUARD_NP = 444 + SYS_USRCTL = 445 + SYS_PROC_RLIMIT_CONTROL = 446 + SYS_CONNECTX = 447 + SYS_DISCONNECTX = 448 + SYS_PEELOFF = 449 + SYS_SOCKET_DELEGATE = 450 + SYS_TELEMETRY = 451 + SYS_PROC_UUID_POLICY = 452 + SYS_MEMORYSTATUS_GET_LEVEL = 453 + SYS_SYSTEM_OVERRIDE = 454 + SYS_VFS_PURGE = 455 + SYS_SFI_CTL = 456 + SYS_SFI_PIDCTL = 457 + SYS_COALITION = 458 + SYS_COALITION_INFO = 459 + SYS_NECP_MATCH_POLICY = 460 + SYS_GETATTRLISTBULK = 461 + SYS_CLONEFILEAT = 462 + SYS_OPENAT = 463 + SYS_OPENAT_NOCANCEL = 464 + SYS_RENAMEAT = 465 + SYS_FACCESSAT = 466 + SYS_FCHMODAT = 467 + SYS_FCHOWNAT = 468 + SYS_FSTATAT = 469 + SYS_FSTATAT64 = 470 + SYS_LINKAT = 471 + SYS_UNLINKAT = 472 + SYS_READLINKAT = 473 + SYS_SYMLINKAT = 474 + SYS_MKDIRAT = 475 + SYS_GETATTRLISTAT = 476 + SYS_PROC_TRACE_LOG = 477 + SYS_BSDTHREAD_CTL = 478 + SYS_OPENBYID_NP = 479 + SYS_RECVMSG_X = 480 + SYS_SENDMSG_X = 481 + SYS_THREAD_SELFUSAGE = 482 + SYS_CSRCTL = 483 + SYS_GUARDED_OPEN_DPROTECTED_NP = 484 + SYS_GUARDED_WRITE_NP = 485 + SYS_GUARDED_PWRITE_NP = 486 + SYS_GUARDED_WRITEV_NP = 487 + SYS_RENAMEATX_NP = 488 + SYS_MREMAP_ENCRYPTED = 489 + SYS_NETAGENT_TRIGGER = 490 + SYS_STACK_SNAPSHOT_WITH_CONFIG = 491 + SYS_MICROSTACKSHOT = 492 + SYS_GRAB_PGO_DATA = 493 + SYS_PERSONA = 494 + SYS_WORK_INTERVAL_CTL = 499 + SYS_GETENTROPY = 500 + SYS_NECP_OPEN = 501 + SYS_NECP_CLIENT_ACTION = 502 + SYS___NEXUS_OPEN = 503 + SYS___NEXUS_REGISTER = 504 + SYS___NEXUS_DEREGISTER = 505 + SYS___NEXUS_CREATE = 506 + SYS___NEXUS_DESTROY = 507 + SYS___NEXUS_GET_OPT = 508 + SYS___NEXUS_SET_OPT = 509 + SYS___CHANNEL_OPEN = 510 + SYS___CHANNEL_GET_INFO = 511 + SYS___CHANNEL_SYNC = 512 + SYS___CHANNEL_GET_OPT = 513 + SYS___CHANNEL_SET_OPT = 514 + SYS_ULOCK_WAIT = 515 + SYS_ULOCK_WAKE = 516 + SYS_FCLONEFILEAT = 517 + SYS_FS_SNAPSHOT = 518 + SYS_TERMINATE_WITH_PAYLOAD = 520 + SYS_ABORT_WITH_PAYLOAD = 521 + SYS_NECP_SESSION_OPEN = 522 + SYS_NECP_SESSION_ACTION = 523 + SYS_SETATTRLISTAT = 524 + SYS_NET_QOS_GUIDELINE = 525 + SYS_FMOUNT = 526 + SYS_NTP_ADJTIME = 527 + SYS_NTP_GETTIME = 528 + SYS_OS_FAULT_WITH_PAYLOAD = 529 + SYS_MAXSYSCALL = 530 + SYS_INVALID = 63 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go new file mode 100644 index 00000000000..a2fc91d6a80 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_amd64.go @@ -0,0 +1,439 @@ +// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/sys/syscall.h +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build amd64,darwin + +package unix + +// Deprecated: Use libSystem wrappers instead of direct syscalls. +const ( + SYS_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAIT4 = 7 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_CHDIR = 12 + SYS_FCHDIR = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_CHOWN = 16 + SYS_GETFSSTAT = 18 + SYS_GETPID = 20 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_GETEUID = 25 + SYS_PTRACE = 26 + SYS_RECVMSG = 27 + SYS_SENDMSG = 28 + SYS_RECVFROM = 29 + SYS_ACCEPT = 30 + SYS_GETPEERNAME = 31 + SYS_GETSOCKNAME = 32 + SYS_ACCESS = 33 + SYS_CHFLAGS = 34 + SYS_FCHFLAGS = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_GETPPID = 39 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_GETEGID = 43 + SYS_SIGACTION = 46 + SYS_GETGID = 47 + SYS_SIGPROCMASK = 48 + SYS_GETLOGIN = 49 + SYS_SETLOGIN = 50 + SYS_ACCT = 51 + SYS_SIGPENDING = 52 + SYS_SIGALTSTACK = 53 + SYS_IOCTL = 54 + SYS_REBOOT = 55 + SYS_REVOKE = 56 + SYS_SYMLINK = 57 + SYS_READLINK = 58 + SYS_EXECVE = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_MSYNC = 65 + SYS_VFORK = 66 + SYS_MUNMAP = 73 + SYS_MPROTECT = 74 + SYS_MADVISE = 75 + SYS_MINCORE = 78 + SYS_GETGROUPS = 79 + SYS_SETGROUPS = 80 + SYS_GETPGRP = 81 + SYS_SETPGID = 82 + SYS_SETITIMER = 83 + SYS_SWAPON = 85 + SYS_GETITIMER = 86 + SYS_GETDTABLESIZE = 89 + SYS_DUP2 = 90 + SYS_FCNTL = 92 + SYS_SELECT = 93 + SYS_FSYNC = 95 + SYS_SETPRIORITY = 96 + SYS_SOCKET = 97 + SYS_CONNECT = 98 + SYS_GETPRIORITY = 100 + SYS_BIND = 104 + SYS_SETSOCKOPT = 105 + SYS_LISTEN = 106 + SYS_SIGSUSPEND = 111 + SYS_GETTIMEOFDAY = 116 + SYS_GETRUSAGE = 117 + SYS_GETSOCKOPT = 118 + SYS_READV = 120 + SYS_WRITEV = 121 + SYS_SETTIMEOFDAY = 122 + SYS_FCHOWN = 123 + SYS_FCHMOD = 124 + SYS_SETREUID = 126 + SYS_SETREGID = 127 + SYS_RENAME = 128 + SYS_FLOCK = 131 + SYS_MKFIFO = 132 + SYS_SENDTO = 133 + SYS_SHUTDOWN = 134 + SYS_SOCKETPAIR = 135 + SYS_MKDIR = 136 + SYS_RMDIR = 137 + SYS_UTIMES = 138 + SYS_FUTIMES = 139 + SYS_ADJTIME = 140 + SYS_GETHOSTUUID = 142 + SYS_SETSID = 147 + SYS_GETPGID = 151 + SYS_SETPRIVEXEC = 152 + SYS_PREAD = 153 + SYS_PWRITE = 154 + SYS_NFSSVC = 155 + SYS_STATFS = 157 + SYS_FSTATFS = 158 + SYS_UNMOUNT = 159 + SYS_GETFH = 161 + SYS_QUOTACTL = 165 + SYS_MOUNT = 167 + SYS_CSOPS = 169 + SYS_CSOPS_AUDITTOKEN = 170 + SYS_WAITID = 173 + SYS_KDEBUG_TYPEFILTER = 177 + SYS_KDEBUG_TRACE_STRING = 178 + SYS_KDEBUG_TRACE64 = 179 + SYS_KDEBUG_TRACE = 180 + SYS_SETGID = 181 + SYS_SETEGID = 182 + SYS_SETEUID = 183 + SYS_SIGRETURN = 184 + SYS_THREAD_SELFCOUNTS = 186 + SYS_FDATASYNC = 187 + SYS_STAT = 188 + SYS_FSTAT = 189 + SYS_LSTAT = 190 + SYS_PATHCONF = 191 + SYS_FPATHCONF = 192 + SYS_GETRLIMIT = 194 + SYS_SETRLIMIT = 195 + SYS_GETDIRENTRIES = 196 + SYS_MMAP = 197 + SYS_LSEEK = 199 + SYS_TRUNCATE = 200 + SYS_FTRUNCATE = 201 + SYS_SYSCTL = 202 + SYS_MLOCK = 203 + SYS_MUNLOCK = 204 + SYS_UNDELETE = 205 + SYS_OPEN_DPROTECTED_NP = 216 + SYS_GETATTRLIST = 220 + SYS_SETATTRLIST = 221 + SYS_GETDIRENTRIESATTR = 222 + SYS_EXCHANGEDATA = 223 + SYS_SEARCHFS = 225 + SYS_DELETE = 226 + SYS_COPYFILE = 227 + SYS_FGETATTRLIST = 228 + SYS_FSETATTRLIST = 229 + SYS_POLL = 230 + SYS_WATCHEVENT = 231 + SYS_WAITEVENT = 232 + SYS_MODWATCH = 233 + SYS_GETXATTR = 234 + SYS_FGETXATTR = 235 + SYS_SETXATTR = 236 + SYS_FSETXATTR = 237 + SYS_REMOVEXATTR = 238 + SYS_FREMOVEXATTR = 239 + SYS_LISTXATTR = 240 + SYS_FLISTXATTR = 241 + SYS_FSCTL = 242 + SYS_INITGROUPS = 243 + SYS_POSIX_SPAWN = 244 + SYS_FFSCTL = 245 + SYS_NFSCLNT = 247 + SYS_FHOPEN = 248 + SYS_MINHERIT = 250 + SYS_SEMSYS = 251 + SYS_MSGSYS = 252 + SYS_SHMSYS = 253 + SYS_SEMCTL = 254 + SYS_SEMGET = 255 + SYS_SEMOP = 256 + SYS_MSGCTL = 258 + SYS_MSGGET = 259 + SYS_MSGSND = 260 + SYS_MSGRCV = 261 + SYS_SHMAT = 262 + SYS_SHMCTL = 263 + SYS_SHMDT = 264 + SYS_SHMGET = 265 + SYS_SHM_OPEN = 266 + SYS_SHM_UNLINK = 267 + SYS_SEM_OPEN = 268 + SYS_SEM_CLOSE = 269 + SYS_SEM_UNLINK = 270 + SYS_SEM_WAIT = 271 + SYS_SEM_TRYWAIT = 272 + SYS_SEM_POST = 273 + SYS_SYSCTLBYNAME = 274 + SYS_OPEN_EXTENDED = 277 + SYS_UMASK_EXTENDED = 278 + SYS_STAT_EXTENDED = 279 + SYS_LSTAT_EXTENDED = 280 + SYS_FSTAT_EXTENDED = 281 + SYS_CHMOD_EXTENDED = 282 + SYS_FCHMOD_EXTENDED = 283 + SYS_ACCESS_EXTENDED = 284 + SYS_SETTID = 285 + SYS_GETTID = 286 + SYS_SETSGROUPS = 287 + SYS_GETSGROUPS = 288 + SYS_SETWGROUPS = 289 + SYS_GETWGROUPS = 290 + SYS_MKFIFO_EXTENDED = 291 + SYS_MKDIR_EXTENDED = 292 + SYS_IDENTITYSVC = 293 + SYS_SHARED_REGION_CHECK_NP = 294 + SYS_VM_PRESSURE_MONITOR = 296 + SYS_PSYNCH_RW_LONGRDLOCK = 297 + SYS_PSYNCH_RW_YIELDWRLOCK = 298 + SYS_PSYNCH_RW_DOWNGRADE = 299 + SYS_PSYNCH_RW_UPGRADE = 300 + SYS_PSYNCH_MUTEXWAIT = 301 + SYS_PSYNCH_MUTEXDROP = 302 + SYS_PSYNCH_CVBROAD = 303 + SYS_PSYNCH_CVSIGNAL = 304 + SYS_PSYNCH_CVWAIT = 305 + SYS_PSYNCH_RW_RDLOCK = 306 + SYS_PSYNCH_RW_WRLOCK = 307 + SYS_PSYNCH_RW_UNLOCK = 308 + SYS_PSYNCH_RW_UNLOCK2 = 309 + SYS_GETSID = 310 + SYS_SETTID_WITH_PID = 311 + SYS_PSYNCH_CVCLRPREPOST = 312 + SYS_AIO_FSYNC = 313 + SYS_AIO_RETURN = 314 + SYS_AIO_SUSPEND = 315 + SYS_AIO_CANCEL = 316 + SYS_AIO_ERROR = 317 + SYS_AIO_READ = 318 + SYS_AIO_WRITE = 319 + SYS_LIO_LISTIO = 320 + SYS_IOPOLICYSYS = 322 + SYS_PROCESS_POLICY = 323 + SYS_MLOCKALL = 324 + SYS_MUNLOCKALL = 325 + SYS_ISSETUGID = 327 + SYS___PTHREAD_KILL = 328 + SYS___PTHREAD_SIGMASK = 329 + SYS___SIGWAIT = 330 + SYS___DISABLE_THREADSIGNAL = 331 + SYS___PTHREAD_MARKCANCEL = 332 + SYS___PTHREAD_CANCELED = 333 + SYS___SEMWAIT_SIGNAL = 334 + SYS_PROC_INFO = 336 + SYS_SENDFILE = 337 + SYS_STAT64 = 338 + SYS_FSTAT64 = 339 + SYS_LSTAT64 = 340 + SYS_STAT64_EXTENDED = 341 + SYS_LSTAT64_EXTENDED = 342 + SYS_FSTAT64_EXTENDED = 343 + SYS_GETDIRENTRIES64 = 344 + SYS_STATFS64 = 345 + SYS_FSTATFS64 = 346 + SYS_GETFSSTAT64 = 347 + SYS___PTHREAD_CHDIR = 348 + SYS___PTHREAD_FCHDIR = 349 + SYS_AUDIT = 350 + SYS_AUDITON = 351 + SYS_GETAUID = 353 + SYS_SETAUID = 354 + SYS_GETAUDIT_ADDR = 357 + SYS_SETAUDIT_ADDR = 358 + SYS_AUDITCTL = 359 + SYS_BSDTHREAD_CREATE = 360 + SYS_BSDTHREAD_TERMINATE = 361 + SYS_KQUEUE = 362 + SYS_KEVENT = 363 + SYS_LCHOWN = 364 + SYS_BSDTHREAD_REGISTER = 366 + SYS_WORKQ_OPEN = 367 + SYS_WORKQ_KERNRETURN = 368 + SYS_KEVENT64 = 369 + SYS___OLD_SEMWAIT_SIGNAL = 370 + SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 + SYS_THREAD_SELFID = 372 + SYS_LEDGER = 373 + SYS_KEVENT_QOS = 374 + SYS_KEVENT_ID = 375 + SYS___MAC_EXECVE = 380 + SYS___MAC_SYSCALL = 381 + SYS___MAC_GET_FILE = 382 + SYS___MAC_SET_FILE = 383 + SYS___MAC_GET_LINK = 384 + SYS___MAC_SET_LINK = 385 + SYS___MAC_GET_PROC = 386 + SYS___MAC_SET_PROC = 387 + SYS___MAC_GET_FD = 388 + SYS___MAC_SET_FD = 389 + SYS___MAC_GET_PID = 390 + SYS_PSELECT = 394 + SYS_PSELECT_NOCANCEL = 395 + SYS_READ_NOCANCEL = 396 + SYS_WRITE_NOCANCEL = 397 + SYS_OPEN_NOCANCEL = 398 + SYS_CLOSE_NOCANCEL = 399 + SYS_WAIT4_NOCANCEL = 400 + SYS_RECVMSG_NOCANCEL = 401 + SYS_SENDMSG_NOCANCEL = 402 + SYS_RECVFROM_NOCANCEL = 403 + SYS_ACCEPT_NOCANCEL = 404 + SYS_MSYNC_NOCANCEL = 405 + SYS_FCNTL_NOCANCEL = 406 + SYS_SELECT_NOCANCEL = 407 + SYS_FSYNC_NOCANCEL = 408 + SYS_CONNECT_NOCANCEL = 409 + SYS_SIGSUSPEND_NOCANCEL = 410 + SYS_READV_NOCANCEL = 411 + SYS_WRITEV_NOCANCEL = 412 + SYS_SENDTO_NOCANCEL = 413 + SYS_PREAD_NOCANCEL = 414 + SYS_PWRITE_NOCANCEL = 415 + SYS_WAITID_NOCANCEL = 416 + SYS_POLL_NOCANCEL = 417 + SYS_MSGSND_NOCANCEL = 418 + SYS_MSGRCV_NOCANCEL = 419 + SYS_SEM_WAIT_NOCANCEL = 420 + SYS_AIO_SUSPEND_NOCANCEL = 421 + SYS___SIGWAIT_NOCANCEL = 422 + SYS___SEMWAIT_SIGNAL_NOCANCEL = 423 + SYS___MAC_MOUNT = 424 + SYS___MAC_GET_MOUNT = 425 + SYS___MAC_GETFSSTAT = 426 + SYS_FSGETPATH = 427 + SYS_AUDIT_SESSION_SELF = 428 + SYS_AUDIT_SESSION_JOIN = 429 + SYS_FILEPORT_MAKEPORT = 430 + SYS_FILEPORT_MAKEFD = 431 + SYS_AUDIT_SESSION_PORT = 432 + SYS_PID_SUSPEND = 433 + SYS_PID_RESUME = 434 + SYS_PID_HIBERNATE = 435 + SYS_PID_SHUTDOWN_SOCKETS = 436 + SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438 + SYS_KAS_INFO = 439 + SYS_MEMORYSTATUS_CONTROL = 440 + SYS_GUARDED_OPEN_NP = 441 + SYS_GUARDED_CLOSE_NP = 442 + SYS_GUARDED_KQUEUE_NP = 443 + SYS_CHANGE_FDGUARD_NP = 444 + SYS_USRCTL = 445 + SYS_PROC_RLIMIT_CONTROL = 446 + SYS_CONNECTX = 447 + SYS_DISCONNECTX = 448 + SYS_PEELOFF = 449 + SYS_SOCKET_DELEGATE = 450 + SYS_TELEMETRY = 451 + SYS_PROC_UUID_POLICY = 452 + SYS_MEMORYSTATUS_GET_LEVEL = 453 + SYS_SYSTEM_OVERRIDE = 454 + SYS_VFS_PURGE = 455 + SYS_SFI_CTL = 456 + SYS_SFI_PIDCTL = 457 + SYS_COALITION = 458 + SYS_COALITION_INFO = 459 + SYS_NECP_MATCH_POLICY = 460 + SYS_GETATTRLISTBULK = 461 + SYS_CLONEFILEAT = 462 + SYS_OPENAT = 463 + SYS_OPENAT_NOCANCEL = 464 + SYS_RENAMEAT = 465 + SYS_FACCESSAT = 466 + SYS_FCHMODAT = 467 + SYS_FCHOWNAT = 468 + SYS_FSTATAT = 469 + SYS_FSTATAT64 = 470 + SYS_LINKAT = 471 + SYS_UNLINKAT = 472 + SYS_READLINKAT = 473 + SYS_SYMLINKAT = 474 + SYS_MKDIRAT = 475 + SYS_GETATTRLISTAT = 476 + SYS_PROC_TRACE_LOG = 477 + SYS_BSDTHREAD_CTL = 478 + SYS_OPENBYID_NP = 479 + SYS_RECVMSG_X = 480 + SYS_SENDMSG_X = 481 + SYS_THREAD_SELFUSAGE = 482 + SYS_CSRCTL = 483 + SYS_GUARDED_OPEN_DPROTECTED_NP = 484 + SYS_GUARDED_WRITE_NP = 485 + SYS_GUARDED_PWRITE_NP = 486 + SYS_GUARDED_WRITEV_NP = 487 + SYS_RENAMEATX_NP = 488 + SYS_MREMAP_ENCRYPTED = 489 + SYS_NETAGENT_TRIGGER = 490 + SYS_STACK_SNAPSHOT_WITH_CONFIG = 491 + SYS_MICROSTACKSHOT = 492 + SYS_GRAB_PGO_DATA = 493 + SYS_PERSONA = 494 + SYS_WORK_INTERVAL_CTL = 499 + SYS_GETENTROPY = 500 + SYS_NECP_OPEN = 501 + SYS_NECP_CLIENT_ACTION = 502 + SYS___NEXUS_OPEN = 503 + SYS___NEXUS_REGISTER = 504 + SYS___NEXUS_DEREGISTER = 505 + SYS___NEXUS_CREATE = 506 + SYS___NEXUS_DESTROY = 507 + SYS___NEXUS_GET_OPT = 508 + SYS___NEXUS_SET_OPT = 509 + SYS___CHANNEL_OPEN = 510 + SYS___CHANNEL_GET_INFO = 511 + SYS___CHANNEL_SYNC = 512 + SYS___CHANNEL_GET_OPT = 513 + SYS___CHANNEL_SET_OPT = 514 + SYS_ULOCK_WAIT = 515 + SYS_ULOCK_WAKE = 516 + SYS_FCLONEFILEAT = 517 + SYS_FS_SNAPSHOT = 518 + SYS_TERMINATE_WITH_PAYLOAD = 520 + SYS_ABORT_WITH_PAYLOAD = 521 + SYS_NECP_SESSION_OPEN = 522 + SYS_NECP_SESSION_ACTION = 523 + SYS_SETATTRLISTAT = 524 + SYS_NET_QOS_GUIDELINE = 525 + SYS_FMOUNT = 526 + SYS_NTP_ADJTIME = 527 + SYS_NTP_GETTIME = 528 + SYS_OS_FAULT_WITH_PAYLOAD = 529 + SYS_KQUEUE_WORKLOOP_CTL = 530 + SYS___MACH_BRIDGE_REMOTE_TIME = 531 + SYS_MAXSYSCALL = 532 + SYS_INVALID = 63 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go new file mode 100644 index 00000000000..20d7808ace3 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm.go @@ -0,0 +1,437 @@ +// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build arm,darwin + +package unix + +// Deprecated: Use libSystem wrappers instead of direct syscalls. +const ( + SYS_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAIT4 = 7 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_CHDIR = 12 + SYS_FCHDIR = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_CHOWN = 16 + SYS_GETFSSTAT = 18 + SYS_GETPID = 20 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_GETEUID = 25 + SYS_PTRACE = 26 + SYS_RECVMSG = 27 + SYS_SENDMSG = 28 + SYS_RECVFROM = 29 + SYS_ACCEPT = 30 + SYS_GETPEERNAME = 31 + SYS_GETSOCKNAME = 32 + SYS_ACCESS = 33 + SYS_CHFLAGS = 34 + SYS_FCHFLAGS = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_GETPPID = 39 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_GETEGID = 43 + SYS_SIGACTION = 46 + SYS_GETGID = 47 + SYS_SIGPROCMASK = 48 + SYS_GETLOGIN = 49 + SYS_SETLOGIN = 50 + SYS_ACCT = 51 + SYS_SIGPENDING = 52 + SYS_SIGALTSTACK = 53 + SYS_IOCTL = 54 + SYS_REBOOT = 55 + SYS_REVOKE = 56 + SYS_SYMLINK = 57 + SYS_READLINK = 58 + SYS_EXECVE = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_MSYNC = 65 + SYS_VFORK = 66 + SYS_MUNMAP = 73 + SYS_MPROTECT = 74 + SYS_MADVISE = 75 + SYS_MINCORE = 78 + SYS_GETGROUPS = 79 + SYS_SETGROUPS = 80 + SYS_GETPGRP = 81 + SYS_SETPGID = 82 + SYS_SETITIMER = 83 + SYS_SWAPON = 85 + SYS_GETITIMER = 86 + SYS_GETDTABLESIZE = 89 + SYS_DUP2 = 90 + SYS_FCNTL = 92 + SYS_SELECT = 93 + SYS_FSYNC = 95 + SYS_SETPRIORITY = 96 + SYS_SOCKET = 97 + SYS_CONNECT = 98 + SYS_GETPRIORITY = 100 + SYS_BIND = 104 + SYS_SETSOCKOPT = 105 + SYS_LISTEN = 106 + SYS_SIGSUSPEND = 111 + SYS_GETTIMEOFDAY = 116 + SYS_GETRUSAGE = 117 + SYS_GETSOCKOPT = 118 + SYS_READV = 120 + SYS_WRITEV = 121 + SYS_SETTIMEOFDAY = 122 + SYS_FCHOWN = 123 + SYS_FCHMOD = 124 + SYS_SETREUID = 126 + SYS_SETREGID = 127 + SYS_RENAME = 128 + SYS_FLOCK = 131 + SYS_MKFIFO = 132 + SYS_SENDTO = 133 + SYS_SHUTDOWN = 134 + SYS_SOCKETPAIR = 135 + SYS_MKDIR = 136 + SYS_RMDIR = 137 + SYS_UTIMES = 138 + SYS_FUTIMES = 139 + SYS_ADJTIME = 140 + SYS_GETHOSTUUID = 142 + SYS_SETSID = 147 + SYS_GETPGID = 151 + SYS_SETPRIVEXEC = 152 + SYS_PREAD = 153 + SYS_PWRITE = 154 + SYS_NFSSVC = 155 + SYS_STATFS = 157 + SYS_FSTATFS = 158 + SYS_UNMOUNT = 159 + SYS_GETFH = 161 + SYS_QUOTACTL = 165 + SYS_MOUNT = 167 + SYS_CSOPS = 169 + SYS_CSOPS_AUDITTOKEN = 170 + SYS_WAITID = 173 + SYS_KDEBUG_TYPEFILTER = 177 + SYS_KDEBUG_TRACE_STRING = 178 + SYS_KDEBUG_TRACE64 = 179 + SYS_KDEBUG_TRACE = 180 + SYS_SETGID = 181 + SYS_SETEGID = 182 + SYS_SETEUID = 183 + SYS_SIGRETURN = 184 + SYS_THREAD_SELFCOUNTS = 186 + SYS_FDATASYNC = 187 + SYS_STAT = 188 + SYS_FSTAT = 189 + SYS_LSTAT = 190 + SYS_PATHCONF = 191 + SYS_FPATHCONF = 192 + SYS_GETRLIMIT = 194 + SYS_SETRLIMIT = 195 + SYS_GETDIRENTRIES = 196 + SYS_MMAP = 197 + SYS_LSEEK = 199 + SYS_TRUNCATE = 200 + SYS_FTRUNCATE = 201 + SYS_SYSCTL = 202 + SYS_MLOCK = 203 + SYS_MUNLOCK = 204 + SYS_UNDELETE = 205 + SYS_OPEN_DPROTECTED_NP = 216 + SYS_GETATTRLIST = 220 + SYS_SETATTRLIST = 221 + SYS_GETDIRENTRIESATTR = 222 + SYS_EXCHANGEDATA = 223 + SYS_SEARCHFS = 225 + SYS_DELETE = 226 + SYS_COPYFILE = 227 + SYS_FGETATTRLIST = 228 + SYS_FSETATTRLIST = 229 + SYS_POLL = 230 + SYS_WATCHEVENT = 231 + SYS_WAITEVENT = 232 + SYS_MODWATCH = 233 + SYS_GETXATTR = 234 + SYS_FGETXATTR = 235 + SYS_SETXATTR = 236 + SYS_FSETXATTR = 237 + SYS_REMOVEXATTR = 238 + SYS_FREMOVEXATTR = 239 + SYS_LISTXATTR = 240 + SYS_FLISTXATTR = 241 + SYS_FSCTL = 242 + SYS_INITGROUPS = 243 + SYS_POSIX_SPAWN = 244 + SYS_FFSCTL = 245 + SYS_NFSCLNT = 247 + SYS_FHOPEN = 248 + SYS_MINHERIT = 250 + SYS_SEMSYS = 251 + SYS_MSGSYS = 252 + SYS_SHMSYS = 253 + SYS_SEMCTL = 254 + SYS_SEMGET = 255 + SYS_SEMOP = 256 + SYS_MSGCTL = 258 + SYS_MSGGET = 259 + SYS_MSGSND = 260 + SYS_MSGRCV = 261 + SYS_SHMAT = 262 + SYS_SHMCTL = 263 + SYS_SHMDT = 264 + SYS_SHMGET = 265 + SYS_SHM_OPEN = 266 + SYS_SHM_UNLINK = 267 + SYS_SEM_OPEN = 268 + SYS_SEM_CLOSE = 269 + SYS_SEM_UNLINK = 270 + SYS_SEM_WAIT = 271 + SYS_SEM_TRYWAIT = 272 + SYS_SEM_POST = 273 + SYS_SYSCTLBYNAME = 274 + SYS_OPEN_EXTENDED = 277 + SYS_UMASK_EXTENDED = 278 + SYS_STAT_EXTENDED = 279 + SYS_LSTAT_EXTENDED = 280 + SYS_FSTAT_EXTENDED = 281 + SYS_CHMOD_EXTENDED = 282 + SYS_FCHMOD_EXTENDED = 283 + SYS_ACCESS_EXTENDED = 284 + SYS_SETTID = 285 + SYS_GETTID = 286 + SYS_SETSGROUPS = 287 + SYS_GETSGROUPS = 288 + SYS_SETWGROUPS = 289 + SYS_GETWGROUPS = 290 + SYS_MKFIFO_EXTENDED = 291 + SYS_MKDIR_EXTENDED = 292 + SYS_IDENTITYSVC = 293 + SYS_SHARED_REGION_CHECK_NP = 294 + SYS_VM_PRESSURE_MONITOR = 296 + SYS_PSYNCH_RW_LONGRDLOCK = 297 + SYS_PSYNCH_RW_YIELDWRLOCK = 298 + SYS_PSYNCH_RW_DOWNGRADE = 299 + SYS_PSYNCH_RW_UPGRADE = 300 + SYS_PSYNCH_MUTEXWAIT = 301 + SYS_PSYNCH_MUTEXDROP = 302 + SYS_PSYNCH_CVBROAD = 303 + SYS_PSYNCH_CVSIGNAL = 304 + SYS_PSYNCH_CVWAIT = 305 + SYS_PSYNCH_RW_RDLOCK = 306 + SYS_PSYNCH_RW_WRLOCK = 307 + SYS_PSYNCH_RW_UNLOCK = 308 + SYS_PSYNCH_RW_UNLOCK2 = 309 + SYS_GETSID = 310 + SYS_SETTID_WITH_PID = 311 + SYS_PSYNCH_CVCLRPREPOST = 312 + SYS_AIO_FSYNC = 313 + SYS_AIO_RETURN = 314 + SYS_AIO_SUSPEND = 315 + SYS_AIO_CANCEL = 316 + SYS_AIO_ERROR = 317 + SYS_AIO_READ = 318 + SYS_AIO_WRITE = 319 + SYS_LIO_LISTIO = 320 + SYS_IOPOLICYSYS = 322 + SYS_PROCESS_POLICY = 323 + SYS_MLOCKALL = 324 + SYS_MUNLOCKALL = 325 + SYS_ISSETUGID = 327 + SYS___PTHREAD_KILL = 328 + SYS___PTHREAD_SIGMASK = 329 + SYS___SIGWAIT = 330 + SYS___DISABLE_THREADSIGNAL = 331 + SYS___PTHREAD_MARKCANCEL = 332 + SYS___PTHREAD_CANCELED = 333 + SYS___SEMWAIT_SIGNAL = 334 + SYS_PROC_INFO = 336 + SYS_SENDFILE = 337 + SYS_STAT64 = 338 + SYS_FSTAT64 = 339 + SYS_LSTAT64 = 340 + SYS_STAT64_EXTENDED = 341 + SYS_LSTAT64_EXTENDED = 342 + SYS_FSTAT64_EXTENDED = 343 + SYS_GETDIRENTRIES64 = 344 + SYS_STATFS64 = 345 + SYS_FSTATFS64 = 346 + SYS_GETFSSTAT64 = 347 + SYS___PTHREAD_CHDIR = 348 + SYS___PTHREAD_FCHDIR = 349 + SYS_AUDIT = 350 + SYS_AUDITON = 351 + SYS_GETAUID = 353 + SYS_SETAUID = 354 + SYS_GETAUDIT_ADDR = 357 + SYS_SETAUDIT_ADDR = 358 + SYS_AUDITCTL = 359 + SYS_BSDTHREAD_CREATE = 360 + SYS_BSDTHREAD_TERMINATE = 361 + SYS_KQUEUE = 362 + SYS_KEVENT = 363 + SYS_LCHOWN = 364 + SYS_BSDTHREAD_REGISTER = 366 + SYS_WORKQ_OPEN = 367 + SYS_WORKQ_KERNRETURN = 368 + SYS_KEVENT64 = 369 + SYS___OLD_SEMWAIT_SIGNAL = 370 + SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 + SYS_THREAD_SELFID = 372 + SYS_LEDGER = 373 + SYS_KEVENT_QOS = 374 + SYS_KEVENT_ID = 375 + SYS___MAC_EXECVE = 380 + SYS___MAC_SYSCALL = 381 + SYS___MAC_GET_FILE = 382 + SYS___MAC_SET_FILE = 383 + SYS___MAC_GET_LINK = 384 + SYS___MAC_SET_LINK = 385 + SYS___MAC_GET_PROC = 386 + SYS___MAC_SET_PROC = 387 + SYS___MAC_GET_FD = 388 + SYS___MAC_SET_FD = 389 + SYS___MAC_GET_PID = 390 + SYS_PSELECT = 394 + SYS_PSELECT_NOCANCEL = 395 + SYS_READ_NOCANCEL = 396 + SYS_WRITE_NOCANCEL = 397 + SYS_OPEN_NOCANCEL = 398 + SYS_CLOSE_NOCANCEL = 399 + SYS_WAIT4_NOCANCEL = 400 + SYS_RECVMSG_NOCANCEL = 401 + SYS_SENDMSG_NOCANCEL = 402 + SYS_RECVFROM_NOCANCEL = 403 + SYS_ACCEPT_NOCANCEL = 404 + SYS_MSYNC_NOCANCEL = 405 + SYS_FCNTL_NOCANCEL = 406 + SYS_SELECT_NOCANCEL = 407 + SYS_FSYNC_NOCANCEL = 408 + SYS_CONNECT_NOCANCEL = 409 + SYS_SIGSUSPEND_NOCANCEL = 410 + SYS_READV_NOCANCEL = 411 + SYS_WRITEV_NOCANCEL = 412 + SYS_SENDTO_NOCANCEL = 413 + SYS_PREAD_NOCANCEL = 414 + SYS_PWRITE_NOCANCEL = 415 + SYS_WAITID_NOCANCEL = 416 + SYS_POLL_NOCANCEL = 417 + SYS_MSGSND_NOCANCEL = 418 + SYS_MSGRCV_NOCANCEL = 419 + SYS_SEM_WAIT_NOCANCEL = 420 + SYS_AIO_SUSPEND_NOCANCEL = 421 + SYS___SIGWAIT_NOCANCEL = 422 + SYS___SEMWAIT_SIGNAL_NOCANCEL = 423 + SYS___MAC_MOUNT = 424 + SYS___MAC_GET_MOUNT = 425 + SYS___MAC_GETFSSTAT = 426 + SYS_FSGETPATH = 427 + SYS_AUDIT_SESSION_SELF = 428 + SYS_AUDIT_SESSION_JOIN = 429 + SYS_FILEPORT_MAKEPORT = 430 + SYS_FILEPORT_MAKEFD = 431 + SYS_AUDIT_SESSION_PORT = 432 + SYS_PID_SUSPEND = 433 + SYS_PID_RESUME = 434 + SYS_PID_HIBERNATE = 435 + SYS_PID_SHUTDOWN_SOCKETS = 436 + SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438 + SYS_KAS_INFO = 439 + SYS_MEMORYSTATUS_CONTROL = 440 + SYS_GUARDED_OPEN_NP = 441 + SYS_GUARDED_CLOSE_NP = 442 + SYS_GUARDED_KQUEUE_NP = 443 + SYS_CHANGE_FDGUARD_NP = 444 + SYS_USRCTL = 445 + SYS_PROC_RLIMIT_CONTROL = 446 + SYS_CONNECTX = 447 + SYS_DISCONNECTX = 448 + SYS_PEELOFF = 449 + SYS_SOCKET_DELEGATE = 450 + SYS_TELEMETRY = 451 + SYS_PROC_UUID_POLICY = 452 + SYS_MEMORYSTATUS_GET_LEVEL = 453 + SYS_SYSTEM_OVERRIDE = 454 + SYS_VFS_PURGE = 455 + SYS_SFI_CTL = 456 + SYS_SFI_PIDCTL = 457 + SYS_COALITION = 458 + SYS_COALITION_INFO = 459 + SYS_NECP_MATCH_POLICY = 460 + SYS_GETATTRLISTBULK = 461 + SYS_CLONEFILEAT = 462 + SYS_OPENAT = 463 + SYS_OPENAT_NOCANCEL = 464 + SYS_RENAMEAT = 465 + SYS_FACCESSAT = 466 + SYS_FCHMODAT = 467 + SYS_FCHOWNAT = 468 + SYS_FSTATAT = 469 + SYS_FSTATAT64 = 470 + SYS_LINKAT = 471 + SYS_UNLINKAT = 472 + SYS_READLINKAT = 473 + SYS_SYMLINKAT = 474 + SYS_MKDIRAT = 475 + SYS_GETATTRLISTAT = 476 + SYS_PROC_TRACE_LOG = 477 + SYS_BSDTHREAD_CTL = 478 + SYS_OPENBYID_NP = 479 + SYS_RECVMSG_X = 480 + SYS_SENDMSG_X = 481 + SYS_THREAD_SELFUSAGE = 482 + SYS_CSRCTL = 483 + SYS_GUARDED_OPEN_DPROTECTED_NP = 484 + SYS_GUARDED_WRITE_NP = 485 + SYS_GUARDED_PWRITE_NP = 486 + SYS_GUARDED_WRITEV_NP = 487 + SYS_RENAMEATX_NP = 488 + SYS_MREMAP_ENCRYPTED = 489 + SYS_NETAGENT_TRIGGER = 490 + SYS_STACK_SNAPSHOT_WITH_CONFIG = 491 + SYS_MICROSTACKSHOT = 492 + SYS_GRAB_PGO_DATA = 493 + SYS_PERSONA = 494 + SYS_WORK_INTERVAL_CTL = 499 + SYS_GETENTROPY = 500 + SYS_NECP_OPEN = 501 + SYS_NECP_CLIENT_ACTION = 502 + SYS___NEXUS_OPEN = 503 + SYS___NEXUS_REGISTER = 504 + SYS___NEXUS_DEREGISTER = 505 + SYS___NEXUS_CREATE = 506 + SYS___NEXUS_DESTROY = 507 + SYS___NEXUS_GET_OPT = 508 + SYS___NEXUS_SET_OPT = 509 + SYS___CHANNEL_OPEN = 510 + SYS___CHANNEL_GET_INFO = 511 + SYS___CHANNEL_SYNC = 512 + SYS___CHANNEL_GET_OPT = 513 + SYS___CHANNEL_SET_OPT = 514 + SYS_ULOCK_WAIT = 515 + SYS_ULOCK_WAKE = 516 + SYS_FCLONEFILEAT = 517 + SYS_FS_SNAPSHOT = 518 + SYS_TERMINATE_WITH_PAYLOAD = 520 + SYS_ABORT_WITH_PAYLOAD = 521 + SYS_NECP_SESSION_OPEN = 522 + SYS_NECP_SESSION_ACTION = 523 + SYS_SETATTRLISTAT = 524 + SYS_NET_QOS_GUIDELINE = 525 + SYS_FMOUNT = 526 + SYS_NTP_ADJTIME = 527 + SYS_NTP_GETTIME = 528 + SYS_OS_FAULT_WITH_PAYLOAD = 529 + SYS_MAXSYSCALL = 530 + SYS_INVALID = 63 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go new file mode 100644 index 00000000000..527b9588cc9 --- /dev/null +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_darwin_arm64.go @@ -0,0 +1,437 @@ +// go run mksysnum.go /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.1.sdk/usr/include/sys/syscall.h +// Code generated by the command above; see README.md. DO NOT EDIT. + +// +build arm64,darwin + +package unix + +// Deprecated: Use libSystem wrappers instead of direct syscalls. +const ( + SYS_SYSCALL = 0 + SYS_EXIT = 1 + SYS_FORK = 2 + SYS_READ = 3 + SYS_WRITE = 4 + SYS_OPEN = 5 + SYS_CLOSE = 6 + SYS_WAIT4 = 7 + SYS_LINK = 9 + SYS_UNLINK = 10 + SYS_CHDIR = 12 + SYS_FCHDIR = 13 + SYS_MKNOD = 14 + SYS_CHMOD = 15 + SYS_CHOWN = 16 + SYS_GETFSSTAT = 18 + SYS_GETPID = 20 + SYS_SETUID = 23 + SYS_GETUID = 24 + SYS_GETEUID = 25 + SYS_PTRACE = 26 + SYS_RECVMSG = 27 + SYS_SENDMSG = 28 + SYS_RECVFROM = 29 + SYS_ACCEPT = 30 + SYS_GETPEERNAME = 31 + SYS_GETSOCKNAME = 32 + SYS_ACCESS = 33 + SYS_CHFLAGS = 34 + SYS_FCHFLAGS = 35 + SYS_SYNC = 36 + SYS_KILL = 37 + SYS_GETPPID = 39 + SYS_DUP = 41 + SYS_PIPE = 42 + SYS_GETEGID = 43 + SYS_SIGACTION = 46 + SYS_GETGID = 47 + SYS_SIGPROCMASK = 48 + SYS_GETLOGIN = 49 + SYS_SETLOGIN = 50 + SYS_ACCT = 51 + SYS_SIGPENDING = 52 + SYS_SIGALTSTACK = 53 + SYS_IOCTL = 54 + SYS_REBOOT = 55 + SYS_REVOKE = 56 + SYS_SYMLINK = 57 + SYS_READLINK = 58 + SYS_EXECVE = 59 + SYS_UMASK = 60 + SYS_CHROOT = 61 + SYS_MSYNC = 65 + SYS_VFORK = 66 + SYS_MUNMAP = 73 + SYS_MPROTECT = 74 + SYS_MADVISE = 75 + SYS_MINCORE = 78 + SYS_GETGROUPS = 79 + SYS_SETGROUPS = 80 + SYS_GETPGRP = 81 + SYS_SETPGID = 82 + SYS_SETITIMER = 83 + SYS_SWAPON = 85 + SYS_GETITIMER = 86 + SYS_GETDTABLESIZE = 89 + SYS_DUP2 = 90 + SYS_FCNTL = 92 + SYS_SELECT = 93 + SYS_FSYNC = 95 + SYS_SETPRIORITY = 96 + SYS_SOCKET = 97 + SYS_CONNECT = 98 + SYS_GETPRIORITY = 100 + SYS_BIND = 104 + SYS_SETSOCKOPT = 105 + SYS_LISTEN = 106 + SYS_SIGSUSPEND = 111 + SYS_GETTIMEOFDAY = 116 + SYS_GETRUSAGE = 117 + SYS_GETSOCKOPT = 118 + SYS_READV = 120 + SYS_WRITEV = 121 + SYS_SETTIMEOFDAY = 122 + SYS_FCHOWN = 123 + SYS_FCHMOD = 124 + SYS_SETREUID = 126 + SYS_SETREGID = 127 + SYS_RENAME = 128 + SYS_FLOCK = 131 + SYS_MKFIFO = 132 + SYS_SENDTO = 133 + SYS_SHUTDOWN = 134 + SYS_SOCKETPAIR = 135 + SYS_MKDIR = 136 + SYS_RMDIR = 137 + SYS_UTIMES = 138 + SYS_FUTIMES = 139 + SYS_ADJTIME = 140 + SYS_GETHOSTUUID = 142 + SYS_SETSID = 147 + SYS_GETPGID = 151 + SYS_SETPRIVEXEC = 152 + SYS_PREAD = 153 + SYS_PWRITE = 154 + SYS_NFSSVC = 155 + SYS_STATFS = 157 + SYS_FSTATFS = 158 + SYS_UNMOUNT = 159 + SYS_GETFH = 161 + SYS_QUOTACTL = 165 + SYS_MOUNT = 167 + SYS_CSOPS = 169 + SYS_CSOPS_AUDITTOKEN = 170 + SYS_WAITID = 173 + SYS_KDEBUG_TYPEFILTER = 177 + SYS_KDEBUG_TRACE_STRING = 178 + SYS_KDEBUG_TRACE64 = 179 + SYS_KDEBUG_TRACE = 180 + SYS_SETGID = 181 + SYS_SETEGID = 182 + SYS_SETEUID = 183 + SYS_SIGRETURN = 184 + SYS_THREAD_SELFCOUNTS = 186 + SYS_FDATASYNC = 187 + SYS_STAT = 188 + SYS_FSTAT = 189 + SYS_LSTAT = 190 + SYS_PATHCONF = 191 + SYS_FPATHCONF = 192 + SYS_GETRLIMIT = 194 + SYS_SETRLIMIT = 195 + SYS_GETDIRENTRIES = 196 + SYS_MMAP = 197 + SYS_LSEEK = 199 + SYS_TRUNCATE = 200 + SYS_FTRUNCATE = 201 + SYS_SYSCTL = 202 + SYS_MLOCK = 203 + SYS_MUNLOCK = 204 + SYS_UNDELETE = 205 + SYS_OPEN_DPROTECTED_NP = 216 + SYS_GETATTRLIST = 220 + SYS_SETATTRLIST = 221 + SYS_GETDIRENTRIESATTR = 222 + SYS_EXCHANGEDATA = 223 + SYS_SEARCHFS = 225 + SYS_DELETE = 226 + SYS_COPYFILE = 227 + SYS_FGETATTRLIST = 228 + SYS_FSETATTRLIST = 229 + SYS_POLL = 230 + SYS_WATCHEVENT = 231 + SYS_WAITEVENT = 232 + SYS_MODWATCH = 233 + SYS_GETXATTR = 234 + SYS_FGETXATTR = 235 + SYS_SETXATTR = 236 + SYS_FSETXATTR = 237 + SYS_REMOVEXATTR = 238 + SYS_FREMOVEXATTR = 239 + SYS_LISTXATTR = 240 + SYS_FLISTXATTR = 241 + SYS_FSCTL = 242 + SYS_INITGROUPS = 243 + SYS_POSIX_SPAWN = 244 + SYS_FFSCTL = 245 + SYS_NFSCLNT = 247 + SYS_FHOPEN = 248 + SYS_MINHERIT = 250 + SYS_SEMSYS = 251 + SYS_MSGSYS = 252 + SYS_SHMSYS = 253 + SYS_SEMCTL = 254 + SYS_SEMGET = 255 + SYS_SEMOP = 256 + SYS_MSGCTL = 258 + SYS_MSGGET = 259 + SYS_MSGSND = 260 + SYS_MSGRCV = 261 + SYS_SHMAT = 262 + SYS_SHMCTL = 263 + SYS_SHMDT = 264 + SYS_SHMGET = 265 + SYS_SHM_OPEN = 266 + SYS_SHM_UNLINK = 267 + SYS_SEM_OPEN = 268 + SYS_SEM_CLOSE = 269 + SYS_SEM_UNLINK = 270 + SYS_SEM_WAIT = 271 + SYS_SEM_TRYWAIT = 272 + SYS_SEM_POST = 273 + SYS_SYSCTLBYNAME = 274 + SYS_OPEN_EXTENDED = 277 + SYS_UMASK_EXTENDED = 278 + SYS_STAT_EXTENDED = 279 + SYS_LSTAT_EXTENDED = 280 + SYS_FSTAT_EXTENDED = 281 + SYS_CHMOD_EXTENDED = 282 + SYS_FCHMOD_EXTENDED = 283 + SYS_ACCESS_EXTENDED = 284 + SYS_SETTID = 285 + SYS_GETTID = 286 + SYS_SETSGROUPS = 287 + SYS_GETSGROUPS = 288 + SYS_SETWGROUPS = 289 + SYS_GETWGROUPS = 290 + SYS_MKFIFO_EXTENDED = 291 + SYS_MKDIR_EXTENDED = 292 + SYS_IDENTITYSVC = 293 + SYS_SHARED_REGION_CHECK_NP = 294 + SYS_VM_PRESSURE_MONITOR = 296 + SYS_PSYNCH_RW_LONGRDLOCK = 297 + SYS_PSYNCH_RW_YIELDWRLOCK = 298 + SYS_PSYNCH_RW_DOWNGRADE = 299 + SYS_PSYNCH_RW_UPGRADE = 300 + SYS_PSYNCH_MUTEXWAIT = 301 + SYS_PSYNCH_MUTEXDROP = 302 + SYS_PSYNCH_CVBROAD = 303 + SYS_PSYNCH_CVSIGNAL = 304 + SYS_PSYNCH_CVWAIT = 305 + SYS_PSYNCH_RW_RDLOCK = 306 + SYS_PSYNCH_RW_WRLOCK = 307 + SYS_PSYNCH_RW_UNLOCK = 308 + SYS_PSYNCH_RW_UNLOCK2 = 309 + SYS_GETSID = 310 + SYS_SETTID_WITH_PID = 311 + SYS_PSYNCH_CVCLRPREPOST = 312 + SYS_AIO_FSYNC = 313 + SYS_AIO_RETURN = 314 + SYS_AIO_SUSPEND = 315 + SYS_AIO_CANCEL = 316 + SYS_AIO_ERROR = 317 + SYS_AIO_READ = 318 + SYS_AIO_WRITE = 319 + SYS_LIO_LISTIO = 320 + SYS_IOPOLICYSYS = 322 + SYS_PROCESS_POLICY = 323 + SYS_MLOCKALL = 324 + SYS_MUNLOCKALL = 325 + SYS_ISSETUGID = 327 + SYS___PTHREAD_KILL = 328 + SYS___PTHREAD_SIGMASK = 329 + SYS___SIGWAIT = 330 + SYS___DISABLE_THREADSIGNAL = 331 + SYS___PTHREAD_MARKCANCEL = 332 + SYS___PTHREAD_CANCELED = 333 + SYS___SEMWAIT_SIGNAL = 334 + SYS_PROC_INFO = 336 + SYS_SENDFILE = 337 + SYS_STAT64 = 338 + SYS_FSTAT64 = 339 + SYS_LSTAT64 = 340 + SYS_STAT64_EXTENDED = 341 + SYS_LSTAT64_EXTENDED = 342 + SYS_FSTAT64_EXTENDED = 343 + SYS_GETDIRENTRIES64 = 344 + SYS_STATFS64 = 345 + SYS_FSTATFS64 = 346 + SYS_GETFSSTAT64 = 347 + SYS___PTHREAD_CHDIR = 348 + SYS___PTHREAD_FCHDIR = 349 + SYS_AUDIT = 350 + SYS_AUDITON = 351 + SYS_GETAUID = 353 + SYS_SETAUID = 354 + SYS_GETAUDIT_ADDR = 357 + SYS_SETAUDIT_ADDR = 358 + SYS_AUDITCTL = 359 + SYS_BSDTHREAD_CREATE = 360 + SYS_BSDTHREAD_TERMINATE = 361 + SYS_KQUEUE = 362 + SYS_KEVENT = 363 + SYS_LCHOWN = 364 + SYS_BSDTHREAD_REGISTER = 366 + SYS_WORKQ_OPEN = 367 + SYS_WORKQ_KERNRETURN = 368 + SYS_KEVENT64 = 369 + SYS___OLD_SEMWAIT_SIGNAL = 370 + SYS___OLD_SEMWAIT_SIGNAL_NOCANCEL = 371 + SYS_THREAD_SELFID = 372 + SYS_LEDGER = 373 + SYS_KEVENT_QOS = 374 + SYS_KEVENT_ID = 375 + SYS___MAC_EXECVE = 380 + SYS___MAC_SYSCALL = 381 + SYS___MAC_GET_FILE = 382 + SYS___MAC_SET_FILE = 383 + SYS___MAC_GET_LINK = 384 + SYS___MAC_SET_LINK = 385 + SYS___MAC_GET_PROC = 386 + SYS___MAC_SET_PROC = 387 + SYS___MAC_GET_FD = 388 + SYS___MAC_SET_FD = 389 + SYS___MAC_GET_PID = 390 + SYS_PSELECT = 394 + SYS_PSELECT_NOCANCEL = 395 + SYS_READ_NOCANCEL = 396 + SYS_WRITE_NOCANCEL = 397 + SYS_OPEN_NOCANCEL = 398 + SYS_CLOSE_NOCANCEL = 399 + SYS_WAIT4_NOCANCEL = 400 + SYS_RECVMSG_NOCANCEL = 401 + SYS_SENDMSG_NOCANCEL = 402 + SYS_RECVFROM_NOCANCEL = 403 + SYS_ACCEPT_NOCANCEL = 404 + SYS_MSYNC_NOCANCEL = 405 + SYS_FCNTL_NOCANCEL = 406 + SYS_SELECT_NOCANCEL = 407 + SYS_FSYNC_NOCANCEL = 408 + SYS_CONNECT_NOCANCEL = 409 + SYS_SIGSUSPEND_NOCANCEL = 410 + SYS_READV_NOCANCEL = 411 + SYS_WRITEV_NOCANCEL = 412 + SYS_SENDTO_NOCANCEL = 413 + SYS_PREAD_NOCANCEL = 414 + SYS_PWRITE_NOCANCEL = 415 + SYS_WAITID_NOCANCEL = 416 + SYS_POLL_NOCANCEL = 417 + SYS_MSGSND_NOCANCEL = 418 + SYS_MSGRCV_NOCANCEL = 419 + SYS_SEM_WAIT_NOCANCEL = 420 + SYS_AIO_SUSPEND_NOCANCEL = 421 + SYS___SIGWAIT_NOCANCEL = 422 + SYS___SEMWAIT_SIGNAL_NOCANCEL = 423 + SYS___MAC_MOUNT = 424 + SYS___MAC_GET_MOUNT = 425 + SYS___MAC_GETFSSTAT = 426 + SYS_FSGETPATH = 427 + SYS_AUDIT_SESSION_SELF = 428 + SYS_AUDIT_SESSION_JOIN = 429 + SYS_FILEPORT_MAKEPORT = 430 + SYS_FILEPORT_MAKEFD = 431 + SYS_AUDIT_SESSION_PORT = 432 + SYS_PID_SUSPEND = 433 + SYS_PID_RESUME = 434 + SYS_PID_HIBERNATE = 435 + SYS_PID_SHUTDOWN_SOCKETS = 436 + SYS_SHARED_REGION_MAP_AND_SLIDE_NP = 438 + SYS_KAS_INFO = 439 + SYS_MEMORYSTATUS_CONTROL = 440 + SYS_GUARDED_OPEN_NP = 441 + SYS_GUARDED_CLOSE_NP = 442 + SYS_GUARDED_KQUEUE_NP = 443 + SYS_CHANGE_FDGUARD_NP = 444 + SYS_USRCTL = 445 + SYS_PROC_RLIMIT_CONTROL = 446 + SYS_CONNECTX = 447 + SYS_DISCONNECTX = 448 + SYS_PEELOFF = 449 + SYS_SOCKET_DELEGATE = 450 + SYS_TELEMETRY = 451 + SYS_PROC_UUID_POLICY = 452 + SYS_MEMORYSTATUS_GET_LEVEL = 453 + SYS_SYSTEM_OVERRIDE = 454 + SYS_VFS_PURGE = 455 + SYS_SFI_CTL = 456 + SYS_SFI_PIDCTL = 457 + SYS_COALITION = 458 + SYS_COALITION_INFO = 459 + SYS_NECP_MATCH_POLICY = 460 + SYS_GETATTRLISTBULK = 461 + SYS_CLONEFILEAT = 462 + SYS_OPENAT = 463 + SYS_OPENAT_NOCANCEL = 464 + SYS_RENAMEAT = 465 + SYS_FACCESSAT = 466 + SYS_FCHMODAT = 467 + SYS_FCHOWNAT = 468 + SYS_FSTATAT = 469 + SYS_FSTATAT64 = 470 + SYS_LINKAT = 471 + SYS_UNLINKAT = 472 + SYS_READLINKAT = 473 + SYS_SYMLINKAT = 474 + SYS_MKDIRAT = 475 + SYS_GETATTRLISTAT = 476 + SYS_PROC_TRACE_LOG = 477 + SYS_BSDTHREAD_CTL = 478 + SYS_OPENBYID_NP = 479 + SYS_RECVMSG_X = 480 + SYS_SENDMSG_X = 481 + SYS_THREAD_SELFUSAGE = 482 + SYS_CSRCTL = 483 + SYS_GUARDED_OPEN_DPROTECTED_NP = 484 + SYS_GUARDED_WRITE_NP = 485 + SYS_GUARDED_PWRITE_NP = 486 + SYS_GUARDED_WRITEV_NP = 487 + SYS_RENAMEATX_NP = 488 + SYS_MREMAP_ENCRYPTED = 489 + SYS_NETAGENT_TRIGGER = 490 + SYS_STACK_SNAPSHOT_WITH_CONFIG = 491 + SYS_MICROSTACKSHOT = 492 + SYS_GRAB_PGO_DATA = 493 + SYS_PERSONA = 494 + SYS_WORK_INTERVAL_CTL = 499 + SYS_GETENTROPY = 500 + SYS_NECP_OPEN = 501 + SYS_NECP_CLIENT_ACTION = 502 + SYS___NEXUS_OPEN = 503 + SYS___NEXUS_REGISTER = 504 + SYS___NEXUS_DEREGISTER = 505 + SYS___NEXUS_CREATE = 506 + SYS___NEXUS_DESTROY = 507 + SYS___NEXUS_GET_OPT = 508 + SYS___NEXUS_SET_OPT = 509 + SYS___CHANNEL_OPEN = 510 + SYS___CHANNEL_GET_INFO = 511 + SYS___CHANNEL_SYNC = 512 + SYS___CHANNEL_GET_OPT = 513 + SYS___CHANNEL_SET_OPT = 514 + SYS_ULOCK_WAIT = 515 + SYS_ULOCK_WAKE = 516 + SYS_FCLONEFILEAT = 517 + SYS_FS_SNAPSHOT = 518 + SYS_TERMINATE_WITH_PAYLOAD = 520 + SYS_ABORT_WITH_PAYLOAD = 521 + SYS_NECP_SESSION_OPEN = 522 + SYS_NECP_SESSION_ACTION = 523 + SYS_SETATTRLISTAT = 524 + SYS_NET_QOS_GUIDELINE = 525 + SYS_FMOUNT = 526 + SYS_NTP_ADJTIME = 527 + SYS_NTP_GETTIME = 528 + SYS_OS_FAULT_WITH_PAYLOAD = 529 + SYS_MAXSYSCALL = 530 + SYS_INVALID = 63 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go index 464c9a9832d..9912c6ee3d6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_dragonfly_amd64.go @@ -6,129 +6,125 @@ package unix const ( - // SYS_NOSYS = 0; // { int nosys(void); } syscall nosys_args int - SYS_EXIT = 1 // { void exit(int rval); } - SYS_FORK = 2 // { int fork(void); } - SYS_READ = 3 // { ssize_t read(int fd, void *buf, size_t nbyte); } - SYS_WRITE = 4 // { ssize_t write(int fd, const void *buf, size_t nbyte); } - SYS_OPEN = 5 // { int open(char *path, int flags, int mode); } - SYS_CLOSE = 6 // { int close(int fd); } - SYS_WAIT4 = 7 // { int wait4(int pid, int *status, int options, struct rusage *rusage); } wait4 wait_args int - SYS_LINK = 9 // { int link(char *path, char *link); } - SYS_UNLINK = 10 // { int unlink(char *path); } - SYS_CHDIR = 12 // { int chdir(char *path); } - SYS_FCHDIR = 13 // { int fchdir(int fd); } - SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } - SYS_CHMOD = 15 // { int chmod(char *path, int mode); } - SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } - SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int - SYS_GETFSSTAT = 18 // { int getfsstat(struct statfs *buf, long bufsize, int flags); } - SYS_GETPID = 20 // { pid_t getpid(void); } - SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } - SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } - SYS_SETUID = 23 // { int setuid(uid_t uid); } - SYS_GETUID = 24 // { uid_t getuid(void); } - SYS_GETEUID = 25 // { uid_t geteuid(void); } - SYS_PTRACE = 26 // { int ptrace(int req, pid_t pid, caddr_t addr, int data); } - SYS_RECVMSG = 27 // { int recvmsg(int s, struct msghdr *msg, int flags); } - SYS_SENDMSG = 28 // { int sendmsg(int s, caddr_t msg, int flags); } - SYS_RECVFROM = 29 // { int recvfrom(int s, caddr_t buf, size_t len, int flags, caddr_t from, int *fromlenaddr); } - SYS_ACCEPT = 30 // { int accept(int s, caddr_t name, int *anamelen); } - SYS_GETPEERNAME = 31 // { int getpeername(int fdes, caddr_t asa, int *alen); } - SYS_GETSOCKNAME = 32 // { int getsockname(int fdes, caddr_t asa, int *alen); } - SYS_ACCESS = 33 // { int access(char *path, int flags); } - SYS_CHFLAGS = 34 // { int chflags(char *path, int flags); } - SYS_FCHFLAGS = 35 // { int fchflags(int fd, int flags); } - SYS_SYNC = 36 // { int sync(void); } - SYS_KILL = 37 // { int kill(int pid, int signum); } - SYS_GETPPID = 39 // { pid_t getppid(void); } - SYS_DUP = 41 // { int dup(int fd); } - SYS_PIPE = 42 // { int pipe(void); } - SYS_GETEGID = 43 // { gid_t getegid(void); } - SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, size_t offset, u_int scale); } - SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } - SYS_GETGID = 47 // { gid_t getgid(void); } - SYS_GETLOGIN = 49 // { int getlogin(char *namebuf, u_int namelen); } - SYS_SETLOGIN = 50 // { int setlogin(char *namebuf); } - SYS_ACCT = 51 // { int acct(char *path); } - SYS_SIGALTSTACK = 53 // { int sigaltstack(stack_t *ss, stack_t *oss); } - SYS_IOCTL = 54 // { int ioctl(int fd, u_long com, caddr_t data); } - SYS_REBOOT = 55 // { int reboot(int opt); } - SYS_REVOKE = 56 // { int revoke(char *path); } - SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } - SYS_READLINK = 58 // { int readlink(char *path, char *buf, int count); } - SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } - SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int - SYS_CHROOT = 61 // { int chroot(char *path); } - SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } - SYS_VFORK = 66 // { pid_t vfork(void); } - SYS_SBRK = 69 // { int sbrk(int incr); } - SYS_SSTK = 70 // { int sstk(int incr); } - SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } - SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } - SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } - SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } - SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } - SYS_SETGROUPS = 80 // { int setgroups(u_int gidsetsize, gid_t *gidset); } - SYS_GETPGRP = 81 // { int getpgrp(void); } - SYS_SETPGID = 82 // { int setpgid(int pid, int pgid); } - SYS_SETITIMER = 83 // { int setitimer(u_int which, struct itimerval *itv, struct itimerval *oitv); } - SYS_SWAPON = 85 // { int swapon(char *name); } - SYS_GETITIMER = 86 // { int getitimer(u_int which, struct itimerval *itv); } - SYS_GETDTABLESIZE = 89 // { int getdtablesize(void); } - SYS_DUP2 = 90 // { int dup2(int from, int to); } - SYS_FCNTL = 92 // { int fcntl(int fd, int cmd, long arg); } - SYS_SELECT = 93 // { int select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } - SYS_FSYNC = 95 // { int fsync(int fd); } - SYS_SETPRIORITY = 96 // { int setpriority(int which, int who, int prio); } - SYS_SOCKET = 97 // { int socket(int domain, int type, int protocol); } - SYS_CONNECT = 98 // { int connect(int s, caddr_t name, int namelen); } - SYS_GETPRIORITY = 100 // { int getpriority(int which, int who); } - SYS_BIND = 104 // { int bind(int s, caddr_t name, int namelen); } - SYS_SETSOCKOPT = 105 // { int setsockopt(int s, int level, int name, caddr_t val, int valsize); } - SYS_LISTEN = 106 // { int listen(int s, int backlog); } - SYS_GETTIMEOFDAY = 116 // { int gettimeofday(struct timeval *tp, struct timezone *tzp); } - SYS_GETRUSAGE = 117 // { int getrusage(int who, struct rusage *rusage); } - SYS_GETSOCKOPT = 118 // { int getsockopt(int s, int level, int name, caddr_t val, int *avalsize); } - SYS_READV = 120 // { int readv(int fd, struct iovec *iovp, u_int iovcnt); } - SYS_WRITEV = 121 // { int writev(int fd, struct iovec *iovp, u_int iovcnt); } - SYS_SETTIMEOFDAY = 122 // { int settimeofday(struct timeval *tv, struct timezone *tzp); } - SYS_FCHOWN = 123 // { int fchown(int fd, int uid, int gid); } - SYS_FCHMOD = 124 // { int fchmod(int fd, int mode); } - SYS_SETREUID = 126 // { int setreuid(int ruid, int euid); } - SYS_SETREGID = 127 // { int setregid(int rgid, int egid); } - SYS_RENAME = 128 // { int rename(char *from, char *to); } - SYS_FLOCK = 131 // { int flock(int fd, int how); } - SYS_MKFIFO = 132 // { int mkfifo(char *path, int mode); } - SYS_SENDTO = 133 // { int sendto(int s, caddr_t buf, size_t len, int flags, caddr_t to, int tolen); } - SYS_SHUTDOWN = 134 // { int shutdown(int s, int how); } - SYS_SOCKETPAIR = 135 // { int socketpair(int domain, int type, int protocol, int *rsv); } - SYS_MKDIR = 136 // { int mkdir(char *path, int mode); } - SYS_RMDIR = 137 // { int rmdir(char *path); } - SYS_UTIMES = 138 // { int utimes(char *path, struct timeval *tptr); } - SYS_ADJTIME = 140 // { int adjtime(struct timeval *delta, struct timeval *olddelta); } - SYS_SETSID = 147 // { int setsid(void); } - SYS_QUOTACTL = 148 // { int quotactl(char *path, int cmd, int uid, caddr_t arg); } - SYS_STATFS = 157 // { int statfs(char *path, struct statfs *buf); } - SYS_FSTATFS = 158 // { int fstatfs(int fd, struct statfs *buf); } - SYS_GETFH = 161 // { int getfh(char *fname, struct fhandle *fhp); } - SYS_GETDOMAINNAME = 162 // { int getdomainname(char *domainname, int len); } - SYS_SETDOMAINNAME = 163 // { int setdomainname(char *domainname, int len); } - SYS_UNAME = 164 // { int uname(struct utsname *name); } - SYS_SYSARCH = 165 // { int sysarch(int op, char *parms); } - SYS_RTPRIO = 166 // { int rtprio(int function, pid_t pid, struct rtprio *rtp); } - SYS_EXTPREAD = 173 // { ssize_t extpread(int fd, void *buf, size_t nbyte, int flags, off_t offset); } - SYS_EXTPWRITE = 174 // { ssize_t extpwrite(int fd, const void *buf, size_t nbyte, int flags, off_t offset); } - SYS_NTP_ADJTIME = 176 // { int ntp_adjtime(struct timex *tp); } - SYS_SETGID = 181 // { int setgid(gid_t gid); } - SYS_SETEGID = 182 // { int setegid(gid_t egid); } - SYS_SETEUID = 183 // { int seteuid(uid_t euid); } - SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } - SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } - SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int - SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int - SYS_MMAP = 197 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); } - // SYS_NOSYS = 198; // { int nosys(void); } __syscall __syscall_args int + SYS_EXIT = 1 // { void exit(int rval); } + SYS_FORK = 2 // { int fork(void); } + SYS_READ = 3 // { ssize_t read(int fd, void *buf, size_t nbyte); } + SYS_WRITE = 4 // { ssize_t write(int fd, const void *buf, size_t nbyte); } + SYS_OPEN = 5 // { int open(char *path, int flags, int mode); } + SYS_CLOSE = 6 // { int close(int fd); } + SYS_WAIT4 = 7 // { int wait4(int pid, int *status, int options, struct rusage *rusage); } wait4 wait_args int + // SYS_NOSYS = 8; // { int nosys(void); } __nosys nosys_args int + SYS_LINK = 9 // { int link(char *path, char *link); } + SYS_UNLINK = 10 // { int unlink(char *path); } + SYS_CHDIR = 12 // { int chdir(char *path); } + SYS_FCHDIR = 13 // { int fchdir(int fd); } + SYS_MKNOD = 14 // { int mknod(char *path, int mode, int dev); } + SYS_CHMOD = 15 // { int chmod(char *path, int mode); } + SYS_CHOWN = 16 // { int chown(char *path, int uid, int gid); } + SYS_OBREAK = 17 // { int obreak(char *nsize); } break obreak_args int + SYS_GETFSSTAT = 18 // { int getfsstat(struct statfs *buf, long bufsize, int flags); } + SYS_GETPID = 20 // { pid_t getpid(void); } + SYS_MOUNT = 21 // { int mount(char *type, char *path, int flags, caddr_t data); } + SYS_UNMOUNT = 22 // { int unmount(char *path, int flags); } + SYS_SETUID = 23 // { int setuid(uid_t uid); } + SYS_GETUID = 24 // { uid_t getuid(void); } + SYS_GETEUID = 25 // { uid_t geteuid(void); } + SYS_PTRACE = 26 // { int ptrace(int req, pid_t pid, caddr_t addr, int data); } + SYS_RECVMSG = 27 // { int recvmsg(int s, struct msghdr *msg, int flags); } + SYS_SENDMSG = 28 // { int sendmsg(int s, caddr_t msg, int flags); } + SYS_RECVFROM = 29 // { int recvfrom(int s, caddr_t buf, size_t len, int flags, caddr_t from, int *fromlenaddr); } + SYS_ACCEPT = 30 // { int accept(int s, caddr_t name, int *anamelen); } + SYS_GETPEERNAME = 31 // { int getpeername(int fdes, caddr_t asa, int *alen); } + SYS_GETSOCKNAME = 32 // { int getsockname(int fdes, caddr_t asa, int *alen); } + SYS_ACCESS = 33 // { int access(char *path, int flags); } + SYS_CHFLAGS = 34 // { int chflags(const char *path, u_long flags); } + SYS_FCHFLAGS = 35 // { int fchflags(int fd, u_long flags); } + SYS_SYNC = 36 // { int sync(void); } + SYS_KILL = 37 // { int kill(int pid, int signum); } + SYS_GETPPID = 39 // { pid_t getppid(void); } + SYS_DUP = 41 // { int dup(int fd); } + SYS_PIPE = 42 // { int pipe(void); } + SYS_GETEGID = 43 // { gid_t getegid(void); } + SYS_PROFIL = 44 // { int profil(caddr_t samples, size_t size, u_long offset, u_int scale); } + SYS_KTRACE = 45 // { int ktrace(const char *fname, int ops, int facs, int pid); } + SYS_GETGID = 47 // { gid_t getgid(void); } + SYS_GETLOGIN = 49 // { int getlogin(char *namebuf, size_t namelen); } + SYS_SETLOGIN = 50 // { int setlogin(char *namebuf); } + SYS_ACCT = 51 // { int acct(char *path); } + SYS_SIGALTSTACK = 53 // { int sigaltstack(stack_t *ss, stack_t *oss); } + SYS_IOCTL = 54 // { int ioctl(int fd, u_long com, caddr_t data); } + SYS_REBOOT = 55 // { int reboot(int opt); } + SYS_REVOKE = 56 // { int revoke(char *path); } + SYS_SYMLINK = 57 // { int symlink(char *path, char *link); } + SYS_READLINK = 58 // { int readlink(char *path, char *buf, int count); } + SYS_EXECVE = 59 // { int execve(char *fname, char **argv, char **envv); } + SYS_UMASK = 60 // { int umask(int newmask); } umask umask_args int + SYS_CHROOT = 61 // { int chroot(char *path); } + SYS_MSYNC = 65 // { int msync(void *addr, size_t len, int flags); } + SYS_VFORK = 66 // { pid_t vfork(void); } + SYS_SBRK = 69 // { caddr_t sbrk(size_t incr); } + SYS_SSTK = 70 // { int sstk(size_t incr); } + SYS_MUNMAP = 73 // { int munmap(void *addr, size_t len); } + SYS_MPROTECT = 74 // { int mprotect(void *addr, size_t len, int prot); } + SYS_MADVISE = 75 // { int madvise(void *addr, size_t len, int behav); } + SYS_MINCORE = 78 // { int mincore(const void *addr, size_t len, char *vec); } + SYS_GETGROUPS = 79 // { int getgroups(u_int gidsetsize, gid_t *gidset); } + SYS_SETGROUPS = 80 // { int setgroups(u_int gidsetsize, gid_t *gidset); } + SYS_GETPGRP = 81 // { int getpgrp(void); } + SYS_SETPGID = 82 // { int setpgid(int pid, int pgid); } + SYS_SETITIMER = 83 // { int setitimer(u_int which, struct itimerval *itv, struct itimerval *oitv); } + SYS_SWAPON = 85 // { int swapon(char *name); } + SYS_GETITIMER = 86 // { int getitimer(u_int which, struct itimerval *itv); } + SYS_GETDTABLESIZE = 89 // { int getdtablesize(void); } + SYS_DUP2 = 90 // { int dup2(int from, int to); } + SYS_FCNTL = 92 // { int fcntl(int fd, int cmd, long arg); } + SYS_SELECT = 93 // { int select(int nd, fd_set *in, fd_set *ou, fd_set *ex, struct timeval *tv); } + SYS_FSYNC = 95 // { int fsync(int fd); } + SYS_SETPRIORITY = 96 // { int setpriority(int which, int who, int prio); } + SYS_SOCKET = 97 // { int socket(int domain, int type, int protocol); } + SYS_CONNECT = 98 // { int connect(int s, caddr_t name, int namelen); } + SYS_GETPRIORITY = 100 // { int getpriority(int which, int who); } + SYS_BIND = 104 // { int bind(int s, caddr_t name, int namelen); } + SYS_SETSOCKOPT = 105 // { int setsockopt(int s, int level, int name, caddr_t val, int valsize); } + SYS_LISTEN = 106 // { int listen(int s, int backlog); } + SYS_GETTIMEOFDAY = 116 // { int gettimeofday(struct timeval *tp, struct timezone *tzp); } + SYS_GETRUSAGE = 117 // { int getrusage(int who, struct rusage *rusage); } + SYS_GETSOCKOPT = 118 // { int getsockopt(int s, int level, int name, caddr_t val, int *avalsize); } + SYS_READV = 120 // { int readv(int fd, struct iovec *iovp, u_int iovcnt); } + SYS_WRITEV = 121 // { int writev(int fd, struct iovec *iovp, u_int iovcnt); } + SYS_SETTIMEOFDAY = 122 // { int settimeofday(struct timeval *tv, struct timezone *tzp); } + SYS_FCHOWN = 123 // { int fchown(int fd, int uid, int gid); } + SYS_FCHMOD = 124 // { int fchmod(int fd, int mode); } + SYS_SETREUID = 126 // { int setreuid(int ruid, int euid); } + SYS_SETREGID = 127 // { int setregid(int rgid, int egid); } + SYS_RENAME = 128 // { int rename(char *from, char *to); } + SYS_FLOCK = 131 // { int flock(int fd, int how); } + SYS_MKFIFO = 132 // { int mkfifo(char *path, int mode); } + SYS_SENDTO = 133 // { int sendto(int s, caddr_t buf, size_t len, int flags, caddr_t to, int tolen); } + SYS_SHUTDOWN = 134 // { int shutdown(int s, int how); } + SYS_SOCKETPAIR = 135 // { int socketpair(int domain, int type, int protocol, int *rsv); } + SYS_MKDIR = 136 // { int mkdir(char *path, int mode); } + SYS_RMDIR = 137 // { int rmdir(char *path); } + SYS_UTIMES = 138 // { int utimes(char *path, struct timeval *tptr); } + SYS_ADJTIME = 140 // { int adjtime(struct timeval *delta, struct timeval *olddelta); } + SYS_SETSID = 147 // { int setsid(void); } + SYS_QUOTACTL = 148 // { int quotactl(char *path, int cmd, int uid, caddr_t arg); } + SYS_STATFS = 157 // { int statfs(char *path, struct statfs *buf); } + SYS_FSTATFS = 158 // { int fstatfs(int fd, struct statfs *buf); } + SYS_GETFH = 161 // { int getfh(char *fname, struct fhandle *fhp); } + SYS_SYSARCH = 165 // { int sysarch(int op, char *parms); } + SYS_RTPRIO = 166 // { int rtprio(int function, pid_t pid, struct rtprio *rtp); } + SYS_EXTPREAD = 173 // { ssize_t extpread(int fd, void *buf, size_t nbyte, int flags, off_t offset); } + SYS_EXTPWRITE = 174 // { ssize_t extpwrite(int fd, const void *buf, size_t nbyte, int flags, off_t offset); } + SYS_NTP_ADJTIME = 176 // { int ntp_adjtime(struct timex *tp); } + SYS_SETGID = 181 // { int setgid(gid_t gid); } + SYS_SETEGID = 182 // { int setegid(gid_t egid); } + SYS_SETEUID = 183 // { int seteuid(uid_t euid); } + SYS_PATHCONF = 191 // { int pathconf(char *path, int name); } + SYS_FPATHCONF = 192 // { int fpathconf(int fd, int name); } + SYS_GETRLIMIT = 194 // { int getrlimit(u_int which, struct rlimit *rlp); } getrlimit __getrlimit_args int + SYS_SETRLIMIT = 195 // { int setrlimit(u_int which, struct rlimit *rlp); } setrlimit __setrlimit_args int + SYS_MMAP = 197 // { caddr_t mmap(caddr_t addr, size_t len, int prot, int flags, int fd, int pad, off_t pos); } SYS_LSEEK = 199 // { off_t lseek(int fd, int pad, off_t offset, int whence); } SYS_TRUNCATE = 200 // { int truncate(char *path, int pad, off_t length); } SYS_FTRUNCATE = 201 // { int ftruncate(int fd, int pad, off_t length); } @@ -161,8 +157,8 @@ const ( SYS_LCHOWN = 254 // { int lchown(char *path, int uid, int gid); } SYS_LCHMOD = 274 // { int lchmod(char *path, mode_t mode); } SYS_LUTIMES = 276 // { int lutimes(char *path, struct timeval *tptr); } - SYS_EXTPREADV = 289 // { ssize_t extpreadv(int fd, struct iovec *iovp, u_int iovcnt, int flags, off_t offset); } - SYS_EXTPWRITEV = 290 // { ssize_t extpwritev(int fd, struct iovec *iovp,u_int iovcnt, int flags, off_t offset); } + SYS_EXTPREADV = 289 // { ssize_t extpreadv(int fd, const struct iovec *iovp, int iovcnt, int flags, off_t offset); } + SYS_EXTPWRITEV = 290 // { ssize_t extpwritev(int fd, const struct iovec *iovp, int iovcnt, int flags, off_t offset); } SYS_FHSTATFS = 297 // { int fhstatfs(const struct fhandle *u_fhp, struct statfs *buf); } SYS_FHOPEN = 298 // { int fhopen(const struct fhandle *u_fhp, int flags); } SYS_MODNEXT = 300 // { int modnext(int modid); } @@ -225,7 +221,7 @@ const ( SYS_KQUEUE = 362 // { int kqueue(void); } SYS_KEVENT = 363 // { int kevent(int fd, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); } SYS_KENV = 390 // { int kenv(int what, const char *name, char *value, int len); } - SYS_LCHFLAGS = 391 // { int lchflags(char *path, int flags); } + SYS_LCHFLAGS = 391 // { int lchflags(const char *path, u_long flags); } SYS_UUIDGEN = 392 // { int uuidgen(struct uuid *store, int count); } SYS_SENDFILE = 393 // { int sendfile(int fd, int s, off_t offset, size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags); } SYS_VARSYM_SET = 450 // { int varsym_set(int level, const char *name, const char *data); } @@ -302,7 +298,7 @@ const ( SYS_VMM_GUEST_CTL = 534 // { int vmm_guest_ctl(int op, struct vmm_guest_options *options); } SYS_VMM_GUEST_SYNC_ADDR = 535 // { int vmm_guest_sync_addr(long *dstaddr, long *srcaddr); } SYS_PROCCTL = 536 // { int procctl(idtype_t idtype, id_t id, int cmd, void *data); } - SYS_CHFLAGSAT = 537 // { int chflagsat(int fd, const char *path, int flags, int atflags);} + SYS_CHFLAGSAT = 537 // { int chflagsat(int fd, const char *path, u_long flags, int atflags);} SYS_PIPE2 = 538 // { int pipe2(int *fildes, int flags); } SYS_UTIMENSAT = 539 // { int utimensat(int fd, const char *path, const struct timespec *ts, int flags); } SYS_FUTIMENS = 540 // { int futimens(int fd, const struct timespec *ts); } @@ -312,4 +308,9 @@ const ( SYS_LWP_SETAFFINITY = 544 // { int lwp_setaffinity(pid_t pid, lwpid_t tid, const cpumask_t *mask); } SYS_LWP_GETAFFINITY = 545 // { int lwp_getaffinity(pid_t pid, lwpid_t tid, cpumask_t *mask); } SYS_LWP_CREATE2 = 546 // { int lwp_create2(struct lwp_params *params, const cpumask_t *mask); } + SYS_GETCPUCLOCKID = 547 // { int getcpuclockid(pid_t pid, lwpid_t lwp_id, clockid_t *clock_id); } + SYS_WAIT6 = 548 // { int wait6(idtype_t idtype, id_t id, int *status, int options, struct __wrusage *wrusage, siginfo_t *info); } + SYS_LWP_GETNAME = 549 // { int lwp_getname(lwpid_t tid, char *name, size_t len); } + SYS_GETRANDOM = 550 // { ssize_t getrandom(void *buf, size_t len, unsigned flags); } + SYS___REALPATH = 551 // { ssize_t __realpath(const char *path, char *buf, size_t len); } ) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index a597e061cae..0f5a3f6970a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -431,6 +431,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index 8c102e55a1d..36d5219ef82 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -353,6 +353,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index 98f9b68fb90..3622ba14b4e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -395,6 +395,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index 4dabc33fbc9..6193c3dc07c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -298,6 +298,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index d5724e5964d..640b974345f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -416,6 +416,7 @@ const ( SYS_FSPICK = 4433 SYS_PIDFD_OPEN = 4434 SYS_CLONE3 = 4435 + SYS_CLOSE_RANGE = 4436 SYS_OPENAT2 = 4437 SYS_PIDFD_GETFD = 4438 SYS_FACCESSAT2 = 4439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index c1d824a4f3d..3467fbb5ff1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -346,6 +346,7 @@ const ( SYS_FSPICK = 5433 SYS_PIDFD_OPEN = 5434 SYS_CLONE3 = 5435 + SYS_CLOSE_RANGE = 5436 SYS_OPENAT2 = 5437 SYS_PIDFD_GETFD = 5438 SYS_FACCESSAT2 = 5439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index 598dd5d6375..0fc38d5a72f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -346,6 +346,7 @@ const ( SYS_FSPICK = 5433 SYS_PIDFD_OPEN = 5434 SYS_CLONE3 = 5435 + SYS_CLOSE_RANGE = 5436 SYS_OPENAT2 = 5437 SYS_PIDFD_GETFD = 5438 SYS_FACCESSAT2 = 5439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index c36782d08e2..999fd55bccb 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -416,6 +416,7 @@ const ( SYS_FSPICK = 4433 SYS_PIDFD_OPEN = 4434 SYS_CLONE3 = 4435 + SYS_CLOSE_RANGE = 4436 SYS_OPENAT2 = 4437 SYS_PIDFD_GETFD = 4438 SYS_FACCESSAT2 = 4439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 9287538d368..1df0d799355 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -395,6 +395,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 4dafad8352a..4db39cca4da 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -395,6 +395,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 6642cfccdf1..e6927401446 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -297,6 +297,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 23367b9467f..a585aec4e79 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -360,6 +360,7 @@ const ( SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 SYS_CLONE3 = 435 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index 083aa0204ef..d047e567afc 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -374,6 +374,7 @@ const ( SYS_FSMOUNT = 432 SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 + SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 SYS_FACCESSAT2 = 439 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go index 9f47b87c507..830fbb35c0a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_386.go @@ -92,9 +92,9 @@ type Statfs_t struct { Type uint32 Flags uint32 Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 + Fstypename [16]byte + Mntonname [1024]byte + Mntfromname [1024]byte Reserved [8]uint32 } @@ -145,6 +145,10 @@ type Dirent struct { _ [3]byte } +const ( + PathMax = 0x400 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 @@ -190,6 +194,15 @@ type RawSockaddrAny struct { Pad [92]int8 } +type RawSockaddrCtl struct { + Sc_len uint8 + Sc_family uint8 + Ss_sysaddr uint16 + Sc_id uint32 + Sc_unit uint32 + Sc_reserved [5]uint32 +} + type _Socklen uint32 type Linger struct { @@ -254,6 +267,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 + SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 @@ -301,7 +315,6 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } @@ -344,7 +357,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -365,7 +377,6 @@ type IfmaMsghdr2 struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Refcount int32 } @@ -374,7 +385,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -396,7 +406,8 @@ type RtMetrics struct { Rtt uint32 Rttvar uint32 Pksent uint32 - Filler [4]uint32 + State uint32 + Filler [3]uint32 } const ( @@ -497,3 +508,8 @@ type Clockinfo struct { Stathz int32 Profhz int32 } + +type CtlInfo struct { + Id uint32 + Name [96]byte +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go index 966798a8709..e53a7c49ffe 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go @@ -70,7 +70,6 @@ type Stat_t struct { Uid uint32 Gid uint32 Rdev int32 - _ [4]byte Atim Timespec Mtim Timespec Ctim Timespec @@ -97,10 +96,11 @@ type Statfs_t struct { Type uint32 Flags uint32 Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 - Reserved [8]uint32 + Fstypename [16]byte + Mntonname [1024]byte + Mntfromname [1024]byte + Flags_ext uint32 + Reserved [7]uint32 } type Flock_t struct { @@ -133,8 +133,7 @@ type Fbootstraptransfer_t struct { type Log2phys_t struct { Flags uint32 - _ [8]byte - _ [8]byte + _ [16]byte } type Fsid struct { @@ -151,6 +150,10 @@ type Dirent struct { _ [3]byte } +const ( + PathMax = 0x400 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 @@ -196,6 +199,15 @@ type RawSockaddrAny struct { Pad [92]int8 } +type RawSockaddrCtl struct { + Sc_len uint8 + Sc_family uint8 + Ss_sysaddr uint16 + Sc_id uint32 + Sc_unit uint32 + Sc_reserved [5]uint32 +} + type _Socklen uint32 type Linger struct { @@ -221,10 +233,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -262,6 +272,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 + SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 @@ -309,7 +320,6 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } @@ -352,7 +362,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -373,7 +382,6 @@ type IfmaMsghdr2 struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Refcount int32 } @@ -382,7 +390,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -404,7 +411,8 @@ type RtMetrics struct { Rtt uint32 Rttvar uint32 Pksent uint32 - Filler [4]uint32 + State uint32 + Filler [3]uint32 } const ( @@ -427,7 +435,6 @@ type BpfStat struct { type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } @@ -452,7 +459,6 @@ type Termios struct { Cflag uint64 Lflag uint64 Cc [20]uint8 - _ [4]byte Ispeed uint64 Ospeed uint64 } @@ -507,3 +513,8 @@ type Clockinfo struct { Stathz int32 Profhz int32 } + +type CtlInfo struct { + Id uint32 + Name [96]byte +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go index 4fe4c9cd73e..98be973ef94 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm.go @@ -1,6 +1,5 @@ -// NOTE: cgo can't generate struct Stat_t and struct Statfs_t yet -// Created by cgo -godefs - DO NOT EDIT -// cgo -godefs types_darwin.go +// cgo -godefs types_darwin.go | go run mkpost.go +// Code generated by the command above; see README.md. DO NOT EDIT. // +build arm,darwin @@ -31,7 +30,7 @@ type Timeval struct { Usec int32 } -type Timeval32 [0]byte +type Timeval32 struct{} type Rusage struct { Utime Timeval @@ -93,9 +92,9 @@ type Statfs_t struct { Type uint32 Flags uint32 Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 + Fstypename [16]byte + Mntonname [1024]byte + Mntfromname [1024]byte Reserved [8]uint32 } @@ -146,6 +145,10 @@ type Dirent struct { _ [3]byte } +const ( + PathMax = 0x400 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 @@ -191,6 +194,15 @@ type RawSockaddrAny struct { Pad [92]int8 } +type RawSockaddrCtl struct { + Sc_len uint8 + Sc_family uint8 + Ss_sysaddr uint16 + Sc_id uint32 + Sc_unit uint32 + Sc_reserved [5]uint32 +} + type _Socklen uint32 type Linger struct { @@ -255,6 +267,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 + SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 @@ -302,7 +315,6 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } @@ -345,7 +357,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -366,7 +377,6 @@ type IfmaMsghdr2 struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Refcount int32 } @@ -375,7 +385,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -397,7 +406,8 @@ type RtMetrics struct { Rtt uint32 Rttvar uint32 Pksent uint32 - Filler [4]uint32 + State uint32 + Filler [3]uint32 } const ( @@ -498,3 +508,8 @@ type Clockinfo struct { Stathz int32 Profhz int32 } + +type CtlInfo struct { + Id uint32 + Name [96]byte +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go index 21999e4b0a2..ddae5afe1ba 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go @@ -70,7 +70,6 @@ type Stat_t struct { Uid uint32 Gid uint32 Rdev int32 - _ [4]byte Atim Timespec Mtim Timespec Ctim Timespec @@ -97,10 +96,11 @@ type Statfs_t struct { Type uint32 Flags uint32 Fssubtype uint32 - Fstypename [16]int8 - Mntonname [1024]int8 - Mntfromname [1024]int8 - Reserved [8]uint32 + Fstypename [16]byte + Mntonname [1024]byte + Mntfromname [1024]byte + Flags_ext uint32 + Reserved [7]uint32 } type Flock_t struct { @@ -133,8 +133,7 @@ type Fbootstraptransfer_t struct { type Log2phys_t struct { Flags uint32 - _ [8]byte - _ [8]byte + _ [16]byte } type Fsid struct { @@ -151,6 +150,10 @@ type Dirent struct { _ [3]byte } +const ( + PathMax = 0x400 +) + type RawSockaddrInet4 struct { Len uint8 Family uint8 @@ -196,6 +199,15 @@ type RawSockaddrAny struct { Pad [92]int8 } +type RawSockaddrCtl struct { + Sc_len uint8 + Sc_family uint8 + Ss_sysaddr uint16 + Sc_id uint32 + Sc_unit uint32 + Sc_reserved [5]uint32 +} + type _Socklen uint32 type Linger struct { @@ -221,10 +233,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -262,6 +272,7 @@ const ( SizeofSockaddrAny = 0x6c SizeofSockaddrUnix = 0x6a SizeofSockaddrDatalink = 0x14 + SizeofSockaddrCtl = 0x20 SizeofLinger = 0x8 SizeofIPMreq = 0x8 SizeofIPv6Mreq = 0x14 @@ -309,7 +320,6 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } @@ -352,7 +362,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -373,7 +382,6 @@ type IfmaMsghdr2 struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Refcount int32 } @@ -382,7 +390,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -404,7 +411,8 @@ type RtMetrics struct { Rtt uint32 Rttvar uint32 Pksent uint32 - Filler [4]uint32 + State uint32 + Filler [3]uint32 } const ( @@ -427,7 +435,6 @@ type BpfStat struct { type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } @@ -452,7 +459,6 @@ type Termios struct { Cflag uint64 Lflag uint64 Cc [20]uint8 - _ [4]byte Ispeed uint64 Ospeed uint64 } @@ -507,3 +513,8 @@ type Clockinfo struct { Stathz int32 Profhz int32 } + +type CtlInfo struct { + Id uint32 + Name [96]byte +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go index 71ea1d6d23f..c4772df23bf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_dragonfly_amd64.go @@ -70,11 +70,11 @@ type Stat_t struct { Ctim Timespec Size int64 Blocks int64 - Blksize uint32 + _ uint32 Flags uint32 Gen uint32 Lspare int32 - Qspare1 int64 + Blksize int64 Qspare2 int64 } @@ -91,17 +91,15 @@ type Statfs_t struct { Owner uint32 Type int32 Flags int32 - _ [4]byte Syncwrites int64 Asyncwrites int64 - Fstypename [16]int8 - Mntonname [80]int8 + Fstypename [16]byte + Mntonname [80]byte Syncreads int64 Asyncreads int64 Spares1 int16 - Mntfromname [80]int8 + Mntfromname [80]byte Spares2 int16 - _ [4]byte Spare [2]int64 } @@ -202,10 +200,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Control *byte Controllen uint32 Flags int32 @@ -269,7 +265,7 @@ type FdSet struct { const ( SizeofIfMsghdr = 0xb0 SizeofIfData = 0xa0 - SizeofIfaMsghdr = 0x14 + SizeofIfaMsghdr = 0x18 SizeofIfmaMsghdr = 0x10 SizeofIfAnnounceMsghdr = 0x18 SizeofRtMsghdr = 0x98 @@ -280,10 +276,9 @@ type IfMsghdr struct { Msglen uint16 Version uint8 Type uint8 - Addrs int32 - Flags int32 Index uint16 - _ [2]byte + Flags int32 + Addrs int32 Data IfData } @@ -294,7 +289,6 @@ type IfData struct { Hdrlen uint8 Recvquota uint8 Xmitquota uint8 - _ [2]byte Mtu uint64 Metric uint64 Link_state uint64 @@ -316,24 +310,23 @@ type IfData struct { } type IfaMsghdr struct { - Msglen uint16 - Version uint8 - Type uint8 - Addrs int32 - Flags int32 - Index uint16 - _ [2]byte - Metric int32 + Msglen uint16 + Version uint8 + Type uint8 + Index uint16 + Flags int32 + Addrs int32 + Addrflags int32 + Metric int32 } type IfmaMsghdr struct { Msglen uint16 Version uint8 Type uint8 - Addrs int32 - Flags int32 Index uint16 - _ [2]byte + Flags int32 + Addrs int32 } type IfAnnounceMsghdr struct { @@ -350,7 +343,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -374,7 +366,6 @@ type RtMetrics struct { Hopcount uint64 Mssopt uint16 Pad uint16 - _ [4]byte Msl uint64 Iwmaxsegs uint64 Iwcapsegs uint64 @@ -400,7 +391,6 @@ type BpfStat struct { type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go index a92a5019afa..a96ad4c299d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -462,166 +462,107 @@ const ( ) const ( - NDA_UNSPEC = 0x0 - NDA_DST = 0x1 - NDA_LLADDR = 0x2 - NDA_CACHEINFO = 0x3 - NDA_PROBES = 0x4 - NDA_VLAN = 0x5 - NDA_PORT = 0x6 - NDA_VNI = 0x7 - NDA_IFINDEX = 0x8 - NDA_MASTER = 0x9 - NDA_LINK_NETNSID = 0xa - NDA_SRC_VNI = 0xb - NTF_USE = 0x1 - NTF_SELF = 0x2 - NTF_MASTER = 0x4 - NTF_PROXY = 0x8 - NTF_EXT_LEARNED = 0x10 - NTF_OFFLOADED = 0x20 - NTF_ROUTER = 0x80 - NUD_INCOMPLETE = 0x1 - NUD_REACHABLE = 0x2 - NUD_STALE = 0x4 - NUD_DELAY = 0x8 - NUD_PROBE = 0x10 - NUD_FAILED = 0x20 - NUD_NOARP = 0x40 - NUD_PERMANENT = 0x80 - NUD_NONE = 0x0 - IFA_UNSPEC = 0x0 - IFA_ADDRESS = 0x1 - IFA_LOCAL = 0x2 - IFA_LABEL = 0x3 - IFA_BROADCAST = 0x4 - IFA_ANYCAST = 0x5 - IFA_CACHEINFO = 0x6 - IFA_MULTICAST = 0x7 - IFA_FLAGS = 0x8 - IFA_RT_PRIORITY = 0x9 - IFA_TARGET_NETNSID = 0xa - IFLA_UNSPEC = 0x0 - IFLA_ADDRESS = 0x1 - IFLA_BROADCAST = 0x2 - IFLA_IFNAME = 0x3 - IFLA_MTU = 0x4 - IFLA_LINK = 0x5 - IFLA_QDISC = 0x6 - IFLA_STATS = 0x7 - IFLA_COST = 0x8 - IFLA_PRIORITY = 0x9 - IFLA_MASTER = 0xa - IFLA_WIRELESS = 0xb - IFLA_PROTINFO = 0xc - IFLA_TXQLEN = 0xd - IFLA_MAP = 0xe - IFLA_WEIGHT = 0xf - IFLA_OPERSTATE = 0x10 - IFLA_LINKMODE = 0x11 - IFLA_LINKINFO = 0x12 - IFLA_NET_NS_PID = 0x13 - IFLA_IFALIAS = 0x14 - IFLA_NUM_VF = 0x15 - IFLA_VFINFO_LIST = 0x16 - IFLA_STATS64 = 0x17 - IFLA_VF_PORTS = 0x18 - IFLA_PORT_SELF = 0x19 - IFLA_AF_SPEC = 0x1a - IFLA_GROUP = 0x1b - IFLA_NET_NS_FD = 0x1c - IFLA_EXT_MASK = 0x1d - IFLA_PROMISCUITY = 0x1e - IFLA_NUM_TX_QUEUES = 0x1f - IFLA_NUM_RX_QUEUES = 0x20 - IFLA_CARRIER = 0x21 - IFLA_PHYS_PORT_ID = 0x22 - IFLA_CARRIER_CHANGES = 0x23 - IFLA_PHYS_SWITCH_ID = 0x24 - IFLA_LINK_NETNSID = 0x25 - IFLA_PHYS_PORT_NAME = 0x26 - IFLA_PROTO_DOWN = 0x27 - IFLA_GSO_MAX_SEGS = 0x28 - IFLA_GSO_MAX_SIZE = 0x29 - IFLA_PAD = 0x2a - IFLA_XDP = 0x2b - IFLA_EVENT = 0x2c - IFLA_NEW_NETNSID = 0x2d - IFLA_IF_NETNSID = 0x2e - IFLA_TARGET_NETNSID = 0x2e - IFLA_CARRIER_UP_COUNT = 0x2f - IFLA_CARRIER_DOWN_COUNT = 0x30 - IFLA_NEW_IFINDEX = 0x31 - IFLA_MIN_MTU = 0x32 - IFLA_MAX_MTU = 0x33 - IFLA_MAX = 0x36 - IFLA_INFO_KIND = 0x1 - IFLA_INFO_DATA = 0x2 - IFLA_INFO_XSTATS = 0x3 - IFLA_INFO_SLAVE_KIND = 0x4 - IFLA_INFO_SLAVE_DATA = 0x5 - RT_SCOPE_UNIVERSE = 0x0 - RT_SCOPE_SITE = 0xc8 - RT_SCOPE_LINK = 0xfd - RT_SCOPE_HOST = 0xfe - RT_SCOPE_NOWHERE = 0xff - RT_TABLE_UNSPEC = 0x0 - RT_TABLE_COMPAT = 0xfc - RT_TABLE_DEFAULT = 0xfd - RT_TABLE_MAIN = 0xfe - RT_TABLE_LOCAL = 0xff - RT_TABLE_MAX = 0xffffffff - RTA_UNSPEC = 0x0 - RTA_DST = 0x1 - RTA_SRC = 0x2 - RTA_IIF = 0x3 - RTA_OIF = 0x4 - RTA_GATEWAY = 0x5 - RTA_PRIORITY = 0x6 - RTA_PREFSRC = 0x7 - RTA_METRICS = 0x8 - RTA_MULTIPATH = 0x9 - RTA_FLOW = 0xb - RTA_CACHEINFO = 0xc - RTA_TABLE = 0xf - RTA_MARK = 0x10 - RTA_MFC_STATS = 0x11 - RTA_VIA = 0x12 - RTA_NEWDST = 0x13 - RTA_PREF = 0x14 - RTA_ENCAP_TYPE = 0x15 - RTA_ENCAP = 0x16 - RTA_EXPIRES = 0x17 - RTA_PAD = 0x18 - RTA_UID = 0x19 - RTA_TTL_PROPAGATE = 0x1a - RTA_IP_PROTO = 0x1b - RTA_SPORT = 0x1c - RTA_DPORT = 0x1d - RTN_UNSPEC = 0x0 - RTN_UNICAST = 0x1 - RTN_LOCAL = 0x2 - RTN_BROADCAST = 0x3 - RTN_ANYCAST = 0x4 - RTN_MULTICAST = 0x5 - RTN_BLACKHOLE = 0x6 - RTN_UNREACHABLE = 0x7 - RTN_PROHIBIT = 0x8 - RTN_THROW = 0x9 - RTN_NAT = 0xa - RTN_XRESOLVE = 0xb - SizeofNlMsghdr = 0x10 - SizeofNlMsgerr = 0x14 - SizeofRtGenmsg = 0x1 - SizeofNlAttr = 0x4 - SizeofRtAttr = 0x4 - SizeofIfInfomsg = 0x10 - SizeofIfAddrmsg = 0x8 - SizeofIfaCacheinfo = 0x10 - SizeofRtMsg = 0xc - SizeofRtNexthop = 0x8 - SizeofNdUseroptmsg = 0x10 - SizeofNdMsg = 0xc + NDA_UNSPEC = 0x0 + NDA_DST = 0x1 + NDA_LLADDR = 0x2 + NDA_CACHEINFO = 0x3 + NDA_PROBES = 0x4 + NDA_VLAN = 0x5 + NDA_PORT = 0x6 + NDA_VNI = 0x7 + NDA_IFINDEX = 0x8 + NDA_MASTER = 0x9 + NDA_LINK_NETNSID = 0xa + NDA_SRC_VNI = 0xb + NTF_USE = 0x1 + NTF_SELF = 0x2 + NTF_MASTER = 0x4 + NTF_PROXY = 0x8 + NTF_EXT_LEARNED = 0x10 + NTF_OFFLOADED = 0x20 + NTF_ROUTER = 0x80 + NUD_INCOMPLETE = 0x1 + NUD_REACHABLE = 0x2 + NUD_STALE = 0x4 + NUD_DELAY = 0x8 + NUD_PROBE = 0x10 + NUD_FAILED = 0x20 + NUD_NOARP = 0x40 + NUD_PERMANENT = 0x80 + NUD_NONE = 0x0 + IFA_UNSPEC = 0x0 + IFA_ADDRESS = 0x1 + IFA_LOCAL = 0x2 + IFA_LABEL = 0x3 + IFA_BROADCAST = 0x4 + IFA_ANYCAST = 0x5 + IFA_CACHEINFO = 0x6 + IFA_MULTICAST = 0x7 + IFA_FLAGS = 0x8 + IFA_RT_PRIORITY = 0x9 + IFA_TARGET_NETNSID = 0xa + RT_SCOPE_UNIVERSE = 0x0 + RT_SCOPE_SITE = 0xc8 + RT_SCOPE_LINK = 0xfd + RT_SCOPE_HOST = 0xfe + RT_SCOPE_NOWHERE = 0xff + RT_TABLE_UNSPEC = 0x0 + RT_TABLE_COMPAT = 0xfc + RT_TABLE_DEFAULT = 0xfd + RT_TABLE_MAIN = 0xfe + RT_TABLE_LOCAL = 0xff + RT_TABLE_MAX = 0xffffffff + RTA_UNSPEC = 0x0 + RTA_DST = 0x1 + RTA_SRC = 0x2 + RTA_IIF = 0x3 + RTA_OIF = 0x4 + RTA_GATEWAY = 0x5 + RTA_PRIORITY = 0x6 + RTA_PREFSRC = 0x7 + RTA_METRICS = 0x8 + RTA_MULTIPATH = 0x9 + RTA_FLOW = 0xb + RTA_CACHEINFO = 0xc + RTA_TABLE = 0xf + RTA_MARK = 0x10 + RTA_MFC_STATS = 0x11 + RTA_VIA = 0x12 + RTA_NEWDST = 0x13 + RTA_PREF = 0x14 + RTA_ENCAP_TYPE = 0x15 + RTA_ENCAP = 0x16 + RTA_EXPIRES = 0x17 + RTA_PAD = 0x18 + RTA_UID = 0x19 + RTA_TTL_PROPAGATE = 0x1a + RTA_IP_PROTO = 0x1b + RTA_SPORT = 0x1c + RTA_DPORT = 0x1d + RTN_UNSPEC = 0x0 + RTN_UNICAST = 0x1 + RTN_LOCAL = 0x2 + RTN_BROADCAST = 0x3 + RTN_ANYCAST = 0x4 + RTN_MULTICAST = 0x5 + RTN_BLACKHOLE = 0x6 + RTN_UNREACHABLE = 0x7 + RTN_PROHIBIT = 0x8 + RTN_THROW = 0x9 + RTN_NAT = 0xa + RTN_XRESOLVE = 0xb + SizeofNlMsghdr = 0x10 + SizeofNlMsgerr = 0x14 + SizeofRtGenmsg = 0x1 + SizeofNlAttr = 0x4 + SizeofRtAttr = 0x4 + SizeofIfInfomsg = 0x10 + SizeofIfAddrmsg = 0x8 + SizeofIfaCacheinfo = 0x10 + SizeofRtMsg = 0xc + SizeofRtNexthop = 0x8 + SizeofNdUseroptmsg = 0x10 + SizeofNdMsg = 0xc ) type NlMsghdr struct { @@ -823,8 +764,6 @@ type SignalfdSiginfo struct { _ [28]uint8 } -const PERF_IOC_FLAG_GROUP = 0x1 - type Winsize struct { Row uint16 Col uint16 @@ -948,7 +887,10 @@ type PerfEventMmapPage struct { Time_offset uint64 Time_zero uint64 Size uint32 - _ [948]uint8 + _ uint32 + Time_cycles uint64 + Time_mask uint64 + _ [928]uint8 Data_head uint64 Data_tail uint64 Data_offset uint64 @@ -990,13 +932,13 @@ const ( ) const ( - PERF_TYPE_HARDWARE = 0x0 - PERF_TYPE_SOFTWARE = 0x1 - PERF_TYPE_TRACEPOINT = 0x2 - PERF_TYPE_HW_CACHE = 0x3 - PERF_TYPE_RAW = 0x4 - PERF_TYPE_BREAKPOINT = 0x5 - + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + PERF_TYPE_MAX = 0x6 PERF_COUNT_HW_CPU_CYCLES = 0x0 PERF_COUNT_HW_INSTRUCTIONS = 0x1 PERF_COUNT_HW_CACHE_REFERENCES = 0x2 @@ -1007,106 +949,163 @@ const ( PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 - - PERF_COUNT_HW_CACHE_L1D = 0x0 - PERF_COUNT_HW_CACHE_L1I = 0x1 - PERF_COUNT_HW_CACHE_LL = 0x2 - PERF_COUNT_HW_CACHE_DTLB = 0x3 - PERF_COUNT_HW_CACHE_ITLB = 0x4 - PERF_COUNT_HW_CACHE_BPU = 0x5 - PERF_COUNT_HW_CACHE_NODE = 0x6 - - PERF_COUNT_HW_CACHE_OP_READ = 0x0 - PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 - PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 - - PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 - PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 - - PERF_COUNT_SW_CPU_CLOCK = 0x0 - PERF_COUNT_SW_TASK_CLOCK = 0x1 - PERF_COUNT_SW_PAGE_FAULTS = 0x2 - PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 - PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 - PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 - PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 - PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 - PERF_COUNT_SW_EMULATION_FAULTS = 0x8 - PERF_COUNT_SW_DUMMY = 0x9 - PERF_COUNT_SW_BPF_OUTPUT = 0xa - - PERF_SAMPLE_IP = 0x1 - PERF_SAMPLE_TID = 0x2 - PERF_SAMPLE_TIME = 0x4 - PERF_SAMPLE_ADDR = 0x8 - PERF_SAMPLE_READ = 0x10 - PERF_SAMPLE_CALLCHAIN = 0x20 - PERF_SAMPLE_ID = 0x40 - PERF_SAMPLE_CPU = 0x80 - PERF_SAMPLE_PERIOD = 0x100 - PERF_SAMPLE_STREAM_ID = 0x200 - PERF_SAMPLE_RAW = 0x400 - PERF_SAMPLE_BRANCH_STACK = 0x800 - PERF_SAMPLE_REGS_USER = 0x1000 - PERF_SAMPLE_STACK_USER = 0x2000 - PERF_SAMPLE_WEIGHT = 0x4000 - PERF_SAMPLE_DATA_SRC = 0x8000 - PERF_SAMPLE_IDENTIFIER = 0x10000 - PERF_SAMPLE_TRANSACTION = 0x20000 - PERF_SAMPLE_REGS_INTR = 0x40000 - - PERF_SAMPLE_BRANCH_USER = 0x1 - PERF_SAMPLE_BRANCH_KERNEL = 0x2 - PERF_SAMPLE_BRANCH_HV = 0x4 - PERF_SAMPLE_BRANCH_ANY = 0x8 - PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 - PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 - PERF_SAMPLE_BRANCH_IND_CALL = 0x40 - PERF_SAMPLE_BRANCH_ABORT_TX = 0x80 - PERF_SAMPLE_BRANCH_IN_TX = 0x100 - PERF_SAMPLE_BRANCH_NO_TX = 0x200 - PERF_SAMPLE_BRANCH_COND = 0x400 - PERF_SAMPLE_BRANCH_CALL_STACK = 0x800 - PERF_SAMPLE_BRANCH_IND_JUMP = 0x1000 - PERF_SAMPLE_BRANCH_CALL = 0x2000 - PERF_SAMPLE_BRANCH_NO_FLAGS = 0x4000 - PERF_SAMPLE_BRANCH_NO_CYCLES = 0x8000 - PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000 - - PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 - PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 - PERF_FORMAT_ID = 0x4 - PERF_FORMAT_GROUP = 0x8 - - PERF_RECORD_MMAP = 0x1 - PERF_RECORD_LOST = 0x2 - PERF_RECORD_COMM = 0x3 - PERF_RECORD_EXIT = 0x4 - PERF_RECORD_THROTTLE = 0x5 - PERF_RECORD_UNTHROTTLE = 0x6 - PERF_RECORD_FORK = 0x7 - PERF_RECORD_READ = 0x8 - PERF_RECORD_SAMPLE = 0x9 - PERF_RECORD_MMAP2 = 0xa - PERF_RECORD_AUX = 0xb - PERF_RECORD_ITRACE_START = 0xc - PERF_RECORD_LOST_SAMPLES = 0xd - PERF_RECORD_SWITCH = 0xe - PERF_RECORD_SWITCH_CPU_WIDE = 0xf - PERF_RECORD_NAMESPACES = 0x10 - - PERF_CONTEXT_HV = -0x20 - PERF_CONTEXT_KERNEL = -0x80 - PERF_CONTEXT_USER = -0x200 - - PERF_CONTEXT_GUEST = -0x800 - PERF_CONTEXT_GUEST_KERNEL = -0x880 - PERF_CONTEXT_GUEST_USER = -0xa00 - - PERF_FLAG_FD_NO_GROUP = 0x1 - PERF_FLAG_FD_OUTPUT = 0x2 - PERF_FLAG_PID_CGROUP = 0x4 - PERF_FLAG_FD_CLOEXEC = 0x8 + PERF_COUNT_HW_MAX = 0xa + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + PERF_COUNT_HW_CACHE_MAX = 0x7 + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + PERF_COUNT_HW_CACHE_OP_MAX = 0x3 + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + PERF_COUNT_HW_CACHE_RESULT_MAX = 0x2 + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + PERF_COUNT_SW_BPF_OUTPUT = 0xa + PERF_COUNT_SW_MAX = 0xb + PERF_SAMPLE_IP = 0x1 + PERF_SAMPLE_TID = 0x2 + PERF_SAMPLE_TIME = 0x4 + PERF_SAMPLE_ADDR = 0x8 + PERF_SAMPLE_READ = 0x10 + PERF_SAMPLE_CALLCHAIN = 0x20 + PERF_SAMPLE_ID = 0x40 + PERF_SAMPLE_CPU = 0x80 + PERF_SAMPLE_PERIOD = 0x100 + PERF_SAMPLE_STREAM_ID = 0x200 + PERF_SAMPLE_RAW = 0x400 + PERF_SAMPLE_BRANCH_STACK = 0x800 + PERF_SAMPLE_REGS_USER = 0x1000 + PERF_SAMPLE_STACK_USER = 0x2000 + PERF_SAMPLE_WEIGHT = 0x4000 + PERF_SAMPLE_DATA_SRC = 0x8000 + PERF_SAMPLE_IDENTIFIER = 0x10000 + PERF_SAMPLE_TRANSACTION = 0x20000 + PERF_SAMPLE_REGS_INTR = 0x40000 + PERF_SAMPLE_PHYS_ADDR = 0x80000 + PERF_SAMPLE_AUX = 0x100000 + PERF_SAMPLE_CGROUP = 0x200000 + PERF_SAMPLE_MAX = 0x400000 + PERF_SAMPLE_BRANCH_USER_SHIFT = 0x0 + PERF_SAMPLE_BRANCH_KERNEL_SHIFT = 0x1 + PERF_SAMPLE_BRANCH_HV_SHIFT = 0x2 + PERF_SAMPLE_BRANCH_ANY_SHIFT = 0x3 + PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT = 0x4 + PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT = 0x5 + PERF_SAMPLE_BRANCH_IND_CALL_SHIFT = 0x6 + PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT = 0x7 + PERF_SAMPLE_BRANCH_IN_TX_SHIFT = 0x8 + PERF_SAMPLE_BRANCH_NO_TX_SHIFT = 0x9 + PERF_SAMPLE_BRANCH_COND_SHIFT = 0xa + PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT = 0xb + PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT = 0xc + PERF_SAMPLE_BRANCH_CALL_SHIFT = 0xd + PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 0xe + PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 0xf + PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 0x10 + PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 0x11 + PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x12 + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + PERF_SAMPLE_BRANCH_ABORT_TX = 0x80 + PERF_SAMPLE_BRANCH_IN_TX = 0x100 + PERF_SAMPLE_BRANCH_NO_TX = 0x200 + PERF_SAMPLE_BRANCH_COND = 0x400 + PERF_SAMPLE_BRANCH_CALL_STACK = 0x800 + PERF_SAMPLE_BRANCH_IND_JUMP = 0x1000 + PERF_SAMPLE_BRANCH_CALL = 0x2000 + PERF_SAMPLE_BRANCH_NO_FLAGS = 0x4000 + PERF_SAMPLE_BRANCH_NO_CYCLES = 0x8000 + PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000 + PERF_SAMPLE_BRANCH_HW_INDEX = 0x20000 + PERF_SAMPLE_BRANCH_MAX = 0x40000 + PERF_BR_UNKNOWN = 0x0 + PERF_BR_COND = 0x1 + PERF_BR_UNCOND = 0x2 + PERF_BR_IND = 0x3 + PERF_BR_CALL = 0x4 + PERF_BR_IND_CALL = 0x5 + PERF_BR_RET = 0x6 + PERF_BR_SYSCALL = 0x7 + PERF_BR_SYSRET = 0x8 + PERF_BR_COND_CALL = 0x9 + PERF_BR_COND_RET = 0xa + PERF_BR_MAX = 0xb + PERF_SAMPLE_REGS_ABI_NONE = 0x0 + PERF_SAMPLE_REGS_ABI_32 = 0x1 + PERF_SAMPLE_REGS_ABI_64 = 0x2 + PERF_TXN_ELISION = 0x1 + PERF_TXN_TRANSACTION = 0x2 + PERF_TXN_SYNC = 0x4 + PERF_TXN_ASYNC = 0x8 + PERF_TXN_RETRY = 0x10 + PERF_TXN_CONFLICT = 0x20 + PERF_TXN_CAPACITY_WRITE = 0x40 + PERF_TXN_CAPACITY_READ = 0x80 + PERF_TXN_MAX = 0x100 + PERF_TXN_ABORT_MASK = -0x100000000 + PERF_TXN_ABORT_SHIFT = 0x20 + PERF_FORMAT_TOTAL_TIME_ENABLED = 0x1 + PERF_FORMAT_TOTAL_TIME_RUNNING = 0x2 + PERF_FORMAT_ID = 0x4 + PERF_FORMAT_GROUP = 0x8 + PERF_FORMAT_MAX = 0x10 + PERF_IOC_FLAG_GROUP = 0x1 + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + PERF_RECORD_MMAP2 = 0xa + PERF_RECORD_AUX = 0xb + PERF_RECORD_ITRACE_START = 0xc + PERF_RECORD_LOST_SAMPLES = 0xd + PERF_RECORD_SWITCH = 0xe + PERF_RECORD_SWITCH_CPU_WIDE = 0xf + PERF_RECORD_NAMESPACES = 0x10 + PERF_RECORD_KSYMBOL = 0x11 + PERF_RECORD_BPF_EVENT = 0x12 + PERF_RECORD_CGROUP = 0x13 + PERF_RECORD_TEXT_POKE = 0x14 + PERF_RECORD_MAX = 0x15 + PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0x0 + PERF_RECORD_KSYMBOL_TYPE_BPF = 0x1 + PERF_RECORD_KSYMBOL_TYPE_OOL = 0x2 + PERF_RECORD_KSYMBOL_TYPE_MAX = 0x3 + PERF_BPF_EVENT_UNKNOWN = 0x0 + PERF_BPF_EVENT_PROG_LOAD = 0x1 + PERF_BPF_EVENT_PROG_UNLOAD = 0x2 + PERF_BPF_EVENT_MAX = 0x3 + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + PERF_CONTEXT_MAX = -0xfff ) type TCPMD5Sig struct { @@ -1325,6 +1324,394 @@ const ( SizeofTpacketStatsV3 = 0xc ) +const ( + IFLA_UNSPEC = 0x0 + IFLA_ADDRESS = 0x1 + IFLA_BROADCAST = 0x2 + IFLA_IFNAME = 0x3 + IFLA_MTU = 0x4 + IFLA_LINK = 0x5 + IFLA_QDISC = 0x6 + IFLA_STATS = 0x7 + IFLA_COST = 0x8 + IFLA_PRIORITY = 0x9 + IFLA_MASTER = 0xa + IFLA_WIRELESS = 0xb + IFLA_PROTINFO = 0xc + IFLA_TXQLEN = 0xd + IFLA_MAP = 0xe + IFLA_WEIGHT = 0xf + IFLA_OPERSTATE = 0x10 + IFLA_LINKMODE = 0x11 + IFLA_LINKINFO = 0x12 + IFLA_NET_NS_PID = 0x13 + IFLA_IFALIAS = 0x14 + IFLA_NUM_VF = 0x15 + IFLA_VFINFO_LIST = 0x16 + IFLA_STATS64 = 0x17 + IFLA_VF_PORTS = 0x18 + IFLA_PORT_SELF = 0x19 + IFLA_AF_SPEC = 0x1a + IFLA_GROUP = 0x1b + IFLA_NET_NS_FD = 0x1c + IFLA_EXT_MASK = 0x1d + IFLA_PROMISCUITY = 0x1e + IFLA_NUM_TX_QUEUES = 0x1f + IFLA_NUM_RX_QUEUES = 0x20 + IFLA_CARRIER = 0x21 + IFLA_PHYS_PORT_ID = 0x22 + IFLA_CARRIER_CHANGES = 0x23 + IFLA_PHYS_SWITCH_ID = 0x24 + IFLA_LINK_NETNSID = 0x25 + IFLA_PHYS_PORT_NAME = 0x26 + IFLA_PROTO_DOWN = 0x27 + IFLA_GSO_MAX_SEGS = 0x28 + IFLA_GSO_MAX_SIZE = 0x29 + IFLA_PAD = 0x2a + IFLA_XDP = 0x2b + IFLA_EVENT = 0x2c + IFLA_NEW_NETNSID = 0x2d + IFLA_IF_NETNSID = 0x2e + IFLA_TARGET_NETNSID = 0x2e + IFLA_CARRIER_UP_COUNT = 0x2f + IFLA_CARRIER_DOWN_COUNT = 0x30 + IFLA_NEW_IFINDEX = 0x31 + IFLA_MIN_MTU = 0x32 + IFLA_MAX_MTU = 0x33 + IFLA_PROP_LIST = 0x34 + IFLA_ALT_IFNAME = 0x35 + IFLA_PERM_ADDRESS = 0x36 + IFLA_INET_UNSPEC = 0x0 + IFLA_INET_CONF = 0x1 + IFLA_INET6_UNSPEC = 0x0 + IFLA_INET6_FLAGS = 0x1 + IFLA_INET6_CONF = 0x2 + IFLA_INET6_STATS = 0x3 + IFLA_INET6_MCAST = 0x4 + IFLA_INET6_CACHEINFO = 0x5 + IFLA_INET6_ICMP6STATS = 0x6 + IFLA_INET6_TOKEN = 0x7 + IFLA_INET6_ADDR_GEN_MODE = 0x8 + IFLA_BR_UNSPEC = 0x0 + IFLA_BR_FORWARD_DELAY = 0x1 + IFLA_BR_HELLO_TIME = 0x2 + IFLA_BR_MAX_AGE = 0x3 + IFLA_BR_AGEING_TIME = 0x4 + IFLA_BR_STP_STATE = 0x5 + IFLA_BR_PRIORITY = 0x6 + IFLA_BR_VLAN_FILTERING = 0x7 + IFLA_BR_VLAN_PROTOCOL = 0x8 + IFLA_BR_GROUP_FWD_MASK = 0x9 + IFLA_BR_ROOT_ID = 0xa + IFLA_BR_BRIDGE_ID = 0xb + IFLA_BR_ROOT_PORT = 0xc + IFLA_BR_ROOT_PATH_COST = 0xd + IFLA_BR_TOPOLOGY_CHANGE = 0xe + IFLA_BR_TOPOLOGY_CHANGE_DETECTED = 0xf + IFLA_BR_HELLO_TIMER = 0x10 + IFLA_BR_TCN_TIMER = 0x11 + IFLA_BR_TOPOLOGY_CHANGE_TIMER = 0x12 + IFLA_BR_GC_TIMER = 0x13 + IFLA_BR_GROUP_ADDR = 0x14 + IFLA_BR_FDB_FLUSH = 0x15 + IFLA_BR_MCAST_ROUTER = 0x16 + IFLA_BR_MCAST_SNOOPING = 0x17 + IFLA_BR_MCAST_QUERY_USE_IFADDR = 0x18 + IFLA_BR_MCAST_QUERIER = 0x19 + IFLA_BR_MCAST_HASH_ELASTICITY = 0x1a + IFLA_BR_MCAST_HASH_MAX = 0x1b + IFLA_BR_MCAST_LAST_MEMBER_CNT = 0x1c + IFLA_BR_MCAST_STARTUP_QUERY_CNT = 0x1d + IFLA_BR_MCAST_LAST_MEMBER_INTVL = 0x1e + IFLA_BR_MCAST_MEMBERSHIP_INTVL = 0x1f + IFLA_BR_MCAST_QUERIER_INTVL = 0x20 + IFLA_BR_MCAST_QUERY_INTVL = 0x21 + IFLA_BR_MCAST_QUERY_RESPONSE_INTVL = 0x22 + IFLA_BR_MCAST_STARTUP_QUERY_INTVL = 0x23 + IFLA_BR_NF_CALL_IPTABLES = 0x24 + IFLA_BR_NF_CALL_IP6TABLES = 0x25 + IFLA_BR_NF_CALL_ARPTABLES = 0x26 + IFLA_BR_VLAN_DEFAULT_PVID = 0x27 + IFLA_BR_PAD = 0x28 + IFLA_BR_VLAN_STATS_ENABLED = 0x29 + IFLA_BR_MCAST_STATS_ENABLED = 0x2a + IFLA_BR_MCAST_IGMP_VERSION = 0x2b + IFLA_BR_MCAST_MLD_VERSION = 0x2c + IFLA_BR_VLAN_STATS_PER_PORT = 0x2d + IFLA_BR_MULTI_BOOLOPT = 0x2e + IFLA_BRPORT_UNSPEC = 0x0 + IFLA_BRPORT_STATE = 0x1 + IFLA_BRPORT_PRIORITY = 0x2 + IFLA_BRPORT_COST = 0x3 + IFLA_BRPORT_MODE = 0x4 + IFLA_BRPORT_GUARD = 0x5 + IFLA_BRPORT_PROTECT = 0x6 + IFLA_BRPORT_FAST_LEAVE = 0x7 + IFLA_BRPORT_LEARNING = 0x8 + IFLA_BRPORT_UNICAST_FLOOD = 0x9 + IFLA_BRPORT_PROXYARP = 0xa + IFLA_BRPORT_LEARNING_SYNC = 0xb + IFLA_BRPORT_PROXYARP_WIFI = 0xc + IFLA_BRPORT_ROOT_ID = 0xd + IFLA_BRPORT_BRIDGE_ID = 0xe + IFLA_BRPORT_DESIGNATED_PORT = 0xf + IFLA_BRPORT_DESIGNATED_COST = 0x10 + IFLA_BRPORT_ID = 0x11 + IFLA_BRPORT_NO = 0x12 + IFLA_BRPORT_TOPOLOGY_CHANGE_ACK = 0x13 + IFLA_BRPORT_CONFIG_PENDING = 0x14 + IFLA_BRPORT_MESSAGE_AGE_TIMER = 0x15 + IFLA_BRPORT_FORWARD_DELAY_TIMER = 0x16 + IFLA_BRPORT_HOLD_TIMER = 0x17 + IFLA_BRPORT_FLUSH = 0x18 + IFLA_BRPORT_MULTICAST_ROUTER = 0x19 + IFLA_BRPORT_PAD = 0x1a + IFLA_BRPORT_MCAST_FLOOD = 0x1b + IFLA_BRPORT_MCAST_TO_UCAST = 0x1c + IFLA_BRPORT_VLAN_TUNNEL = 0x1d + IFLA_BRPORT_BCAST_FLOOD = 0x1e + IFLA_BRPORT_GROUP_FWD_MASK = 0x1f + IFLA_BRPORT_NEIGH_SUPPRESS = 0x20 + IFLA_BRPORT_ISOLATED = 0x21 + IFLA_BRPORT_BACKUP_PORT = 0x22 + IFLA_BRPORT_MRP_RING_OPEN = 0x23 + IFLA_INFO_UNSPEC = 0x0 + IFLA_INFO_KIND = 0x1 + IFLA_INFO_DATA = 0x2 + IFLA_INFO_XSTATS = 0x3 + IFLA_INFO_SLAVE_KIND = 0x4 + IFLA_INFO_SLAVE_DATA = 0x5 + IFLA_VLAN_UNSPEC = 0x0 + IFLA_VLAN_ID = 0x1 + IFLA_VLAN_FLAGS = 0x2 + IFLA_VLAN_EGRESS_QOS = 0x3 + IFLA_VLAN_INGRESS_QOS = 0x4 + IFLA_VLAN_PROTOCOL = 0x5 + IFLA_VLAN_QOS_UNSPEC = 0x0 + IFLA_VLAN_QOS_MAPPING = 0x1 + IFLA_MACVLAN_UNSPEC = 0x0 + IFLA_MACVLAN_MODE = 0x1 + IFLA_MACVLAN_FLAGS = 0x2 + IFLA_MACVLAN_MACADDR_MODE = 0x3 + IFLA_MACVLAN_MACADDR = 0x4 + IFLA_MACVLAN_MACADDR_DATA = 0x5 + IFLA_MACVLAN_MACADDR_COUNT = 0x6 + IFLA_VRF_UNSPEC = 0x0 + IFLA_VRF_TABLE = 0x1 + IFLA_VRF_PORT_UNSPEC = 0x0 + IFLA_VRF_PORT_TABLE = 0x1 + IFLA_MACSEC_UNSPEC = 0x0 + IFLA_MACSEC_SCI = 0x1 + IFLA_MACSEC_PORT = 0x2 + IFLA_MACSEC_ICV_LEN = 0x3 + IFLA_MACSEC_CIPHER_SUITE = 0x4 + IFLA_MACSEC_WINDOW = 0x5 + IFLA_MACSEC_ENCODING_SA = 0x6 + IFLA_MACSEC_ENCRYPT = 0x7 + IFLA_MACSEC_PROTECT = 0x8 + IFLA_MACSEC_INC_SCI = 0x9 + IFLA_MACSEC_ES = 0xa + IFLA_MACSEC_SCB = 0xb + IFLA_MACSEC_REPLAY_PROTECT = 0xc + IFLA_MACSEC_VALIDATION = 0xd + IFLA_MACSEC_PAD = 0xe + IFLA_MACSEC_OFFLOAD = 0xf + IFLA_XFRM_UNSPEC = 0x0 + IFLA_XFRM_LINK = 0x1 + IFLA_XFRM_IF_ID = 0x2 + IFLA_IPVLAN_UNSPEC = 0x0 + IFLA_IPVLAN_MODE = 0x1 + IFLA_IPVLAN_FLAGS = 0x2 + IFLA_VXLAN_UNSPEC = 0x0 + IFLA_VXLAN_ID = 0x1 + IFLA_VXLAN_GROUP = 0x2 + IFLA_VXLAN_LINK = 0x3 + IFLA_VXLAN_LOCAL = 0x4 + IFLA_VXLAN_TTL = 0x5 + IFLA_VXLAN_TOS = 0x6 + IFLA_VXLAN_LEARNING = 0x7 + IFLA_VXLAN_AGEING = 0x8 + IFLA_VXLAN_LIMIT = 0x9 + IFLA_VXLAN_PORT_RANGE = 0xa + IFLA_VXLAN_PROXY = 0xb + IFLA_VXLAN_RSC = 0xc + IFLA_VXLAN_L2MISS = 0xd + IFLA_VXLAN_L3MISS = 0xe + IFLA_VXLAN_PORT = 0xf + IFLA_VXLAN_GROUP6 = 0x10 + IFLA_VXLAN_LOCAL6 = 0x11 + IFLA_VXLAN_UDP_CSUM = 0x12 + IFLA_VXLAN_UDP_ZERO_CSUM6_TX = 0x13 + IFLA_VXLAN_UDP_ZERO_CSUM6_RX = 0x14 + IFLA_VXLAN_REMCSUM_TX = 0x15 + IFLA_VXLAN_REMCSUM_RX = 0x16 + IFLA_VXLAN_GBP = 0x17 + IFLA_VXLAN_REMCSUM_NOPARTIAL = 0x18 + IFLA_VXLAN_COLLECT_METADATA = 0x19 + IFLA_VXLAN_LABEL = 0x1a + IFLA_VXLAN_GPE = 0x1b + IFLA_VXLAN_TTL_INHERIT = 0x1c + IFLA_VXLAN_DF = 0x1d + IFLA_GENEVE_UNSPEC = 0x0 + IFLA_GENEVE_ID = 0x1 + IFLA_GENEVE_REMOTE = 0x2 + IFLA_GENEVE_TTL = 0x3 + IFLA_GENEVE_TOS = 0x4 + IFLA_GENEVE_PORT = 0x5 + IFLA_GENEVE_COLLECT_METADATA = 0x6 + IFLA_GENEVE_REMOTE6 = 0x7 + IFLA_GENEVE_UDP_CSUM = 0x8 + IFLA_GENEVE_UDP_ZERO_CSUM6_TX = 0x9 + IFLA_GENEVE_UDP_ZERO_CSUM6_RX = 0xa + IFLA_GENEVE_LABEL = 0xb + IFLA_GENEVE_TTL_INHERIT = 0xc + IFLA_GENEVE_DF = 0xd + IFLA_BAREUDP_UNSPEC = 0x0 + IFLA_BAREUDP_PORT = 0x1 + IFLA_BAREUDP_ETHERTYPE = 0x2 + IFLA_BAREUDP_SRCPORT_MIN = 0x3 + IFLA_BAREUDP_MULTIPROTO_MODE = 0x4 + IFLA_PPP_UNSPEC = 0x0 + IFLA_PPP_DEV_FD = 0x1 + IFLA_GTP_UNSPEC = 0x0 + IFLA_GTP_FD0 = 0x1 + IFLA_GTP_FD1 = 0x2 + IFLA_GTP_PDP_HASHSIZE = 0x3 + IFLA_GTP_ROLE = 0x4 + IFLA_BOND_UNSPEC = 0x0 + IFLA_BOND_MODE = 0x1 + IFLA_BOND_ACTIVE_SLAVE = 0x2 + IFLA_BOND_MIIMON = 0x3 + IFLA_BOND_UPDELAY = 0x4 + IFLA_BOND_DOWNDELAY = 0x5 + IFLA_BOND_USE_CARRIER = 0x6 + IFLA_BOND_ARP_INTERVAL = 0x7 + IFLA_BOND_ARP_IP_TARGET = 0x8 + IFLA_BOND_ARP_VALIDATE = 0x9 + IFLA_BOND_ARP_ALL_TARGETS = 0xa + IFLA_BOND_PRIMARY = 0xb + IFLA_BOND_PRIMARY_RESELECT = 0xc + IFLA_BOND_FAIL_OVER_MAC = 0xd + IFLA_BOND_XMIT_HASH_POLICY = 0xe + IFLA_BOND_RESEND_IGMP = 0xf + IFLA_BOND_NUM_PEER_NOTIF = 0x10 + IFLA_BOND_ALL_SLAVES_ACTIVE = 0x11 + IFLA_BOND_MIN_LINKS = 0x12 + IFLA_BOND_LP_INTERVAL = 0x13 + IFLA_BOND_PACKETS_PER_SLAVE = 0x14 + IFLA_BOND_AD_LACP_RATE = 0x15 + IFLA_BOND_AD_SELECT = 0x16 + IFLA_BOND_AD_INFO = 0x17 + IFLA_BOND_AD_ACTOR_SYS_PRIO = 0x18 + IFLA_BOND_AD_USER_PORT_KEY = 0x19 + IFLA_BOND_AD_ACTOR_SYSTEM = 0x1a + IFLA_BOND_TLB_DYNAMIC_LB = 0x1b + IFLA_BOND_PEER_NOTIF_DELAY = 0x1c + IFLA_BOND_AD_INFO_UNSPEC = 0x0 + IFLA_BOND_AD_INFO_AGGREGATOR = 0x1 + IFLA_BOND_AD_INFO_NUM_PORTS = 0x2 + IFLA_BOND_AD_INFO_ACTOR_KEY = 0x3 + IFLA_BOND_AD_INFO_PARTNER_KEY = 0x4 + IFLA_BOND_AD_INFO_PARTNER_MAC = 0x5 + IFLA_BOND_SLAVE_UNSPEC = 0x0 + IFLA_BOND_SLAVE_STATE = 0x1 + IFLA_BOND_SLAVE_MII_STATUS = 0x2 + IFLA_BOND_SLAVE_LINK_FAILURE_COUNT = 0x3 + IFLA_BOND_SLAVE_PERM_HWADDR = 0x4 + IFLA_BOND_SLAVE_QUEUE_ID = 0x5 + IFLA_BOND_SLAVE_AD_AGGREGATOR_ID = 0x6 + IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE = 0x7 + IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE = 0x8 + IFLA_VF_INFO_UNSPEC = 0x0 + IFLA_VF_INFO = 0x1 + IFLA_VF_UNSPEC = 0x0 + IFLA_VF_MAC = 0x1 + IFLA_VF_VLAN = 0x2 + IFLA_VF_TX_RATE = 0x3 + IFLA_VF_SPOOFCHK = 0x4 + IFLA_VF_LINK_STATE = 0x5 + IFLA_VF_RATE = 0x6 + IFLA_VF_RSS_QUERY_EN = 0x7 + IFLA_VF_STATS = 0x8 + IFLA_VF_TRUST = 0x9 + IFLA_VF_IB_NODE_GUID = 0xa + IFLA_VF_IB_PORT_GUID = 0xb + IFLA_VF_VLAN_LIST = 0xc + IFLA_VF_BROADCAST = 0xd + IFLA_VF_VLAN_INFO_UNSPEC = 0x0 + IFLA_VF_VLAN_INFO = 0x1 + IFLA_VF_LINK_STATE_AUTO = 0x0 + IFLA_VF_LINK_STATE_ENABLE = 0x1 + IFLA_VF_LINK_STATE_DISABLE = 0x2 + IFLA_VF_STATS_RX_PACKETS = 0x0 + IFLA_VF_STATS_TX_PACKETS = 0x1 + IFLA_VF_STATS_RX_BYTES = 0x2 + IFLA_VF_STATS_TX_BYTES = 0x3 + IFLA_VF_STATS_BROADCAST = 0x4 + IFLA_VF_STATS_MULTICAST = 0x5 + IFLA_VF_STATS_PAD = 0x6 + IFLA_VF_STATS_RX_DROPPED = 0x7 + IFLA_VF_STATS_TX_DROPPED = 0x8 + IFLA_VF_PORT_UNSPEC = 0x0 + IFLA_VF_PORT = 0x1 + IFLA_PORT_UNSPEC = 0x0 + IFLA_PORT_VF = 0x1 + IFLA_PORT_PROFILE = 0x2 + IFLA_PORT_VSI_TYPE = 0x3 + IFLA_PORT_INSTANCE_UUID = 0x4 + IFLA_PORT_HOST_UUID = 0x5 + IFLA_PORT_REQUEST = 0x6 + IFLA_PORT_RESPONSE = 0x7 + IFLA_IPOIB_UNSPEC = 0x0 + IFLA_IPOIB_PKEY = 0x1 + IFLA_IPOIB_MODE = 0x2 + IFLA_IPOIB_UMCAST = 0x3 + IFLA_HSR_UNSPEC = 0x0 + IFLA_HSR_SLAVE1 = 0x1 + IFLA_HSR_SLAVE2 = 0x2 + IFLA_HSR_MULTICAST_SPEC = 0x3 + IFLA_HSR_SUPERVISION_ADDR = 0x4 + IFLA_HSR_SEQ_NR = 0x5 + IFLA_HSR_VERSION = 0x6 + IFLA_STATS_UNSPEC = 0x0 + IFLA_STATS_LINK_64 = 0x1 + IFLA_STATS_LINK_XSTATS = 0x2 + IFLA_STATS_LINK_XSTATS_SLAVE = 0x3 + IFLA_STATS_LINK_OFFLOAD_XSTATS = 0x4 + IFLA_STATS_AF_SPEC = 0x5 + IFLA_OFFLOAD_XSTATS_UNSPEC = 0x0 + IFLA_OFFLOAD_XSTATS_CPU_HIT = 0x1 + IFLA_XDP_UNSPEC = 0x0 + IFLA_XDP_FD = 0x1 + IFLA_XDP_ATTACHED = 0x2 + IFLA_XDP_FLAGS = 0x3 + IFLA_XDP_PROG_ID = 0x4 + IFLA_XDP_DRV_PROG_ID = 0x5 + IFLA_XDP_SKB_PROG_ID = 0x6 + IFLA_XDP_HW_PROG_ID = 0x7 + IFLA_XDP_EXPECTED_FD = 0x8 + IFLA_EVENT_NONE = 0x0 + IFLA_EVENT_REBOOT = 0x1 + IFLA_EVENT_FEATURES = 0x2 + IFLA_EVENT_BONDING_FAILOVER = 0x3 + IFLA_EVENT_NOTIFY_PEERS = 0x4 + IFLA_EVENT_IGMP_RESEND = 0x5 + IFLA_EVENT_BONDING_OPTIONS = 0x6 + IFLA_TUN_UNSPEC = 0x0 + IFLA_TUN_OWNER = 0x1 + IFLA_TUN_GROUP = 0x2 + IFLA_TUN_TYPE = 0x3 + IFLA_TUN_PI = 0x4 + IFLA_TUN_VNET_HDR = 0x5 + IFLA_TUN_PERSIST = 0x6 + IFLA_TUN_MULTI_QUEUE = 0x7 + IFLA_TUN_NUM_QUEUES = 0x8 + IFLA_TUN_NUM_DISABLED_QUEUES = 0x9 + IFLA_RMNET_UNSPEC = 0x0 + IFLA_RMNET_MUX_ID = 0x1 + IFLA_RMNET_FLAGS = 0x2 +) + const ( NF_INET_PRE_ROUTING = 0x0 NF_INET_LOCAL_IN = 0x1 @@ -1412,7 +1799,7 @@ const ( NFT_MSG_DELOBJ = 0x14 NFT_MSG_GETOBJ_RESET = 0x15 NFT_MSG_MAX = 0x19 - NFTA_LIST_UNPEC = 0x0 + NFTA_LIST_UNSPEC = 0x0 NFTA_LIST_ELEM = 0x1 NFTA_HOOK_UNSPEC = 0x0 NFTA_HOOK_HOOKNUM = 0x1 @@ -1851,9 +2238,12 @@ type XDPMmapOffsets struct { } type XDPStatistics struct { - Rx_dropped uint64 - Rx_invalid_descs uint64 - Tx_invalid_descs uint64 + Rx_dropped uint64 + Rx_invalid_descs uint64 + Tx_invalid_descs uint64 + Rx_ring_full uint64 + Rx_fill_ring_empty_descs uint64 + Tx_ring_empty_descs uint64 } type XDPDesc struct { @@ -2500,7 +2890,7 @@ const ( DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE = 0x3c DEVLINK_ATTR_PAD = 0x3d DEVLINK_ATTR_ESWITCH_ENCAP_MODE = 0x3e - DEVLINK_ATTR_MAX = 0x90 + DEVLINK_ATTR_MAX = 0x94 DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 @@ -2567,3 +2957,27 @@ const ( CAN_RAW_FD_FRAMES = 0x5 CAN_RAW_JOIN_FILTERS = 0x6 ) + +type WatchdogInfo struct { + Options uint32 + Version uint32 + Identity [32]uint8 +} + +type PPSFData struct { + Info PPSKInfo + Timeout PPSKTime +} + +type PPSKParams struct { + Api_version int32 + Mode int32 + Assert_off_tu PPSKTime + Clear_off_tu PPSKTime +} + +type PPSKTime struct { + Sec int64 + Nsec int32 + Flags uint32 +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 73509d896a2..d54618aa61f 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -602,3 +602,18 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 +} + +const ( + PPS_GETPARAMS = 0x800470a1 + PPS_SETPARAMS = 0x400470a2 + PPS_GETCAP = 0x800470a3 + PPS_FETCH = 0xc00470a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 45eb8738b0d..741d25be957 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -619,3 +619,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 8f6b453aba5..e8d982c3df7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -596,3 +596,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800470a1 + PPS_SETPARAMS = 0x400470a2 + PPS_GETCAP = 0x800470a3 + PPS_FETCH = 0xc00470a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index b1e0c24f192..311cf2155d5 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -598,3 +598,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index fb802c3ec9b..1312bdf77fe 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -602,3 +602,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400470a1 + PPS_SETPARAMS = 0x800470a2 + PPS_GETCAP = 0x400470a3 + PPS_FETCH = 0xc00470a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 30abcf3bb8e..2a993481950 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -601,3 +601,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 99761aa9a78..f964307b293 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -601,3 +601,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index 293690348f6..ca0fab27020 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -602,3 +602,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400470a1 + PPS_SETPARAMS = 0x800470a2 + PPS_GETCAP = 0x400470a3 + PPS_FETCH = 0xc00470a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 0ca856e559b..257e0042473 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -608,3 +608,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index f50f6482eee..980dd31736a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -608,3 +608,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 4d3ac8d7b40..d9fdab20b83 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -626,3 +626,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]uint8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 349f483a80e..c25de8c679c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -622,3 +622,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x800870a1 + PPS_SETPARAMS = 0x400870a2 + PPS_GETCAP = 0x800870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index 80c73beaa15..97fca65340e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -603,3 +603,19 @@ type TIPCSIOCNodeIDReq struct { Peer uint32 Id [16]int8 } + +type PPSKInfo struct { + Assert_sequence uint32 + Clear_sequence uint32 + Assert_tu PPSKTime + Clear_tu PPSKTime + Current_mode int32 + _ [4]byte +} + +const ( + PPS_GETPARAMS = 0x400870a1 + PPS_SETPARAMS = 0x800870a2 + PPS_GETCAP = 0x400870a3 + PPS_FETCH = 0xc00870a4 +) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go index 23ed9fe51d4..db817f3ba82 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go @@ -88,7 +88,6 @@ type Stat_t struct { Mtim Timespec Ctim Timespec Blksize int32 - _ [4]byte Blocks int64 Fstype [16]int8 } @@ -96,7 +95,6 @@ type Stat_t struct { type Flock_t struct { Type int16 Whence int16 - _ [4]byte Start int64 Len int64 Sysid int32 @@ -138,12 +136,12 @@ type RawSockaddrInet4 struct { } type RawSockaddrInet6 struct { - Family uint16 - Port uint16 - Flowinfo uint32 - Addr [16]byte /* in6_addr */ - Scope_id uint32 - X__sin6_src_id uint32 + Family uint16 + Port uint16 + Flowinfo uint32 + Addr [16]byte /* in6_addr */ + Scope_id uint32 + _ uint32 } type RawSockaddrUnix struct { @@ -196,10 +194,8 @@ type IPv6Mreq struct { type Msghdr struct { Name *byte Namelen uint32 - _ [4]byte Iov *Iovec Iovlen int32 - _ [4]byte Accrights *int8 Accrightslen int32 _ [4]byte @@ -228,7 +224,7 @@ type IPv6MTUInfo struct { } type ICMPv6Filter struct { - X__icmp6_filt [8]uint32 + Filt [8]uint32 } const ( @@ -291,7 +287,6 @@ type IfMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Data IfData } @@ -299,7 +294,6 @@ type IfData struct { Type uint8 Addrlen uint8 Hdrlen uint8 - _ [1]byte Mtu uint32 Metric uint32 Baudrate uint32 @@ -324,7 +318,6 @@ type IfaMsghdr struct { Addrs int32 Flags int32 Index uint16 - _ [2]byte Metric int32 } @@ -333,7 +326,6 @@ type RtMsghdr struct { Version uint8 Type uint8 Index uint16 - _ [2]byte Flags int32 Addrs int32 Pid int32 @@ -371,15 +363,14 @@ type BpfVersion struct { } type BpfStat struct { - Recv uint64 - Drop uint64 - Capt uint64 - Padding [13]uint64 + Recv uint64 + Drop uint64 + Capt uint64 + _ [13]uint64 } type BpfProgram struct { Len uint32 - _ [4]byte Insns *BpfInsn } diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall.go index af828a91bcf..6122f557a09 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall.go @@ -25,17 +25,20 @@ package windows // import "golang.org/x/sys/windows" import ( + "bytes" + "strings" "syscall" + "unsafe" + + "golang.org/x/sys/internal/unsafeheader" ) // ByteSliceFromString returns a NUL-terminated slice of bytes // containing the text of s. If s contains a NUL byte at any // location, it returns (nil, syscall.EINVAL). func ByteSliceFromString(s string) ([]byte, error) { - for i := 0; i < len(s); i++ { - if s[i] == 0 { - return nil, syscall.EINVAL - } + if strings.IndexByte(s, 0) != -1 { + return nil, syscall.EINVAL } a := make([]byte, len(s)+1) copy(a, s) @@ -53,6 +56,41 @@ func BytePtrFromString(s string) (*byte, error) { return &a[0], nil } +// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any +// bytes after the NUL removed. +func ByteSliceToString(s []byte) string { + if i := bytes.IndexByte(s, 0); i != -1 { + s = s[:i] + } + return string(s) +} + +// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string. +// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated +// at a zero byte; if the zero byte is not present, the program may crash. +func BytePtrToString(p *byte) string { + if p == nil { + return "" + } + if *p == 0 { + return "" + } + + // Find NUL terminator. + n := 0 + for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { + ptr = unsafe.Pointer(uintptr(ptr) + 1) + } + + var s []byte + h := (*unsafeheader.Slice)(unsafe.Pointer(&s)) + h.Data = unsafe.Pointer(p) + h.Len = n + h.Cap = n + + return string(s) +} + // Single-word zero for use when we need a valid pointer to 0 bytes. // See mksyscall.pl. var _zero uintptr diff --git a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go index 2aa29e8396d..88cff4e0d45 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -92,11 +92,11 @@ func UTF16FromString(s string) ([]uint16, error) { } // UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s, -// with a terminating NUL removed. +// with a terminating NUL and any bytes after the NUL removed. func UTF16ToString(s []uint16) string { for i, v := range s { if v == 0 { - s = s[0:i] + s = s[:i] break } } @@ -120,7 +120,7 @@ func UTF16PtrFromString(s string) (*uint16, error) { } // UTF16PtrToString takes a pointer to a UTF-16 sequence and returns the corresponding UTF-8 encoded string. -// If the pointer is nil, this returns the empty string. This assumes that the UTF-16 sequence is terminated +// If the pointer is nil, it returns the empty string. It assumes that the UTF-16 sequence is terminated // at a zero word; if the zero word is not present, the program may crash. func UTF16PtrToString(p *uint16) string { if p == nil { @@ -270,9 +270,11 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW //sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW //sys GetCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId +//sys ProcessIdToSessionId(pid uint32, sessionid *uint32) (err error) = kernel32.ProcessIdToSessionId //sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode //sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode //sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo +//sys SetConsoleCursorPosition(console Handle, position Coord) (err error) = kernel32.SetConsoleCursorPosition //sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW //sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW //sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot @@ -348,6 +350,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetThreadPreferredUILanguages //sys getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetUserPreferredUILanguages //sys getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) = kernel32.GetSystemPreferredUILanguages +//sys GetFinalPathNameByHandleW(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) = kernel32.GetFinalPathNameByHandleW // Process Status API (PSAPI) //sys EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) = psapi.EnumProcesses @@ -388,11 +391,7 @@ func GetProcAddressByOrdinal(module Handle, ordinal uintptr) (proc uintptr, err r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), ordinal, 0) proc = uintptr(r0) if proc == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -1089,11 +1088,7 @@ func WSASendMsg(fd Handle, msg *WSAMsg, flags uint32, bytesSent *uint32, overlap } r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.sendAddr, 6, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(flags), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return err } @@ -1105,11 +1100,7 @@ func WSARecvMsg(fd Handle, msg *WSAMsg, bytesReceived *uint32, overlapped *Overl } r1, _, e1 := syscall.Syscall6(sendRecvMsgFunc.recvAddr, 5, uintptr(fd), uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(bytesReceived)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0) if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return err } diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 347f13dbf6e..a1c801d1b8f 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -17,6 +17,7 @@ const ( var ( errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL ) // errnoErr returns common boxed Errno values, to prevent @@ -24,7 +25,7 @@ var ( func errnoErr(e syscall.Errno) error { switch e { case 0: - return nil + return errERROR_EINVAL case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } @@ -36,375 +37,392 @@ func errnoErr(e syscall.Errno) error { var ( modadvapi32 = NewLazySystemDLL("advapi32.dll") - modkernel32 = NewLazySystemDLL("kernel32.dll") - modshell32 = NewLazySystemDLL("shell32.dll") - moduserenv = NewLazySystemDLL("userenv.dll") - modmswsock = NewLazySystemDLL("mswsock.dll") modcrypt32 = NewLazySystemDLL("crypt32.dll") - moduser32 = NewLazySystemDLL("user32.dll") - modole32 = NewLazySystemDLL("ole32.dll") - modntdll = NewLazySystemDLL("ntdll.dll") - modpsapi = NewLazySystemDLL("psapi.dll") - modws2_32 = NewLazySystemDLL("ws2_32.dll") moddnsapi = NewLazySystemDLL("dnsapi.dll") modiphlpapi = NewLazySystemDLL("iphlpapi.dll") - modsecur32 = NewLazySystemDLL("secur32.dll") + modkernel32 = NewLazySystemDLL("kernel32.dll") + modmswsock = NewLazySystemDLL("mswsock.dll") modnetapi32 = NewLazySystemDLL("netapi32.dll") + modntdll = NewLazySystemDLL("ntdll.dll") + modole32 = NewLazySystemDLL("ole32.dll") + modpsapi = NewLazySystemDLL("psapi.dll") + modsecur32 = NewLazySystemDLL("secur32.dll") + modshell32 = NewLazySystemDLL("shell32.dll") + moduser32 = NewLazySystemDLL("user32.dll") + moduserenv = NewLazySystemDLL("userenv.dll") + modws2_32 = NewLazySystemDLL("ws2_32.dll") modwtsapi32 = NewLazySystemDLL("wtsapi32.dll") - procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") - procDeregisterEventSource = modadvapi32.NewProc("DeregisterEventSource") - procReportEventW = modadvapi32.NewProc("ReportEventW") - procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") - procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle") - procCreateServiceW = modadvapi32.NewProc("CreateServiceW") - procOpenServiceW = modadvapi32.NewProc("OpenServiceW") - procDeleteService = modadvapi32.NewProc("DeleteService") - procStartServiceW = modadvapi32.NewProc("StartServiceW") - procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") - procQueryServiceLockStatusW = modadvapi32.NewProc("QueryServiceLockStatusW") - procControlService = modadvapi32.NewProc("ControlService") - procStartServiceCtrlDispatcherW = modadvapi32.NewProc("StartServiceCtrlDispatcherW") - procSetServiceStatus = modadvapi32.NewProc("SetServiceStatus") - procChangeServiceConfigW = modadvapi32.NewProc("ChangeServiceConfigW") - procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") + procAdjustTokenGroups = modadvapi32.NewProc("AdjustTokenGroups") + procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") + procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") + procBuildSecurityDescriptorW = modadvapi32.NewProc("BuildSecurityDescriptorW") procChangeServiceConfig2W = modadvapi32.NewProc("ChangeServiceConfig2W") - procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") - procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") - procQueryServiceStatusEx = modadvapi32.NewProc("QueryServiceStatusEx") - procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") - procGetLastError = modkernel32.NewProc("GetLastError") - procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") - procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") - procFreeLibrary = modkernel32.NewProc("FreeLibrary") - procGetProcAddress = modkernel32.NewProc("GetProcAddress") - procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") - procGetModuleHandleExW = modkernel32.NewProc("GetModuleHandleExW") - procGetVersion = modkernel32.NewProc("GetVersion") - procFormatMessageW = modkernel32.NewProc("FormatMessageW") - procExitProcess = modkernel32.NewProc("ExitProcess") - procIsWow64Process = modkernel32.NewProc("IsWow64Process") - procCreateFileW = modkernel32.NewProc("CreateFileW") - procReadFile = modkernel32.NewProc("ReadFile") - procWriteFile = modkernel32.NewProc("WriteFile") - procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") - procSetFilePointer = modkernel32.NewProc("SetFilePointer") - procCloseHandle = modkernel32.NewProc("CloseHandle") - procGetStdHandle = modkernel32.NewProc("GetStdHandle") - procSetStdHandle = modkernel32.NewProc("SetStdHandle") - procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") - procFindNextFileW = modkernel32.NewProc("FindNextFileW") - procFindClose = modkernel32.NewProc("FindClose") - procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") - procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") - procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") - procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") - procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") - procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") - procDeleteFileW = modkernel32.NewProc("DeleteFileW") - procMoveFileW = modkernel32.NewProc("MoveFileW") - procMoveFileExW = modkernel32.NewProc("MoveFileExW") - procLockFileEx = modkernel32.NewProc("LockFileEx") - procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") - procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") - procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") - procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") - procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") - procGetSystemTimePreciseAsFileTime = modkernel32.NewProc("GetSystemTimePreciseAsFileTime") - procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") - procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") - procCancelIo = modkernel32.NewProc("CancelIo") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") - procCreateProcessW = modkernel32.NewProc("CreateProcessW") - procOpenProcess = modkernel32.NewProc("OpenProcess") - procShellExecuteW = modshell32.NewProc("ShellExecuteW") - procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath") - procTerminateProcess = modkernel32.NewProc("TerminateProcess") - procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") - procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") - procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") - procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") - procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") - procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") - procGetTempPathW = modkernel32.NewProc("GetTempPathW") - procCreatePipe = modkernel32.NewProc("CreatePipe") - procGetFileType = modkernel32.NewProc("GetFileType") + procChangeServiceConfigW = modadvapi32.NewProc("ChangeServiceConfigW") + procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership") + procCloseServiceHandle = modadvapi32.NewProc("CloseServiceHandle") + procControlService = modadvapi32.NewProc("ControlService") + procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") + procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") + procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") + procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") + procCopySid = modadvapi32.NewProc("CopySid") + procCreateServiceW = modadvapi32.NewProc("CreateServiceW") + procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") - procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") - procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") - procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") - procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") - procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") - procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") - procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") - procGetTickCount64 = modkernel32.NewProc("GetTickCount64") - procSetFileTime = modkernel32.NewProc("SetFileTime") - procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") - procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") - procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") - procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") - procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") - procLocalFree = modkernel32.NewProc("LocalFree") - procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") - procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") - procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") - procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") - procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") - procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") - procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") - procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") - procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") - procVirtualLock = modkernel32.NewProc("VirtualLock") - procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") - procVirtualAlloc = modkernel32.NewProc("VirtualAlloc") - procVirtualFree = modkernel32.NewProc("VirtualFree") - procVirtualProtect = modkernel32.NewProc("VirtualProtect") - procTransmitFile = modmswsock.NewProc("TransmitFile") - procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") - procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") - procCertOpenStore = modcrypt32.NewProc("CertOpenStore") - procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") + procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") + procDeleteService = modadvapi32.NewProc("DeleteService") + procDeregisterEventSource = modadvapi32.NewProc("DeregisterEventSource") + procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") + procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") + procEqualSid = modadvapi32.NewProc("EqualSid") + procFreeSid = modadvapi32.NewProc("FreeSid") + procGetLengthSid = modadvapi32.NewProc("GetLengthSid") + procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") + procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") + procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl") + procGetSecurityDescriptorGroup = modadvapi32.NewProc("GetSecurityDescriptorGroup") + procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") + procGetSecurityDescriptorOwner = modadvapi32.NewProc("GetSecurityDescriptorOwner") + procGetSecurityDescriptorRMControl = modadvapi32.NewProc("GetSecurityDescriptorRMControl") + procGetSecurityDescriptorSacl = modadvapi32.NewProc("GetSecurityDescriptorSacl") + procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo") + procGetSidIdentifierAuthority = modadvapi32.NewProc("GetSidIdentifierAuthority") + procGetSidSubAuthority = modadvapi32.NewProc("GetSidSubAuthority") + procGetSidSubAuthorityCount = modadvapi32.NewProc("GetSidSubAuthorityCount") + procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") + procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") + procInitializeSecurityDescriptor = modadvapi32.NewProc("InitializeSecurityDescriptor") + procInitiateSystemShutdownExW = modadvapi32.NewProc("InitiateSystemShutdownExW") + procIsValidSecurityDescriptor = modadvapi32.NewProc("IsValidSecurityDescriptor") + procIsValidSid = modadvapi32.NewProc("IsValidSid") + procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procMakeAbsoluteSD = modadvapi32.NewProc("MakeAbsoluteSD") + procMakeSelfRelativeSD = modadvapi32.NewProc("MakeSelfRelativeSD") + procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") + procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") + procOpenSCManagerW = modadvapi32.NewProc("OpenSCManagerW") + procOpenServiceW = modadvapi32.NewProc("OpenServiceW") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procQueryServiceConfig2W = modadvapi32.NewProc("QueryServiceConfig2W") + procQueryServiceConfigW = modadvapi32.NewProc("QueryServiceConfigW") + procQueryServiceLockStatusW = modadvapi32.NewProc("QueryServiceLockStatusW") + procQueryServiceStatus = modadvapi32.NewProc("QueryServiceStatus") + procQueryServiceStatusEx = modadvapi32.NewProc("QueryServiceStatusEx") + procRegCloseKey = modadvapi32.NewProc("RegCloseKey") + procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") + procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") + procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") + procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") + procRegisterEventSourceW = modadvapi32.NewProc("RegisterEventSourceW") + procReportEventW = modadvapi32.NewProc("ReportEventW") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") + procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") + procSetNamedSecurityInfoW = modadvapi32.NewProc("SetNamedSecurityInfoW") + procSetSecurityDescriptorControl = modadvapi32.NewProc("SetSecurityDescriptorControl") + procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl") + procSetSecurityDescriptorGroup = modadvapi32.NewProc("SetSecurityDescriptorGroup") + procSetSecurityDescriptorOwner = modadvapi32.NewProc("SetSecurityDescriptorOwner") + procSetSecurityDescriptorRMControl = modadvapi32.NewProc("SetSecurityDescriptorRMControl") + procSetSecurityDescriptorSacl = modadvapi32.NewProc("SetSecurityDescriptorSacl") + procSetSecurityInfo = modadvapi32.NewProc("SetSecurityInfo") + procSetServiceStatus = modadvapi32.NewProc("SetServiceStatus") + procSetThreadToken = modadvapi32.NewProc("SetThreadToken") + procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") + procStartServiceCtrlDispatcherW = modadvapi32.NewProc("StartServiceCtrlDispatcherW") + procStartServiceW = modadvapi32.NewProc("StartServiceW") procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") procCertCloseStore = modcrypt32.NewProc("CertCloseStore") - procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") - procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") + procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") + procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") + procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") + procCertOpenStore = modcrypt32.NewProc("CertOpenStore") + procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") - procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") - procRegCloseKey = modadvapi32.NewProc("RegCloseKey") - procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") - procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") - procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") - procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") - procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") - procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") - procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") - procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") - procReadConsoleW = modkernel32.NewProc("ReadConsoleW") - procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") - procProcess32FirstW = modkernel32.NewProc("Process32FirstW") - procProcess32NextW = modkernel32.NewProc("Process32NextW") - procThread32First = modkernel32.NewProc("Thread32First") - procThread32Next = modkernel32.NewProc("Thread32Next") - procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") - procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") - procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") - procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") - procCreateEventW = modkernel32.NewProc("CreateEventW") - procCreateEventExW = modkernel32.NewProc("CreateEventExW") - procOpenEventW = modkernel32.NewProc("OpenEventW") - procSetEvent = modkernel32.NewProc("SetEvent") - procResetEvent = modkernel32.NewProc("ResetEvent") - procPulseEvent = modkernel32.NewProc("PulseEvent") - procCreateMutexW = modkernel32.NewProc("CreateMutexW") - procCreateMutexExW = modkernel32.NewProc("CreateMutexExW") - procOpenMutexW = modkernel32.NewProc("OpenMutexW") - procReleaseMutex = modkernel32.NewProc("ReleaseMutex") - procSleepEx = modkernel32.NewProc("SleepEx") - procCreateJobObjectW = modkernel32.NewProc("CreateJobObjectW") + procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") + procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") + procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") + procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") + procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") + procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") - procTerminateJobObject = modkernel32.NewProc("TerminateJobObject") - procSetErrorMode = modkernel32.NewProc("SetErrorMode") - procResumeThread = modkernel32.NewProc("ResumeThread") - procSetPriorityClass = modkernel32.NewProc("SetPriorityClass") - procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") - procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject") - procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject") - procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") - procGetProcessId = modkernel32.NewProc("GetProcessId") - procOpenThread = modkernel32.NewProc("OpenThread") - procSetProcessPriorityBoost = modkernel32.NewProc("SetProcessPriorityBoost") - procGetProcessWorkingSetSizeEx = modkernel32.NewProc("GetProcessWorkingSetSizeEx") - procSetProcessWorkingSetSizeEx = modkernel32.NewProc("SetProcessWorkingSetSizeEx") + procCancelIo = modkernel32.NewProc("CancelIo") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procCloseHandle = modkernel32.NewProc("CloseHandle") + procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") + procCreateEventExW = modkernel32.NewProc("CreateEventExW") + procCreateEventW = modkernel32.NewProc("CreateEventW") + procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procCreateJobObjectW = modkernel32.NewProc("CreateJobObjectW") + procCreateMutexExW = modkernel32.NewProc("CreateMutexExW") + procCreateMutexW = modkernel32.NewProc("CreateMutexW") + procCreatePipe = modkernel32.NewProc("CreatePipe") + procCreateProcessW = modkernel32.NewProc("CreateProcessW") + procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") procDefineDosDeviceW = modkernel32.NewProc("DefineDosDeviceW") + procDeleteFileW = modkernel32.NewProc("DeleteFileW") procDeleteVolumeMountPointW = modkernel32.NewProc("DeleteVolumeMountPointW") - procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW") + procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") + procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") + procExitProcess = modkernel32.NewProc("ExitProcess") + procFindClose = modkernel32.NewProc("FindClose") + procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") procFindFirstVolumeMountPointW = modkernel32.NewProc("FindFirstVolumeMountPointW") - procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW") + procFindFirstVolumeW = modkernel32.NewProc("FindFirstVolumeW") + procFindNextFileW = modkernel32.NewProc("FindNextFileW") procFindNextVolumeMountPointW = modkernel32.NewProc("FindNextVolumeMountPointW") + procFindNextVolumeW = modkernel32.NewProc("FindNextVolumeW") procFindVolumeClose = modkernel32.NewProc("FindVolumeClose") procFindVolumeMountPointClose = modkernel32.NewProc("FindVolumeMountPointClose") + procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") + procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") + procFormatMessageW = modkernel32.NewProc("FormatMessageW") + procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") + procFreeLibrary = modkernel32.NewProc("FreeLibrary") + procGenerateConsoleCtrlEvent = modkernel32.NewProc("GenerateConsoleCtrlEvent") + procGetACP = modkernel32.NewProc("GetACP") + procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") + procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") + procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procGetConsoleScreenBufferInfo = modkernel32.NewProc("GetConsoleScreenBufferInfo") + procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") + procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") + procGetCurrentThreadId = modkernel32.NewProc("GetCurrentThreadId") procGetDiskFreeSpaceExW = modkernel32.NewProc("GetDiskFreeSpaceExW") procGetDriveTypeW = modkernel32.NewProc("GetDriveTypeW") - procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") + procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") + procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") + procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") + procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") + procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") + procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") + procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procGetFileType = modkernel32.NewProc("GetFileType") + procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW") + procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") + procGetLastError = modkernel32.NewProc("GetLastError") procGetLogicalDriveStringsW = modkernel32.NewProc("GetLogicalDriveStringsW") - procGetVolumeInformationW = modkernel32.NewProc("GetVolumeInformationW") + procGetLogicalDrives = modkernel32.NewProc("GetLogicalDrives") + procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") + procGetModuleHandleExW = modkernel32.NewProc("GetModuleHandleExW") + procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult") + procGetPriorityClass = modkernel32.NewProc("GetPriorityClass") + procGetProcAddress = modkernel32.NewProc("GetProcAddress") + procGetProcessId = modkernel32.NewProc("GetProcessId") + procGetProcessPreferredUILanguages = modkernel32.NewProc("GetProcessPreferredUILanguages") + procGetProcessShutdownParameters = modkernel32.NewProc("GetProcessShutdownParameters") + procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") + procGetProcessWorkingSetSizeEx = modkernel32.NewProc("GetProcessWorkingSetSizeEx") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") + procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") + procGetStdHandle = modkernel32.NewProc("GetStdHandle") + procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW") + procGetSystemPreferredUILanguages = modkernel32.NewProc("GetSystemPreferredUILanguages") + procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") + procGetSystemTimePreciseAsFileTime = modkernel32.NewProc("GetSystemTimePreciseAsFileTime") + procGetSystemWindowsDirectoryW = modkernel32.NewProc("GetSystemWindowsDirectoryW") + procGetTempPathW = modkernel32.NewProc("GetTempPathW") + procGetThreadPreferredUILanguages = modkernel32.NewProc("GetThreadPreferredUILanguages") + procGetTickCount64 = modkernel32.NewProc("GetTickCount64") + procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") + procGetUserPreferredUILanguages = modkernel32.NewProc("GetUserPreferredUILanguages") + procGetVersion = modkernel32.NewProc("GetVersion") procGetVolumeInformationByHandleW = modkernel32.NewProc("GetVolumeInformationByHandleW") + procGetVolumeInformationW = modkernel32.NewProc("GetVolumeInformationW") procGetVolumeNameForVolumeMountPointW = modkernel32.NewProc("GetVolumeNameForVolumeMountPointW") procGetVolumePathNameW = modkernel32.NewProc("GetVolumePathNameW") procGetVolumePathNamesForVolumeNameW = modkernel32.NewProc("GetVolumePathNamesForVolumeNameW") + procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW") + procIsWow64Process = modkernel32.NewProc("IsWow64Process") + procLoadLibraryExW = modkernel32.NewProc("LoadLibraryExW") + procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") + procLocalFree = modkernel32.NewProc("LocalFree") + procLockFileEx = modkernel32.NewProc("LockFileEx") + procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") + procMoveFileExW = modkernel32.NewProc("MoveFileExW") + procMoveFileW = modkernel32.NewProc("MoveFileW") + procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") + procOpenEventW = modkernel32.NewProc("OpenEventW") + procOpenMutexW = modkernel32.NewProc("OpenMutexW") + procOpenProcess = modkernel32.NewProc("OpenProcess") + procOpenThread = modkernel32.NewProc("OpenThread") + procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") + procProcess32FirstW = modkernel32.NewProc("Process32FirstW") + procProcess32NextW = modkernel32.NewProc("Process32NextW") + procProcessIdToSessionId = modkernel32.NewProc("ProcessIdToSessionId") + procPulseEvent = modkernel32.NewProc("PulseEvent") procQueryDosDeviceW = modkernel32.NewProc("QueryDosDeviceW") + procQueryInformationJobObject = modkernel32.NewProc("QueryInformationJobObject") + procReadConsoleW = modkernel32.NewProc("ReadConsoleW") + procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") + procReadFile = modkernel32.NewProc("ReadFile") + procReleaseMutex = modkernel32.NewProc("ReleaseMutex") + procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") + procResetEvent = modkernel32.NewProc("ResetEvent") + procResumeThread = modkernel32.NewProc("ResumeThread") + procSetConsoleCursorPosition = modkernel32.NewProc("SetConsoleCursorPosition") + procSetConsoleMode = modkernel32.NewProc("SetConsoleMode") + procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") + procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") + procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") + procSetErrorMode = modkernel32.NewProc("SetErrorMode") + procSetEvent = modkernel32.NewProc("SetEvent") + procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procSetFilePointer = modkernel32.NewProc("SetFilePointer") + procSetFileTime = modkernel32.NewProc("SetFileTime") + procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") + procSetInformationJobObject = modkernel32.NewProc("SetInformationJobObject") + procSetPriorityClass = modkernel32.NewProc("SetPriorityClass") + procSetProcessPriorityBoost = modkernel32.NewProc("SetProcessPriorityBoost") + procSetProcessShutdownParameters = modkernel32.NewProc("SetProcessShutdownParameters") + procSetProcessWorkingSetSizeEx = modkernel32.NewProc("SetProcessWorkingSetSizeEx") + procSetStdHandle = modkernel32.NewProc("SetStdHandle") procSetVolumeLabelW = modkernel32.NewProc("SetVolumeLabelW") procSetVolumeMountPointW = modkernel32.NewProc("SetVolumeMountPointW") - procMessageBoxW = moduser32.NewProc("MessageBoxW") - procExitWindowsEx = moduser32.NewProc("ExitWindowsEx") - procInitiateSystemShutdownExW = modadvapi32.NewProc("InitiateSystemShutdownExW") - procSetProcessShutdownParameters = modkernel32.NewProc("SetProcessShutdownParameters") - procGetProcessShutdownParameters = modkernel32.NewProc("GetProcessShutdownParameters") - procCLSIDFromString = modole32.NewProc("CLSIDFromString") - procStringFromGUID2 = modole32.NewProc("StringFromGUID2") - procCoCreateGuid = modole32.NewProc("CoCreateGuid") - procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") - procRtlGetVersion = modntdll.NewProc("RtlGetVersion") - procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers") - procGetProcessPreferredUILanguages = modkernel32.NewProc("GetProcessPreferredUILanguages") - procGetThreadPreferredUILanguages = modkernel32.NewProc("GetThreadPreferredUILanguages") - procGetUserPreferredUILanguages = modkernel32.NewProc("GetUserPreferredUILanguages") - procGetSystemPreferredUILanguages = modkernel32.NewProc("GetSystemPreferredUILanguages") - procEnumProcesses = modpsapi.NewProc("EnumProcesses") - procWSAStartup = modws2_32.NewProc("WSAStartup") - procWSACleanup = modws2_32.NewProc("WSACleanup") - procWSAIoctl = modws2_32.NewProc("WSAIoctl") - procsocket = modws2_32.NewProc("socket") - procsendto = modws2_32.NewProc("sendto") - procrecvfrom = modws2_32.NewProc("recvfrom") - procsetsockopt = modws2_32.NewProc("setsockopt") - procgetsockopt = modws2_32.NewProc("getsockopt") - procbind = modws2_32.NewProc("bind") - procconnect = modws2_32.NewProc("connect") - procgetsockname = modws2_32.NewProc("getsockname") - procgetpeername = modws2_32.NewProc("getpeername") - proclisten = modws2_32.NewProc("listen") - procshutdown = modws2_32.NewProc("shutdown") - procclosesocket = modws2_32.NewProc("closesocket") + procSleepEx = modkernel32.NewProc("SleepEx") + procTerminateJobObject = modkernel32.NewProc("TerminateJobObject") + procTerminateProcess = modkernel32.NewProc("TerminateProcess") + procThread32First = modkernel32.NewProc("Thread32First") + procThread32Next = modkernel32.NewProc("Thread32Next") + procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") + procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") + procVirtualAlloc = modkernel32.NewProc("VirtualAlloc") + procVirtualFree = modkernel32.NewProc("VirtualFree") + procVirtualLock = modkernel32.NewProc("VirtualLock") + procVirtualProtect = modkernel32.NewProc("VirtualProtect") + procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") + procWaitForMultipleObjects = modkernel32.NewProc("WaitForMultipleObjects") + procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") + procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") + procWriteFile = modkernel32.NewProc("WriteFile") procAcceptEx = modmswsock.NewProc("AcceptEx") procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") - procWSARecv = modws2_32.NewProc("WSARecv") - procWSASend = modws2_32.NewProc("WSASend") - procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") - procWSASendTo = modws2_32.NewProc("WSASendTo") - procgethostbyname = modws2_32.NewProc("gethostbyname") - procgetservbyname = modws2_32.NewProc("getservbyname") - procntohs = modws2_32.NewProc("ntohs") - procgetprotobyname = modws2_32.NewProc("getprotobyname") - procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") - procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") - procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") - procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") - procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") - procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") - procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") - procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") - procGetACP = modkernel32.NewProc("GetACP") - procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") - procTranslateNameW = modsecur32.NewProc("TranslateNameW") - procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") - procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") - procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procTransmitFile = modmswsock.NewProc("TransmitFile") procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") - procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") - procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") - procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") - procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") - procGetLengthSid = modadvapi32.NewProc("GetLengthSid") - procCopySid = modadvapi32.NewProc("CopySid") - procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid") - procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid") - procIsWellKnownSid = modadvapi32.NewProc("IsWellKnownSid") - procFreeSid = modadvapi32.NewProc("FreeSid") - procEqualSid = modadvapi32.NewProc("EqualSid") - procGetSidIdentifierAuthority = modadvapi32.NewProc("GetSidIdentifierAuthority") - procGetSidSubAuthorityCount = modadvapi32.NewProc("GetSidSubAuthorityCount") - procGetSidSubAuthority = modadvapi32.NewProc("GetSidSubAuthority") - procIsValidSid = modadvapi32.NewProc("IsValidSid") - procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership") - procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") - procSetThreadToken = modadvapi32.NewProc("SetThreadToken") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") - procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") - procAdjustTokenGroups = modadvapi32.NewProc("AdjustTokenGroups") - procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") - procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") - procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") + procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") + procRtlGetNtVersionNumbers = modntdll.NewProc("RtlGetNtVersionNumbers") + procRtlGetVersion = modntdll.NewProc("RtlGetVersion") + procCLSIDFromString = modole32.NewProc("CLSIDFromString") + procCoCreateGuid = modole32.NewProc("CoCreateGuid") + procCoTaskMemFree = modole32.NewProc("CoTaskMemFree") + procStringFromGUID2 = modole32.NewProc("StringFromGUID2") + procEnumProcesses = modpsapi.NewProc("EnumProcesses") + procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") + procTranslateNameW = modsecur32.NewProc("TranslateNameW") + procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") + procSHGetKnownFolderPath = modshell32.NewProc("SHGetKnownFolderPath") + procShellExecuteW = modshell32.NewProc("ShellExecuteW") + procExitWindowsEx = moduser32.NewProc("ExitWindowsEx") + procMessageBoxW = moduser32.NewProc("MessageBoxW") + procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") + procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") - procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW") - procGetWindowsDirectoryW = modkernel32.NewProc("GetWindowsDirectoryW") - procGetSystemWindowsDirectoryW = modkernel32.NewProc("GetSystemWindowsDirectoryW") - procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") + procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") + procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") + procWSACleanup = modws2_32.NewProc("WSACleanup") + procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") + procWSAIoctl = modws2_32.NewProc("WSAIoctl") + procWSARecv = modws2_32.NewProc("WSARecv") + procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") + procWSASend = modws2_32.NewProc("WSASend") + procWSASendTo = modws2_32.NewProc("WSASendTo") + procWSAStartup = modws2_32.NewProc("WSAStartup") + procbind = modws2_32.NewProc("bind") + procclosesocket = modws2_32.NewProc("closesocket") + procconnect = modws2_32.NewProc("connect") + procgethostbyname = modws2_32.NewProc("gethostbyname") + procgetpeername = modws2_32.NewProc("getpeername") + procgetprotobyname = modws2_32.NewProc("getprotobyname") + procgetservbyname = modws2_32.NewProc("getservbyname") + procgetsockname = modws2_32.NewProc("getsockname") + procgetsockopt = modws2_32.NewProc("getsockopt") + proclisten = modws2_32.NewProc("listen") + procntohs = modws2_32.NewProc("ntohs") + procrecvfrom = modws2_32.NewProc("recvfrom") + procsendto = modws2_32.NewProc("sendto") + procsetsockopt = modws2_32.NewProc("setsockopt") + procshutdown = modws2_32.NewProc("shutdown") + procsocket = modws2_32.NewProc("socket") procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW") procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") - procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo") - procSetSecurityInfo = modadvapi32.NewProc("SetSecurityInfo") - procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") - procSetNamedSecurityInfoW = modadvapi32.NewProc("SetNamedSecurityInfoW") - procBuildSecurityDescriptorW = modadvapi32.NewProc("BuildSecurityDescriptorW") - procInitializeSecurityDescriptor = modadvapi32.NewProc("InitializeSecurityDescriptor") - procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") - procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl") - procGetSecurityDescriptorSacl = modadvapi32.NewProc("GetSecurityDescriptorSacl") - procGetSecurityDescriptorOwner = modadvapi32.NewProc("GetSecurityDescriptorOwner") - procGetSecurityDescriptorGroup = modadvapi32.NewProc("GetSecurityDescriptorGroup") - procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") - procGetSecurityDescriptorRMControl = modadvapi32.NewProc("GetSecurityDescriptorRMControl") - procIsValidSecurityDescriptor = modadvapi32.NewProc("IsValidSecurityDescriptor") - procSetSecurityDescriptorControl = modadvapi32.NewProc("SetSecurityDescriptorControl") - procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl") - procSetSecurityDescriptorSacl = modadvapi32.NewProc("SetSecurityDescriptorSacl") - procSetSecurityDescriptorOwner = modadvapi32.NewProc("SetSecurityDescriptorOwner") - procSetSecurityDescriptorGroup = modadvapi32.NewProc("SetSecurityDescriptorGroup") - procSetSecurityDescriptorRMControl = modadvapi32.NewProc("SetSecurityDescriptorRMControl") - procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW") - procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW") - procMakeAbsoluteSD = modadvapi32.NewProc("MakeAbsoluteSD") - procMakeSelfRelativeSD = modadvapi32.NewProc("MakeSelfRelativeSD") - procSetEntriesInAclW = modadvapi32.NewProc("SetEntriesInAclW") + procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") ) -func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procRegisterEventSourceW.Addr(), 2, uintptr(unsafe.Pointer(uncServerName)), uintptr(unsafe.Pointer(sourceName)), 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) { + var _p0 uint32 + if resetToDefault { + _p0 = 1 } - return -} - -func DeregisterEventSource(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procDeregisterEventSource.Addr(), 1, uintptr(handle), 0, 0) + r1, _, e1 := syscall.Syscall6(procAdjustTokenGroups.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procReportEventW.Addr(), 9, uintptr(log), uintptr(etype), uintptr(category), uintptr(eventId), uintptr(usrSId), uintptr(numStrings), uintptr(dataSize), uintptr(unsafe.Pointer(strings)), uintptr(unsafe.Pointer(rawData))) +func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) { + var _p0 uint32 + if disableAllPrivileges { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(access)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) { + r1, _, e1 := syscall.Syscall12(procAllocateAndInitializeSid.Addr(), 11, uintptr(unsafe.Pointer(identAuth)), uintptr(subAuth), uintptr(subAuth0), uintptr(subAuth1), uintptr(subAuth2), uintptr(subAuth3), uintptr(subAuth4), uintptr(subAuth5), uintptr(subAuth6), uintptr(subAuth7), uintptr(unsafe.Pointer(sid)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procBuildSecurityDescriptorW.Addr(), 9, uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(countAccessEntries), uintptr(unsafe.Pointer(accessEntries)), uintptr(countAuditEntries), uintptr(unsafe.Pointer(auditEntries)), uintptr(unsafe.Pointer(oldSecurityDescriptor)), uintptr(unsafe.Pointer(sizeNewSecurityDescriptor)), uintptr(unsafe.Pointer(newSecurityDescriptor))) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) { + r1, _, e1 := syscall.Syscall(procChangeServiceConfig2W.Addr(), 3, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(info))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) { + r1, _, e1 := syscall.Syscall12(procChangeServiceConfigW.Addr(), 11, uintptr(service), uintptr(serviceType), uintptr(startType), uintptr(errorControl), uintptr(unsafe.Pointer(binaryPathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), uintptr(unsafe.Pointer(displayName)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) { + r1, _, e1 := syscall.Syscall(procCheckTokenMembership.Addr(), 3, uintptr(tokenHandle), uintptr(unsafe.Pointer(sidToCheck)), uintptr(unsafe.Pointer(isMember))) + if r1 == 0 { + err = errnoErr(e1) } return } @@ -412,11 +430,64 @@ func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (ha func CloseServiceHandle(handle Handle) (err error) { r1, _, e1 := syscall.Syscall(procCloseServiceHandle.Addr(), 1, uintptr(handle), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) + } + return +} + +func ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) { + r1, _, e1 := syscall.Syscall(procControlService.Addr(), 3, uintptr(service), uintptr(control), uintptr(unsafe.Pointer(status))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(securityInformation), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(strLen)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) { + r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(str) + if err != nil { + return + } + return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) +} + +func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { + r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { + r1, _, e1 := syscall.Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) + if r1 == 0 { + err = errnoErr(e1) } return } @@ -425,24 +496,39 @@ func CreateService(mgr Handle, serviceName *uint16, displayName *uint16, access r0, _, e1 := syscall.Syscall15(procCreateServiceW.Addr(), 13, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(unsafe.Pointer(displayName)), uintptr(access), uintptr(srvType), uintptr(startType), uintptr(errCtl), uintptr(unsafe.Pointer(pathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), 0, 0) handle = Handle(r0) if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procOpenServiceW.Addr(), 3, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(access)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procCreateWellKnownSid.Addr(), 4, uintptr(sidType), uintptr(unsafe.Pointer(domainSid)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sizeSid)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) { + r1, _, e1 := syscall.Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) } return } @@ -450,131 +536,23 @@ func OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, func DeleteService(service Handle) (err error) { r1, _, e1 := syscall.Syscall(procDeleteService.Addr(), 1, uintptr(service), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) { - r1, _, e1 := syscall.Syscall(procStartServiceW.Addr(), 3, uintptr(service), uintptr(numArgs), uintptr(unsafe.Pointer(argVectors))) +func DeregisterEventSource(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDeregisterEventSource.Addr(), 1, uintptr(handle), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) { - r1, _, e1 := syscall.Syscall(procQueryServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(status)), 0) +func DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) { + r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(existingToken), uintptr(desiredAccess), uintptr(unsafe.Pointer(tokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(newToken))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func QueryServiceLockStatus(mgr Handle, lockStatus *QUERY_SERVICE_LOCK_STATUS, bufSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceLockStatusW.Addr(), 4, uintptr(mgr), uintptr(unsafe.Pointer(lockStatus)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ControlService(service Handle, control uint32, status *SERVICE_STATUS) (err error) { - r1, _, e1 := syscall.Syscall(procControlService.Addr(), 3, uintptr(service), uintptr(control), uintptr(unsafe.Pointer(status))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) { - r1, _, e1 := syscall.Syscall(procStartServiceCtrlDispatcherW.Addr(), 1, uintptr(unsafe.Pointer(serviceTable)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) { - r1, _, e1 := syscall.Syscall(procSetServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(serviceStatus)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ChangeServiceConfig(service Handle, serviceType uint32, startType uint32, errorControl uint32, binaryPathName *uint16, loadOrderGroup *uint16, tagId *uint32, dependencies *uint16, serviceStartName *uint16, password *uint16, displayName *uint16) (err error) { - r1, _, e1 := syscall.Syscall12(procChangeServiceConfigW.Addr(), 11, uintptr(service), uintptr(serviceType), uintptr(startType), uintptr(errorControl), uintptr(unsafe.Pointer(binaryPathName)), uintptr(unsafe.Pointer(loadOrderGroup)), uintptr(unsafe.Pointer(tagId)), uintptr(unsafe.Pointer(dependencies)), uintptr(unsafe.Pointer(serviceStartName)), uintptr(unsafe.Pointer(password)), uintptr(unsafe.Pointer(displayName)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceConfigW.Addr(), 4, uintptr(service), uintptr(unsafe.Pointer(serviceConfig)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ChangeServiceConfig2(service Handle, infoLevel uint32, info *byte) (err error) { - r1, _, e1 := syscall.Syscall(procChangeServiceConfig2W.Addr(), 3, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(info))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceConfig2W.Addr(), 5, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -582,23 +560,252 @@ func QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize func EnumServicesStatusEx(mgr Handle, infoLevel uint32, serviceType uint32, serviceState uint32, services *byte, bufSize uint32, bytesNeeded *uint32, servicesReturned *uint32, resumeHandle *uint32, groupName *uint16) (err error) { r1, _, e1 := syscall.Syscall12(procEnumServicesStatusExW.Addr(), 10, uintptr(mgr), uintptr(infoLevel), uintptr(serviceType), uintptr(serviceState), uintptr(unsafe.Pointer(services)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), uintptr(unsafe.Pointer(servicesReturned)), uintptr(unsafe.Pointer(resumeHandle)), uintptr(unsafe.Pointer(groupName)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryServiceStatusEx.Addr(), 5, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), 0) +func EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) { + r0, _, _ := syscall.Syscall(procEqualSid.Addr(), 2, uintptr(unsafe.Pointer(sid1)), uintptr(unsafe.Pointer(sid2)), 0) + isEqual = r0 != 0 + return +} + +func FreeSid(sid *SID) (err error) { + r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + if r1 != 0 { + err = errnoErr(e1) + } + return +} + +func GetLengthSid(sid *SID) (len uint32) { + r0, _, _ := syscall.Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + len = uint32(r0) + return +} + +func getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + var _p0 *uint16 + _p0, ret = syscall.UTF16PtrFromString(objectName) + if ret != nil { + return + } + return _getNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl, sd) +} + +func _getNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procGetNamedSecurityInfoW.Addr(), 8, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(control)), uintptr(unsafe.Pointer(revision))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) + } + return +} + +func getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) { + var _p0 uint32 + if *daclPresent { + _p0 = 1 + } + var _p1 uint32 + if *daclDefaulted { + _p1 = 1 + } + r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + *daclPresent = _p0 != 0 + *daclDefaulted = _p1 != 0 + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) { + var _p0 uint32 + if *groupDefaulted { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(&_p0))) + *groupDefaulted = _p0 != 0 + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + len = uint32(r0) + return +} + +func getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) { + var _p0 uint32 + if *ownerDefaulted { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(&_p0))) + *ownerDefaulted = _p0 != 0 + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) { + r0, _, _ := syscall.Syscall(procGetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) { + var _p0 uint32 + if *saclPresent { + _p0 = 1 + } + var _p1 uint32 + if *saclDefaulted { + _p1 = 1 + } + r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) + *saclPresent = _p0 != 0 + *saclDefaulted = _p1 != 0 + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { + r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) { + r0, _, _ := syscall.Syscall(procGetSidIdentifierAuthority.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + authority = (*SidIdentifierAuthority)(unsafe.Pointer(r0)) + return +} + +func getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) { + r0, _, _ := syscall.Syscall(procGetSidSubAuthority.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(index), 0) + subAuthority = (*uint32)(unsafe.Pointer(r0)) + return +} + +func getSidSubAuthorityCount(sid *SID) (count *uint8) { + r0, _, _ := syscall.Syscall(procGetSidSubAuthorityCount.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + count = (*uint8)(unsafe.Pointer(r0)) + return +} + +func GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetTokenInformation.Addr(), 5, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ImpersonateSelf(impersonationlevel uint32) (err error) { + r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) { + r1, _, e1 := syscall.Syscall(procInitializeSecurityDescriptor.Addr(), 2, uintptr(unsafe.Pointer(absoluteSD)), uintptr(revision), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) { + var _p0 uint32 + if forceAppsClosed { + _p0 = 1 + } + var _p1 uint32 + if rebootAfterShutdown { + _p1 = 1 + } + r1, _, e1 := syscall.Syscall6(procInitiateSystemShutdownExW.Addr(), 6, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) { + r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) + isValid = r0 != 0 + return +} + +func isValidSid(sid *SID) (isValid bool) { + r0, _, _ := syscall.Syscall(procIsValidSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + isValid = r0 != 0 + return +} + +func isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) { + r0, _, _ := syscall.Syscall(procIsWellKnownSid.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(sidType), 0) + isWellKnown = r0 != 0 + return +} + +func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) { + r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(absoluteSDSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(groupSize)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(selfRelativeSDSize))) + if r1 == 0 { + err = errnoErr(e1) } return } @@ -611,1295 +818,80 @@ func NotifyServiceStatusChange(service Handle, notifyMask uint32, notifier *SERV return } -func GetLastError() (lasterr error) { - r0, _, _ := syscall.Syscall(procGetLastError.Addr(), 0, 0, 0, 0) - if r0 != 0 { - lasterr = syscall.Errno(r0) +func OpenProcessToken(process Handle, access uint32, token *Token) (err error) { + r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(process), uintptr(access), uintptr(unsafe.Pointer(token))) + if r1 == 0 { + err = errnoErr(e1) } return } -func LoadLibrary(libname string) (handle Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(libname) - if err != nil { - return - } - return _LoadLibrary(_p0) -} - -func _LoadLibrary(libname *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(libname)), 0, 0) +func OpenSCManager(machineName *uint16, databaseName *uint16, access uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procOpenSCManagerW.Addr(), 3, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(databaseName)), uintptr(access)) handle = Handle(r0) if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(libname) - if err != nil { - return - } - return _LoadLibraryEx(_p0, zero, flags) -} - -func _LoadLibraryEx(libname *uint16, zero Handle, flags uintptr) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLoadLibraryExW.Addr(), 3, uintptr(unsafe.Pointer(libname)), uintptr(zero), uintptr(flags)) +func OpenService(mgr Handle, serviceName *uint16, access uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procOpenServiceW.Addr(), 3, uintptr(mgr), uintptr(unsafe.Pointer(serviceName)), uintptr(access)) handle = Handle(r0) if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func FreeLibrary(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(procname) - if err != nil { - return - } - return _GetProcAddress(module, _p0) -} - -func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { - r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0) - proc = uintptr(r0) - if proc == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) { - r1, _, e1 := syscall.Syscall(procGetModuleHandleExW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(moduleName)), uintptr(unsafe.Pointer(module))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetVersion() (ver uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetVersion.Addr(), 0, 0, 0, 0) - ver = uint32(r0) - if ver == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { - var _p0 *uint16 - if len(buf) > 0 { - _p0 = &buf[0] - } - r0, _, e1 := syscall.Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ExitProcess(exitcode uint32) { - syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) - return -} - -func IsWow64Process(handle Handle, isWow64 *bool) (err error) { +func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) { var _p0 uint32 - if *isWow64 { + if openAsSelf { _p0 = 1 - } else { - _p0 = 0 } - r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(&_p0)), 0) - *isWow64 = _p0 != 0 + r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := syscall.Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) +func QueryServiceConfig2(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryServiceConfig2W.Addr(), 5, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := syscall.Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) +func QueryServiceConfig(service Handle, serviceConfig *QUERY_SERVICE_CONFIG, bufSize uint32, bytesNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryServiceConfigW.Addr(), 4, uintptr(service), uintptr(unsafe.Pointer(serviceConfig)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) { - var _p0 uint32 - if wait { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(done)), uintptr(_p0), 0, 0) +func QueryServiceLockStatus(mgr Handle, lockStatus *QUERY_SERVICE_LOCK_STATUS, bufSize uint32, bytesNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryServiceLockStatusW.Addr(), 4, uintptr(mgr), uintptr(unsafe.Pointer(lockStatus)), uintptr(bufSize), uintptr(unsafe.Pointer(bytesNeeded)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { - r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) - newlowoffset = uint32(r0) - if newlowoffset == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CloseHandle(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) +func QueryServiceStatus(service Handle, status *SERVICE_STATUS) (err error) { + r1, _, e1 := syscall.Syscall(procQueryServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(status)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetStdHandle(stdhandle uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetStdHandle(stdhandle uint32, handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0) +func QueryServiceStatusEx(service Handle, infoLevel uint32, buff *byte, buffSize uint32, bytesNeeded *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryServiceStatusEx.Addr(), 5, uintptr(service), uintptr(infoLevel), uintptr(unsafe.Pointer(buff)), uintptr(buffSize), uintptr(unsafe.Pointer(bytesNeeded)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func findNextFile1(handle Handle, data *win32finddata1) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FindClose(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { - r1, _, e1 := syscall.Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetCurrentDirectory(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { - r1, _, e1 := syscall.Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func RemoveDirectory(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DeleteFile(path *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func MoveFile(from *uint16, to *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetComputerName(buf *uint16, n *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nametype), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetEndOfFile(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetSystemTimeAsFileTime(time *Filetime) { - syscall.Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) - return -} - -func GetSystemTimePreciseAsFileTime(time *Filetime) { - syscall.Syscall(procGetSystemTimePreciseAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) - return -} - -func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0) - rc = uint32(r0) - if rc == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CancelIo(s Handle) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CancelIoEx(s Handle, o *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { - var _p0 uint32 - if inheritHandles { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) { - var _p0 uint32 - if inheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procOpenProcess.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(processId)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) { - r1, _, e1 := syscall.Syscall6(procShellExecuteW.Addr(), 6, uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd)) - if r1 <= 32 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) { - r0, _, _ := syscall.Syscall6(procSHGetKnownFolderPath.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(token), uintptr(unsafe.Pointer(path)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) - } - return -} - -func TerminateProcess(handle Handle, exitcode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetStartupInfo(startupInfo *StartupInfo) (err error) { - r1, _, e1 := syscall.Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { - r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) { - var _p0 uint32 - if bInheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { - r0, _, e1 := syscall.Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0) - event = uint32(r0) - if event == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) { - var _p0 uint32 - if waitAll { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall6(procWaitForMultipleObjects.Addr(), 4, uintptr(count), uintptr(handles), uintptr(_p0), uintptr(waitMilliseconds), 0, 0) - event = uint32(r0) - if event == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetFileType(filehandle Handle) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) { - r1, _, e1 := syscall.Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetEnvironmentStrings() (envs *uint16, err error) { - r0, _, e1 := syscall.Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0) - envs = (*uint16)(unsafe.Pointer(r0)) - if envs == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FreeEnvironmentStrings(envs *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { - var _p0 uint32 - if inheritExisting { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DestroyEnvironmentBlock(block *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getTickCount64() (ms uint64) { - r0, _, _ := syscall.Syscall(procGetTickCount64.Addr(), 0, 0, 0, 0) - ms = uint64(r0) - return -} - -func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetFileAttributes(name *uint16) (attrs uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - attrs = uint32(r0) - if attrs == INVALID_FILE_ATTRIBUTES { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetFileAttributes(name *uint16, attrs uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { - r1, _, e1 := syscall.Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetCommandLine() (cmd *uint16) { - r0, _, _ := syscall.Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0) - cmd = (*uint16)(unsafe.Pointer(r0)) - return -} - -func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { - r0, _, e1 := syscall.Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) - argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0)) - if argv == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func LocalFree(hmem Handle) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0) - handle = Handle(r0) - if handle != 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FlushFileBuffers(handle Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { - r0, _, e1 := syscall.Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0) - addr = uintptr(r0) - if addr == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func UnmapViewOfFile(addr uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FlushViewOfFile(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func VirtualLock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func VirtualUnlock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) { - r0, _, e1 := syscall.Syscall6(procVirtualAlloc.Addr(), 4, uintptr(address), uintptr(size), uintptr(alloctype), uintptr(protect), 0, 0) - value = uintptr(r0) - if value == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) { - r1, _, e1 := syscall.Syscall(procVirtualFree.Addr(), 3, uintptr(address), uintptr(size), uintptr(freetype)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procVirtualProtect.Addr(), 4, uintptr(address), uintptr(size), uintptr(newprotect), uintptr(unsafe.Pointer(oldprotect)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { - var _p0 uint32 - if watchSubTree { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { - r0, _, e1 := syscall.Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0) - store = Handle(r0) - if store == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) { - r0, _, e1 := syscall.Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0) - context = (*CertContext)(unsafe.Pointer(r0)) - if context == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) { - r1, _, e1 := syscall.Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertCloseStore(store Handle, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) { - r1, _, e1 := syscall.Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertFreeCertificateChain(ctx *CertChainContext) { - syscall.Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) - return -} - -func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) { - r0, _, e1 := syscall.Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) - context = (*CertContext)(unsafe.Pointer(r0)) - if context == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertFreeCertificateContext(ctx *CertContext) (err error) { - r1, _, e1 := syscall.Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) { - r1, _, e1 := syscall.Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) { - r0, _, _ := syscall.Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0) - if r0 != 0 { - regerrno = syscall.Errno(r0) + err = errnoErr(e1) } return } @@ -1912,14 +904,6 @@ func RegCloseKey(key Handle) (regerrno error) { return } -func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) { - r0, _, _ := syscall.Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) - if r0 != 0 { - regerrno = syscall.Errno(r0) - } - return -} - func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { r0, _, _ := syscall.Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0) if r0 != 0 { @@ -1928,6 +912,22 @@ func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reser return } +func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) { + r0, _, _ := syscall.Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0) + if r0 != 0 { + regerrno = syscall.Errno(r0) + } + return +} + +func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) { + r0, _, _ := syscall.Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) + if r0 != 0 { + regerrno = syscall.Errno(r0) + } + return +} + func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { r0, _, _ := syscall.Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) if r0 != 0 { @@ -1936,1257 +936,254 @@ func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32 return } -func GetCurrentProcessId() (pid uint32) { - r0, _, _ := syscall.Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0) - pid = uint32(r0) - return -} - -func GetConsoleMode(console Handle, mode *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetConsoleMode(console Handle, mode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(console), uintptr(mode), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { - r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { - r1, _, e1 := syscall.Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { - r1, _, e1 := syscall.Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procThread32First.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error) { - r1, _, e1 := syscall.Syscall(procThread32Next.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) { - r1, _, e1 := syscall.Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetCurrentThreadId() (id uint32) { - r0, _, _ := syscall.Syscall(procGetCurrentThreadId.Addr(), 0, 0, 0, 0) - id = uint32(r0) - return -} - -func CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(manualReset), uintptr(initialState), uintptr(unsafe.Pointer(name)), 0, 0) +func RegisterEventSource(uncServerName *uint16, sourceName *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procRegisterEventSourceW.Addr(), 2, uintptr(unsafe.Pointer(uncServerName)), uintptr(unsafe.Pointer(sourceName)), 0) handle = Handle(r0) if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateEventExW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func ReportEvent(log Handle, etype uint16, category uint16, eventId uint32, usrSId uintptr, numStrings uint16, dataSize uint32, strings **uint16, rawData *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procReportEventW.Addr(), 9, uintptr(log), uintptr(etype), uintptr(category), uintptr(eventId), uintptr(usrSId), uintptr(numStrings), uintptr(dataSize), uintptr(unsafe.Pointer(strings)), uintptr(unsafe.Pointer(rawData))) + if r1 == 0 { + err = errnoErr(e1) } return } -func OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { +func RevertToSelf() (err error) { + r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) { + r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(countExplicitEntries), uintptr(unsafe.Pointer(explicitEntries)), uintptr(unsafe.Pointer(oldACL)), uintptr(unsafe.Pointer(newACL)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { + var _p0 *uint16 + _p0, ret = syscall.UTF16PtrFromString(objectName) + if ret != nil { + return + } + return _SetNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl) +} + +func _SetNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { + r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfoW.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) { + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(controlBitsOfInterest), uintptr(controlBitsToSet)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) { var _p0 uint32 - if inheritHandle { + if daclPresent { _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procOpenEventW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procSetEvent.Addr(), 1, uintptr(event), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ResetEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(event), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func PulseEvent(event Handle) (err error) { - r1, _, e1 := syscall.Syscall(procPulseEvent.Addr(), 1, uintptr(event), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) { - var _p0 uint32 - if initialOwner { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procCreateMutexW.Addr(), 3, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(_p0), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall6(procCreateMutexExW.Addr(), 4, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { - var _p0 uint32 - if inheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procOpenMutexW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ReleaseMutex(mutex Handle) (err error) { - r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SleepEx(milliseconds uint32, alertable bool) (ret uint32) { - var _p0 uint32 - if alertable { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, _ := syscall.Syscall(procSleepEx.Addr(), 2, uintptr(milliseconds), uintptr(_p0), 0) - ret = uint32(r0) - return -} - -func CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procCreateJobObjectW.Addr(), 2, uintptr(unsafe.Pointer(jobAttr)), uintptr(unsafe.Pointer(name)), 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func AssignProcessToJobObject(job Handle, process Handle) (err error) { - r1, _, e1 := syscall.Syscall(procAssignProcessToJobObject.Addr(), 2, uintptr(job), uintptr(process), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func TerminateJobObject(job Handle, exitCode uint32) (err error) { - r1, _, e1 := syscall.Syscall(procTerminateJobObject.Addr(), 2, uintptr(job), uintptr(exitCode), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetErrorMode(mode uint32) (ret uint32) { - r0, _, _ := syscall.Syscall(procSetErrorMode.Addr(), 1, uintptr(mode), 0, 0) - ret = uint32(r0) - return -} - -func ResumeThread(thread Handle) (ret uint32, err error) { - r0, _, e1 := syscall.Syscall(procResumeThread.Addr(), 1, uintptr(thread), 0, 0) - ret = uint32(r0) - if ret == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetPriorityClass(process Handle, priorityClass uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetPriorityClass.Addr(), 2, uintptr(process), uintptr(priorityClass), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetPriorityClass(process Handle) (ret uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetPriorityClass.Addr(), 1, uintptr(process), 0, 0) - ret = uint32(r0) - if ret == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobObjectInformation uintptr, JobObjectInformationLength uint32, retlen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procQueryInformationJobObject.Addr(), 5, uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), uintptr(unsafe.Pointer(retlen)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error) { - r0, _, e1 := syscall.Syscall6(procSetInformationJobObject.Addr(), 4, uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), 0, 0) - ret = int(r0) - if ret == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGenerateConsoleCtrlEvent.Addr(), 2, uintptr(ctrlEvent), uintptr(processGroupID), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetProcessId(process Handle) (id uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetProcessId.Addr(), 1, uintptr(process), 0, 0) - id = uint32(r0) - if id == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) { - var _p0 uint32 - if inheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall(procOpenThread.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(threadId)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetProcessPriorityBoost(process Handle, disable bool) (err error) { - var _p0 uint32 - if disable { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procSetProcessPriorityBoost.Addr(), 2, uintptr(process), uintptr(_p0), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32) { - syscall.Syscall6(procGetProcessWorkingSetSizeEx.Addr(), 4, uintptr(hProcess), uintptr(unsafe.Pointer(lpMinimumWorkingSetSize)), uintptr(unsafe.Pointer(lpMaximumWorkingSetSize)), uintptr(unsafe.Pointer(flags)), 0, 0) - return -} - -func SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetProcessWorkingSetSizeEx.Addr(), 4, uintptr(hProcess), uintptr(dwMinimumWorkingSetSize), uintptr(dwMaximumWorkingSetSize), uintptr(flags), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DeleteVolumeMountPoint(volumeMountPoint *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDeleteVolumeMountPointW.Addr(), 1, uintptr(unsafe.Pointer(volumeMountPoint)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FindFirstVolume(volumeName *uint16, bufferLength uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstVolumeW.Addr(), 2, uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FindFirstVolumeMountPoint(rootPathName *uint16, volumeMountPoint *uint16, bufferLength uint32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procFindFirstVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FindNextVolume(findVolume Handle, volumeName *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextVolumeW.Addr(), 3, uintptr(findVolume), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procFindNextVolumeMountPointW.Addr(), 3, uintptr(findVolumeMountPoint), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FindVolumeClose(findVolume Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindVolumeClose.Addr(), 1, uintptr(findVolume), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) { - r1, _, e1 := syscall.Syscall(procFindVolumeMountPointClose.Addr(), 1, uintptr(findVolumeMountPoint), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) { - r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetDriveType(rootPathName *uint16) (driveType uint32) { - r0, _, _ := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0) - driveType = uint32(r0) - return -} - -func GetLogicalDrives() (drivesBitMask uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLogicalDrives.Addr(), 0, 0, 0, 0) - drivesBitMask = uint32(r0) - if drivesBitMask == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetLogicalDriveStringsW.Addr(), 2, uintptr(bufferLength), uintptr(unsafe.Pointer(buffer)), 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetVolumeInformation(rootPathName *uint16, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetVolumeInformationW.Addr(), 8, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetVolumeInformationByHandle(file Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procGetVolumeInformationByHandleW.Addr(), 8, uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetVolumeNameForVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferlength)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetVolumePathName(fileName *uint16, volumePathName *uint16, bufferLength uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetVolumePathNameW.Addr(), 3, uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(volumePathName)), uintptr(bufferLength)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetVolumePathNamesForVolumeName(volumeName *uint16, volumePathNames *uint16, bufferLength uint32, returnLength *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetVolumePathNamesForVolumeNameW.Addr(), 4, uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(volumePathNames)), uintptr(bufferLength), uintptr(unsafe.Pointer(returnLength)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetVolumeLabelW.Addr(), 2, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeName)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procSetVolumeMountPointW.Addr(), 2, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { - r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0) - ret = int32(r0) - if ret == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ExitWindowsEx(flags uint32, reason uint32) (err error) { - r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func InitiateSystemShutdownEx(machineName *uint16, message *uint16, timeout uint32, forceAppsClosed bool, rebootAfterShutdown bool, reason uint32) (err error) { - var _p0 uint32 - if forceAppsClosed { - _p0 = 1 - } else { - _p0 = 0 } var _p1 uint32 - if rebootAfterShutdown { + if daclDefaulted { _p1 = 1 - } else { - _p1 = 0 } - r1, _, e1 := syscall.Syscall6(procInitiateSystemShutdownExW.Addr(), 6, uintptr(unsafe.Pointer(machineName)), uintptr(unsafe.Pointer(message)), uintptr(timeout), uintptr(_p0), uintptr(_p1), uintptr(reason)) + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procSetProcessShutdownParameters.Addr(), 2, uintptr(level), uintptr(flags), 0) +func setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) { + var _p0 uint32 + if groupDefaulted { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(_p0)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetProcessShutdownParameters.Addr(), 2, uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags)), 0) +func setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) { + var _p0 uint32 + if ownerDefaulted { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(_p0)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { - r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0) - if r0 != 0 { - ret = syscall.Errno(r0) +func setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) { + syscall.Syscall(procSetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) + return +} + +func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) { + var _p0 uint32 + if saclPresent { + _p0 = 1 } - return -} - -func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) { - r0, _, _ := syscall.Syscall(procStringFromGUID2.Addr(), 3, uintptr(unsafe.Pointer(rguid)), uintptr(unsafe.Pointer(lpsz)), uintptr(cchMax)) - chars = int32(r0) - return -} - -func coCreateGuid(pguid *GUID) (ret error) { - r0, _, _ := syscall.Syscall(procCoCreateGuid.Addr(), 1, uintptr(unsafe.Pointer(pguid)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) + var _p1 uint32 + if saclDefaulted { + _p1 = 1 } - return -} - -func CoTaskMemFree(address unsafe.Pointer) { - syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0) - return -} - -func rtlGetVersion(info *OsVersionInfoEx) (ret error) { - r0, _, _ := syscall.Syscall(procRtlGetVersion.Addr(), 1, uintptr(unsafe.Pointer(info)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) - } - return -} - -func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) { - syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) - return -} - -func getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetProcessPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetThreadPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) +func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) { + syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) + return +} + +func SetServiceStatus(service Handle, serviceStatus *SERVICE_STATUS) (err error) { + r1, _, e1 := syscall.Syscall(procSetServiceStatus.Addr(), 2, uintptr(service), uintptr(unsafe.Pointer(serviceStatus)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetUserPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) +func SetThreadToken(thread *Handle, token Token) (err error) { + r1, _, e1 := syscall.Syscall(procSetThreadToken.Addr(), 2, uintptr(unsafe.Pointer(thread)), uintptr(token), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetSystemPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) +func SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { - var _p0 *uint32 - if len(processIds) > 0 { - _p0 = &processIds[0] - } - r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(len(processIds)), uintptr(unsafe.Pointer(bytesReturned))) +func StartServiceCtrlDispatcher(serviceTable *SERVICE_TABLE_ENTRY) (err error) { + r1, _, e1 := syscall.Syscall(procStartServiceCtrlDispatcherW.Addr(), 1, uintptr(unsafe.Pointer(serviceTable)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { - r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) - if r0 != 0 { - sockerr = syscall.Errno(r0) +func StartService(service Handle, numArgs uint32, argVectors **uint16) (err error) { + r1, _, e1 := syscall.Syscall(procStartServiceW.Addr(), 3, uintptr(service), uintptr(numArgs), uintptr(unsafe.Pointer(argVectors))) + if r1 == 0 { + err = errnoErr(e1) } return } -func WSACleanup() (err error) { - r1, _, e1 := syscall.Syscall(procWSACleanup.Addr(), 0, 0, 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) { + r1, _, e1 := syscall.Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) } return } -func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { - r1, _, e1 := syscall.Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func CertCloseStore(store Handle, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) } return } -func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { - r0, _, e1 := syscall.Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol)) +func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) { + r0, _, e1 := syscall.Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) + context = (*CertContext)(unsafe.Pointer(r0)) + if context == nil { + err = errnoErr(e1) + } + return +} + +func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) { + r0, _, e1 := syscall.Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0) + context = (*CertContext)(unsafe.Pointer(r0)) + if context == nil { + err = errnoErr(e1) + } + return +} + +func CertFreeCertificateChain(ctx *CertChainContext) { + syscall.Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + return +} + +func CertFreeCertificateContext(ctx *CertContext) (err error) { + r1, _, e1 := syscall.Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) { + r1, _, e1 := syscall.Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) handle = Handle(r0) if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := syscall.Syscall6(procsendto.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(tolen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { + r0, _, e1 := syscall.Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0) + store = Handle(r0) + if store == 0 { + err = errnoErr(e1) } return } -func recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen *int32) (n int32, err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r0, _, e1 := syscall.Syscall6(procrecvfrom.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) - n = int32(r0) - if n == -1 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { - r1, _, e1 := syscall.Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { - r1, _, e1 := syscall.Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := syscall.Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func listen(s Handle, backlog int32) (err error) { - r1, _, e1 := syscall.Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func shutdown(s Handle, how int32) (err error) { - r1, _, e1 := syscall.Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Closesocket(s Handle) (err error) { - r1, _, e1 := syscall.Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := syscall.Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) +func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) { + r1, _, e1 := syscall.Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { - syscall.Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0) - return -} - -func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := syscall.Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetHostByName(name string) (h *Hostent, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(name) - if err != nil { - return - } - return _GetHostByName(_p0) -} - -func _GetHostByName(name *byte) (h *Hostent, err error) { - r0, _, e1 := syscall.Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - h = (*Hostent)(unsafe.Pointer(r0)) - if h == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetServByName(name string, proto string) (s *Servent, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(name) - if err != nil { - return - } - var _p1 *byte - _p1, err = syscall.BytePtrFromString(proto) - if err != nil { - return - } - return _GetServByName(_p0, _p1) -} - -func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { - r0, _, e1 := syscall.Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0) - s = (*Servent)(unsafe.Pointer(r0)) - if s == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func Ntohs(netshort uint16) (u uint16) { - r0, _, _ := syscall.Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0) - u = uint16(r0) - return -} - -func GetProtoByName(name string) (p *Protoent, err error) { - var _p0 *byte - _p0, err = syscall.BytePtrFromString(name) - if err != nil { - return - } - return _GetProtoByName(_p0) -} - -func _GetProtoByName(name *byte) (p *Protoent, err error) { - r0, _, e1 := syscall.Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - p = (*Protoent)(unsafe.Pointer(r0)) - if p == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) { + r0, _, _ := syscall.Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0) + same = r0 != 0 return } @@ -3212,27 +1209,8 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) { return } -func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) { - r0, _, _ := syscall.Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0) - same = r0 != 0 - return -} - -func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { - r0, _, _ := syscall.Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0) - if r0 != 0 { - sockerr = syscall.Errno(r0) - } - return -} - -func FreeAddrInfoW(addrinfo *AddrinfoW) { - syscall.Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0) - return -} - -func GetIfEntry(pIfRow *MibIfRow) (errcode error) { - r0, _, _ := syscall.Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0) +func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { + r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) if r0 != 0 { errcode = syscall.Errno(r0) } @@ -3247,84 +1225,1416 @@ func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { return } -func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) { - r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(handle), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { - r0, _, e1 := syscall.Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) - n = int32(r0) - if n == -1 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { - r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) +func GetIfEntry(pIfRow *MibIfRow) (errcode error) { + r0, _, _ := syscall.Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0) if r0 != 0 { errcode = syscall.Errno(r0) } return } +func AssignProcessToJobObject(job Handle, process Handle) (err error) { + r1, _, e1 := syscall.Syscall(procAssignProcessToJobObject.Addr(), 2, uintptr(job), uintptr(process), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CancelIo(s Handle) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CancelIoEx(s Handle, o *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CloseHandle(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { + r1, _, e1 := syscall.Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateEventExW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateEventW.Addr(), 4, uintptr(unsafe.Pointer(eventAttrs)), uintptr(manualReset), uintptr(initialState), uintptr(unsafe.Pointer(name)), 0, 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile Handle) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) + if r1&0xff == 0 { + err = errnoErr(e1) + } + return +} + +func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreateJobObject(jobAttr *SecurityAttributes, name *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procCreateJobObjectW.Addr(), 2, uintptr(unsafe.Pointer(jobAttr)), uintptr(unsafe.Pointer(name)), 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreateMutexEx(mutexAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall6(procCreateMutexExW.Addr(), 4, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(desiredAccess), 0, 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreateMutex(mutexAttrs *SecurityAttributes, initialOwner bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if initialOwner { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall(procCreateMutexW.Addr(), 3, uintptr(unsafe.Pointer(mutexAttrs)), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { + var _p0 uint32 + if inheritHandles { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) + if r1&0xff == 0 { + err = errnoErr(e1) + } + return +} + +func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func DefineDosDevice(flags uint32, deviceName *uint16, targetPath *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procDefineDosDeviceW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func DeleteFile(path *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func DeleteVolumeMountPoint(volumeMountPoint *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procDeleteVolumeMountPointW.Addr(), 1, uintptr(unsafe.Pointer(volumeMountPoint)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) { + var _p0 uint32 + if bInheritHandle { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ExitProcess(exitcode uint32) { + syscall.Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) + return +} + +func FindClose(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func FindFirstVolumeMountPoint(rootPathName *uint16, volumeMountPoint *uint16, bufferLength uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procFindFirstVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func FindFirstVolume(volumeName *uint16, bufferLength uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procFindFirstVolumeW.Addr(), 2, uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength), 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func findNextFile1(handle Handle, data *win32finddata1) (err error) { + r1, _, e1 := syscall.Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FindNextVolumeMountPoint(findVolumeMountPoint Handle, volumeMountPoint *uint16, bufferLength uint32) (err error) { + r1, _, e1 := syscall.Syscall(procFindNextVolumeMountPointW.Addr(), 3, uintptr(findVolumeMountPoint), uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(bufferLength)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FindNextVolume(findVolume Handle, volumeName *uint16, bufferLength uint32) (err error) { + r1, _, e1 := syscall.Syscall(procFindNextVolumeW.Addr(), 3, uintptr(findVolume), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferLength)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FindVolumeClose(findVolume Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFindVolumeClose.Addr(), 1, uintptr(findVolume), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFindVolumeMountPointClose.Addr(), 1, uintptr(findVolumeMountPoint), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FlushFileBuffers(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FlushViewOfFile(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { + var _p0 *uint16 + if len(buf) > 0 { + _p0 = &buf[0] + } + r0, _, e1 := syscall.Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func FreeEnvironmentStrings(envs *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FreeLibrary(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GenerateConsoleCtrlEvent(ctrlEvent uint32, processGroupID uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGenerateConsoleCtrlEvent.Addr(), 2, uintptr(ctrlEvent), uintptr(processGroupID), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetACP() (acp uint32) { r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0) acp = uint32(r0) return } +func GetCommandLine() (cmd *uint16) { + r0, _, _ := syscall.Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0) + cmd = (*uint16)(unsafe.Pointer(r0)) + return +} + +func GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nametype), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetComputerName(buf *uint16, n *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetConsoleMode(console Handle, mode *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) { + r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetCurrentProcessId() (pid uint32) { + r0, _, _ := syscall.Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0) + pid = uint32(r0) + return +} + +func GetCurrentThreadId() (id uint32) { + r0, _, _ := syscall.Syscall(procGetCurrentThreadId.Addr(), 0, 0, 0, 0) + id = uint32(r0) + return +} + +func GetDiskFreeSpaceEx(directoryName *uint16, freeBytesAvailableToCaller *uint64, totalNumberOfBytes *uint64, totalNumberOfFreeBytes *uint64) (err error) { + r1, _, e1 := syscall.Syscall6(procGetDiskFreeSpaceExW.Addr(), 4, uintptr(unsafe.Pointer(directoryName)), uintptr(unsafe.Pointer(freeBytesAvailableToCaller)), uintptr(unsafe.Pointer(totalNumberOfBytes)), uintptr(unsafe.Pointer(totalNumberOfFreeBytes)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetDriveType(rootPathName *uint16) (driveType uint32) { + r0, _, _ := syscall.Syscall(procGetDriveTypeW.Addr(), 1, uintptr(unsafe.Pointer(rootPathName)), 0, 0) + driveType = uint32(r0) + return +} + +func GetEnvironmentStrings() (envs *uint16, err error) { + r0, _, e1 := syscall.Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0) + envs = (*uint16)(unsafe.Pointer(r0)) + if envs == nil { + err = errnoErr(e1) + } + return +} + +func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { + r1, _, e1 := syscall.Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileAttributes(name *uint16) (attrs uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + attrs = uint32(r0) + if attrs == INVALID_FILE_ATTRIBUTES { + err = errnoErr(e1) + } + return +} + +func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { + r1, _, e1 := syscall.Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileInformationByHandleEx(handle Handle, class uint32, outBuffer *byte, outBufferLen uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileType(filehandle Handle) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetFinalPathNameByHandleW(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { + r0, _, e1 := syscall.Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetLastError() (lasterr error) { + r0, _, _ := syscall.Syscall(procGetLastError.Addr(), 0, 0, 0, 0) + if r0 != 0 { + lasterr = syscall.Errno(r0) + } + return +} + +func GetLogicalDriveStrings(bufferLength uint32, buffer *uint16) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetLogicalDriveStringsW.Addr(), 2, uintptr(bufferLength), uintptr(unsafe.Pointer(buffer)), 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetLogicalDrives() (drivesBitMask uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetLogicalDrives.Addr(), 0, 0, 0, 0) + drivesBitMask = uint32(r0) + if drivesBitMask == 0 { + err = errnoErr(e1) + } + return +} + +func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetModuleFileName(module Handle, filename *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(filename)), uintptr(size)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetModuleHandleEx(flags uint32, moduleName *uint16, module *Handle) (err error) { + r1, _, e1 := syscall.Syscall(procGetModuleHandleExW.Addr(), 3, uintptr(flags), uintptr(unsafe.Pointer(moduleName)), uintptr(unsafe.Pointer(module))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) { + var _p0 uint32 + if wait { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(done)), uintptr(_p0), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetPriorityClass(process Handle) (ret uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetPriorityClass.Addr(), 1, uintptr(process), 0, 0) + ret = uint32(r0) + if ret == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(procname) + if err != nil { + return + } + return _GetProcAddress(module, _p0) +} + +func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { + r0, _, e1 := syscall.Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0) + proc = uintptr(r0) + if proc == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcessId(process Handle) (id uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetProcessId.Addr(), 1, uintptr(process), 0, 0) + id = uint32(r0) + if id == 0 { + err = errnoErr(e1) + } + return +} + +func getProcessPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetProcessPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcessShutdownParameters(level *uint32, flags *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetProcessShutdownParameters.Addr(), 2, uintptr(unsafe.Pointer(level)), uintptr(unsafe.Pointer(flags)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { + r1, _, e1 := syscall.Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcessWorkingSetSizeEx(hProcess Handle, lpMinimumWorkingSetSize *uintptr, lpMaximumWorkingSetSize *uintptr, flags *uint32) { + syscall.Syscall6(procGetProcessWorkingSetSizeEx.Addr(), 4, uintptr(hProcess), uintptr(unsafe.Pointer(lpMinimumWorkingSetSize)), uintptr(unsafe.Pointer(lpMaximumWorkingSetSize)), uintptr(unsafe.Pointer(flags)), 0, 0) + return +} + +func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetStartupInfo(startupInfo *StartupInfo) (err error) { + r1, _, e1 := syscall.Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetStdHandle(stdhandle uint32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + err = errnoErr(e1) + } + return +} + +func getSystemPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetSystemPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetSystemTimeAsFileTime(time *Filetime) { + syscall.Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) + return +} + +func GetSystemTimePreciseAsFileTime(time *Filetime) { + syscall.Syscall(procGetSystemTimePreciseAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) + return +} + +func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetSystemWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + err = errnoErr(e1) + } + return +} + +func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func getThreadPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetThreadPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getTickCount64() (ms uint64) { + r0, _, _ := syscall.Syscall(procGetTickCount64.Addr(), 0, 0, 0, 0) + ms = uint64(r0) + return +} + +func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0) + rc = uint32(r0) + if rc == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func getUserPreferredUILanguages(flags uint32, numLanguages *uint32, buf *uint16, bufSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetUserPreferredUILanguages.Addr(), 4, uintptr(flags), uintptr(unsafe.Pointer(numLanguages)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(bufSize)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetVersion() (ver uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetVersion.Addr(), 0, 0, 0, 0) + ver = uint32(r0) + if ver == 0 { + err = errnoErr(e1) + } + return +} + +func GetVolumeInformationByHandle(file Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procGetVolumeInformationByHandleW.Addr(), 8, uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetVolumeInformation(rootPathName *uint16, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procGetVolumeInformationW.Addr(), 8, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetVolumeNameForVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16, bufferlength uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetVolumeNameForVolumeMountPointW.Addr(), 3, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), uintptr(bufferlength)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetVolumePathName(fileName *uint16, volumePathName *uint16, bufferLength uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetVolumePathNameW.Addr(), 3, uintptr(unsafe.Pointer(fileName)), uintptr(unsafe.Pointer(volumePathName)), uintptr(bufferLength)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetVolumePathNamesForVolumeName(volumeName *uint16, volumePathNames *uint16, bufferLength uint32, returnLength *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetVolumePathNamesForVolumeNameW.Addr(), 4, uintptr(unsafe.Pointer(volumeName)), uintptr(unsafe.Pointer(volumePathNames)), uintptr(bufferLength), uintptr(unsafe.Pointer(returnLength)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + err = errnoErr(e1) + } + return +} + +func IsWow64Process(handle Handle, isWow64 *bool) (err error) { + var _p0 uint32 + if *isWow64 { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall(procIsWow64Process.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(&_p0)), 0) + *isWow64 = _p0 != 0 + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(libname) + if err != nil { + return + } + return _LoadLibraryEx(_p0, zero, flags) +} + +func _LoadLibraryEx(libname *uint16, zero Handle, flags uintptr) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadLibraryExW.Addr(), 3, uintptr(unsafe.Pointer(libname)), uintptr(zero), uintptr(flags)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func LoadLibrary(libname string) (handle Handle, err error) { + var _p0 *uint16 + _p0, err = syscall.UTF16PtrFromString(libname) + if err != nil { + return + } + return _LoadLibrary(_p0) +} + +func _LoadLibrary(libname *uint16) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(libname)), 0, 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func LocalFree(hmem Handle) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0) + handle = Handle(r0) + if handle != 0 { + err = errnoErr(e1) + } + return +} + +func LockFileEx(file Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { + r0, _, e1 := syscall.Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0) + addr = uintptr(r0) + if addr == 0 { + err = errnoErr(e1) + } + return +} + +func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func MoveFile(from *uint16, to *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) { r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) nwrite = int32(r0) if nwrite == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall(procOpenEventW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) } return } -func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func OpenMutex(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall(procOpenMutexW.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) } return } -func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { - r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) +func OpenProcess(desiredAccess uint32, inheritHandle bool, processId uint32) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall(procOpenProcess.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(processId)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall(procOpenThread.Addr(), 3, uintptr(desiredAccess), uintptr(_p0), uintptr(threadId)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ProcessIdToSessionId(pid uint32, sessionid *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procProcessIdToSessionId.Addr(), 2, uintptr(pid), uintptr(unsafe.Pointer(sessionid)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func PulseEvent(event Handle) (err error) { + r1, _, e1 := syscall.Syscall(procPulseEvent.Addr(), 1, uintptr(event), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func QueryDosDevice(deviceName *uint16, targetPath *uint16, max uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procQueryDosDeviceW.Addr(), 3, uintptr(unsafe.Pointer(deviceName)), uintptr(unsafe.Pointer(targetPath)), uintptr(max)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobObjectInformation uintptr, JobObjectInformationLength uint32, retlen *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procQueryInformationJobObject.Addr(), 5, uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), uintptr(unsafe.Pointer(retlen)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { + r1, _, e1 := syscall.Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { + var _p0 uint32 + if watchSubTree { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := syscall.Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ReleaseMutex(mutex Handle) (err error) { + r1, _, e1 := syscall.Syscall(procReleaseMutex.Addr(), 1, uintptr(mutex), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func RemoveDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ResetEvent(event Handle) (err error) { + r1, _, e1 := syscall.Syscall(procResetEvent.Addr(), 1, uintptr(event), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ResumeThread(thread Handle) (ret uint32, err error) { + r0, _, e1 := syscall.Syscall(procResumeThread.Addr(), 1, uintptr(thread), 0, 0) + ret = uint32(r0) + if ret == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func SetConsoleCursorPosition(console Handle, position Coord) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleCursorPosition.Addr(), 2, uintptr(console), uintptr(*((*uint32)(unsafe.Pointer(&position)))), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetConsoleMode(console Handle, mode uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetConsoleMode.Addr(), 2, uintptr(console), uintptr(mode), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetCurrentDirectory(path *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetEndOfFile(handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetErrorMode(mode uint32) (ret uint32) { + r0, _, _ := syscall.Syscall(procSetErrorMode.Addr(), 1, uintptr(mode), 0, 0) + ret = uint32(r0) + return +} + +func SetEvent(event Handle) (err error) { + r1, _, e1 := syscall.Syscall(procSetEvent.Addr(), 1, uintptr(event), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetFileAttributes(name *uint16, attrs uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) { + r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(handle), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { + r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) + newlowoffset = uint32(r0) + if newlowoffset == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { + r1, _, e1 := syscall.Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetInformationJobObject(job Handle, JobObjectInformationClass uint32, JobObjectInformation uintptr, JobObjectInformationLength uint32) (ret int, err error) { + r0, _, e1 := syscall.Syscall6(procSetInformationJobObject.Addr(), 4, uintptr(job), uintptr(JobObjectInformationClass), uintptr(JobObjectInformation), uintptr(JobObjectInformationLength), 0, 0) + ret = int(r0) + if ret == 0 { + err = errnoErr(e1) + } + return +} + +func SetPriorityClass(process Handle, priorityClass uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetPriorityClass.Addr(), 2, uintptr(process), uintptr(priorityClass), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetProcessPriorityBoost(process Handle, disable bool) (err error) { + var _p0 uint32 + if disable { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall(procSetProcessPriorityBoost.Addr(), 2, uintptr(process), uintptr(_p0), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetProcessShutdownParameters(level uint32, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procSetProcessShutdownParameters.Addr(), 2, uintptr(level), uintptr(flags), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetProcessWorkingSetSizeEx(hProcess Handle, dwMinimumWorkingSetSize uintptr, dwMaximumWorkingSetSize uintptr, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetProcessWorkingSetSizeEx.Addr(), 4, uintptr(hProcess), uintptr(dwMinimumWorkingSetSize), uintptr(dwMaximumWorkingSetSize), uintptr(flags), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetStdHandle(stdhandle uint32, handle Handle) (err error) { + r1, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetVolumeLabel(rootPathName *uint16, volumeName *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procSetVolumeLabelW.Addr(), 2, uintptr(unsafe.Pointer(rootPathName)), uintptr(unsafe.Pointer(volumeName)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetVolumeMountPoint(volumeMountPoint *uint16, volumeName *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procSetVolumeMountPointW.Addr(), 2, uintptr(unsafe.Pointer(volumeMountPoint)), uintptr(unsafe.Pointer(volumeName)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SleepEx(milliseconds uint32, alertable bool) (ret uint32) { + var _p0 uint32 + if alertable { + _p0 = 1 + } + r0, _, _ := syscall.Syscall(procSleepEx.Addr(), 2, uintptr(milliseconds), uintptr(_p0), 0) + ret = uint32(r0) + return +} + +func TerminateJobObject(job Handle, exitCode uint32) (err error) { + r1, _, e1 := syscall.Syscall(procTerminateJobObject.Addr(), 2, uintptr(job), uintptr(exitCode), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func TerminateProcess(handle Handle, exitcode uint32) (err error) { + r1, _, e1 := syscall.Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func Thread32First(snapshot Handle, threadEntry *ThreadEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procThread32First.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func Thread32Next(snapshot Handle, threadEntry *ThreadEntry32) (err error) { + r1, _, e1 := syscall.Syscall(procThread32Next.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(threadEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func UnlockFileEx(file Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func UnmapViewOfFile(addr uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) { + r0, _, e1 := syscall.Syscall6(procVirtualAlloc.Addr(), 4, uintptr(address), uintptr(size), uintptr(alloctype), uintptr(protect), 0, 0) + value = uintptr(r0) + if value == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) { + r1, _, e1 := syscall.Syscall(procVirtualFree.Addr(), 3, uintptr(address), uintptr(size), uintptr(freetype)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualLock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procVirtualProtect.Addr(), 4, uintptr(address), uintptr(size), uintptr(newprotect), uintptr(unsafe.Pointer(oldprotect)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualUnlock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func waitForMultipleObjects(count uint32, handles uintptr, waitAll bool, waitMilliseconds uint32) (event uint32, err error) { + var _p0 uint32 + if waitAll { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall6(procWaitForMultipleObjects.Addr(), 4, uintptr(count), uintptr(handles), uintptr(_p0), uintptr(waitMilliseconds), 0, 0) + event = uint32(r0) + if event == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { + r0, _, e1 := syscall.Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0) + event = uint32(r0) + if event == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { + r1, _, e1 := syscall.Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := syscall.Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := syscall.Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { + syscall.Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0) + return +} + +func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func NetApiBufferFree(buf *byte) (neterr error) { + r0, _, _ := syscall.Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) if r0 != 0 { neterr = syscall.Errno(r0) } @@ -3339,310 +2649,140 @@ func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (nete return } -func NetApiBufferFree(buf *byte) (neterr error) { - r0, _, _ := syscall.Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) +func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { + r0, _, _ := syscall.Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) if r0 != 0 { neterr = syscall.Errno(r0) } return } -func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) +func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) { + syscall.Syscall(procRtlGetNtVersionNumbers.Addr(), 3, uintptr(unsafe.Pointer(majorVersion)), uintptr(unsafe.Pointer(minorVersion)), uintptr(unsafe.Pointer(buildNumber))) + return +} + +func rtlGetVersion(info *OsVersionInfoEx) (ret error) { + r0, _, _ := syscall.Syscall(procRtlGetVersion.Addr(), 1, uintptr(unsafe.Pointer(info)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func clsidFromString(lpsz *uint16, pclsid *GUID) (ret error) { + r0, _, _ := syscall.Syscall(procCLSIDFromString.Addr(), 2, uintptr(unsafe.Pointer(lpsz)), uintptr(unsafe.Pointer(pclsid)), 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func coCreateGuid(pguid *GUID) (ret error) { + r0, _, _ := syscall.Syscall(procCoCreateGuid.Addr(), 1, uintptr(unsafe.Pointer(pguid)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func CoTaskMemFree(address unsafe.Pointer) { + syscall.Syscall(procCoTaskMemFree.Addr(), 1, uintptr(address), 0, 0) + return +} + +func stringFromGUID2(rguid *GUID, lpsz *uint16, cchMax int32) (chars int32) { + r0, _, _ := syscall.Syscall(procStringFromGUID2.Addr(), 3, uintptr(unsafe.Pointer(rguid)), uintptr(unsafe.Pointer(lpsz)), uintptr(cchMax)) + chars = int32(r0) + return +} + +func EnumProcesses(processIds []uint32, bytesReturned *uint32) (err error) { + var _p0 *uint32 + if len(processIds) > 0 { + _p0 = &processIds[0] + } + r1, _, e1 := syscall.Syscall(procEnumProcesses.Addr(), 3, uintptr(unsafe.Pointer(_p0)), uintptr(len(processIds)), uintptr(unsafe.Pointer(bytesReturned))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) +func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) + if r1&0xff == 0 { + err = errnoErr(e1) + } + return +} + +func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0) + if r1&0xff == 0 { + err = errnoErr(e1) + } + return +} + +func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { + r0, _, e1 := syscall.Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) + argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0)) + if argv == nil { + err = errnoErr(e1) + } + return +} + +func shGetKnownFolderPath(id *KNOWNFOLDERID, flags uint32, token Token, path **uint16) (ret error) { + r0, _, _ := syscall.Syscall6(procSHGetKnownFolderPath.Addr(), 4, uintptr(unsafe.Pointer(id)), uintptr(flags), uintptr(token), uintptr(unsafe.Pointer(path)), 0, 0) + if r0 != 0 { + ret = syscall.Errno(r0) + } + return +} + +func ShellExecute(hwnd Handle, verb *uint16, file *uint16, args *uint16, cwd *uint16, showCmd int32) (err error) { + r1, _, e1 := syscall.Syscall6(procShellExecuteW.Addr(), 6, uintptr(hwnd), uintptr(unsafe.Pointer(verb)), uintptr(unsafe.Pointer(file)), uintptr(unsafe.Pointer(args)), uintptr(unsafe.Pointer(cwd)), uintptr(showCmd)) + if r1 <= 32 { + err = errnoErr(e1) + } + return +} + +func ExitWindowsEx(flags uint32, reason uint32) (err error) { + r1, _, e1 := syscall.Syscall(procExitWindowsEx.Addr(), 2, uintptr(flags), uintptr(reason), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) { - r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func MessageBox(hwnd Handle, text *uint16, caption *uint16, boxtype uint32) (ret int32, err error) { + r0, _, e1 := syscall.Syscall6(procMessageBoxW.Addr(), 4, uintptr(hwnd), uintptr(unsafe.Pointer(text)), uintptr(unsafe.Pointer(caption)), uintptr(boxtype), 0, 0) + ret = int32(r0) + if ret == 0 { + err = errnoErr(e1) } return } -func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { - r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetLengthSid(sid *SID) (len uint32) { - r0, _, _ := syscall.Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - len = uint32(r0) - return -} - -func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { - r1, _, e1 := syscall.Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) { - r1, _, e1 := syscall.Syscall12(procAllocateAndInitializeSid.Addr(), 11, uintptr(unsafe.Pointer(identAuth)), uintptr(subAuth), uintptr(subAuth0), uintptr(subAuth1), uintptr(subAuth2), uintptr(subAuth3), uintptr(subAuth4), uintptr(subAuth5), uintptr(subAuth6), uintptr(subAuth7), uintptr(unsafe.Pointer(sid)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procCreateWellKnownSid.Addr(), 4, uintptr(sidType), uintptr(unsafe.Pointer(domainSid)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sizeSid)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func isWellKnownSid(sid *SID, sidType WELL_KNOWN_SID_TYPE) (isWellKnown bool) { - r0, _, _ := syscall.Syscall(procIsWellKnownSid.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(sidType), 0) - isWellKnown = r0 != 0 - return -} - -func FreeSid(sid *SID) (err error) { - r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - if r1 != 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) { - r0, _, _ := syscall.Syscall(procEqualSid.Addr(), 2, uintptr(unsafe.Pointer(sid1)), uintptr(unsafe.Pointer(sid2)), 0) - isEqual = r0 != 0 - return -} - -func getSidIdentifierAuthority(sid *SID) (authority *SidIdentifierAuthority) { - r0, _, _ := syscall.Syscall(procGetSidIdentifierAuthority.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - authority = (*SidIdentifierAuthority)(unsafe.Pointer(r0)) - return -} - -func getSidSubAuthorityCount(sid *SID) (count *uint8) { - r0, _, _ := syscall.Syscall(procGetSidSubAuthorityCount.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - count = (*uint8)(unsafe.Pointer(r0)) - return -} - -func getSidSubAuthority(sid *SID, index uint32) (subAuthority *uint32) { - r0, _, _ := syscall.Syscall(procGetSidSubAuthority.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(index), 0) - subAuthority = (*uint32)(unsafe.Pointer(r0)) - return -} - -func isValidSid(sid *SID) (isValid bool) { - r0, _, _ := syscall.Syscall(procIsValidSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - isValid = r0 != 0 - return -} - -func checkTokenMembership(tokenHandle Token, sidToCheck *SID, isMember *int32) (err error) { - r1, _, e1 := syscall.Syscall(procCheckTokenMembership.Addr(), 3, uintptr(tokenHandle), uintptr(unsafe.Pointer(sidToCheck)), uintptr(unsafe.Pointer(isMember))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func OpenProcessToken(process Handle, access uint32, token *Token) (err error) { - r1, _, e1 := syscall.Syscall(procOpenProcessToken.Addr(), 3, uintptr(process), uintptr(access), uintptr(unsafe.Pointer(token))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func OpenThreadToken(thread Handle, access uint32, openAsSelf bool, token *Token) (err error) { +func CreateEnvironmentBlock(block **uint16, token Token, inheritExisting bool) (err error) { var _p0 uint32 - if openAsSelf { + if inheritExisting { _p0 = 1 - } else { - _p0 = 0 } - r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func ImpersonateSelf(impersonationlevel uint32) (err error) { - r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) +func DestroyEnvironmentBlock(block *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func RevertToSelf() (err error) { - r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetThreadToken(thread *Handle, token Token) (err error) { - r1, _, e1 := syscall.Syscall(procSetThreadToken.Addr(), 2, uintptr(unsafe.Pointer(thread)), uintptr(token), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) { - r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func AdjustTokenPrivileges(token Token, disableAllPrivileges bool, newstate *Tokenprivileges, buflen uint32, prevstate *Tokenprivileges, returnlen *uint32) (err error) { - var _p0 uint32 - if disableAllPrivileges { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func AdjustTokenGroups(token Token, resetToDefault bool, newstate *Tokengroups, buflen uint32, prevstate *Tokengroups, returnlen *uint32) (err error) { - var _p0 uint32 - if resetToDefault { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall6(procAdjustTokenGroups.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetTokenInformation.Addr(), 5, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetTokenInformation(token Token, infoClass uint32, info *byte, infoLen uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(token), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes *SecurityAttributes, impersonationLevel uint32, tokenType uint32, newToken *Token) (err error) { - r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(existingToken), uintptr(desiredAccess), uintptr(unsafe.Pointer(tokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(newToken))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -3650,62 +2790,256 @@ func DuplicateTokenEx(existingToken Token, desiredAccess uint32, tokenAttributes func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetUserProfileDirectoryW.Addr(), 3, uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func FreeAddrInfoW(addrinfo *AddrinfoW) { + syscall.Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0) + return +} + +func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { + r0, _, _ := syscall.Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0) + if r0 != 0 { + sockerr = syscall.Errno(r0) } return } -func getWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSACleanup() (err error) { + r1, _, e1 := syscall.Syscall(procWSACleanup.Addr(), 0, 0, 0, 0) + if r1 == socket_error { + err = errnoErr(e1) } return } -func getSystemWindowsDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetSystemWindowsDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { + r0, _, e1 := syscall.Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) + n = int32(r0) + if n == -1 { + err = errnoErr(e1) } return } -func WTSQueryUserToken(session uint32, token *Token) (err error) { - r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } +func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { + r1, _, e1 := syscall.Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := syscall.Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { + r0, _, _ := syscall.Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) + if r0 != 0 { + sockerr = syscall.Errno(r0) + } + return +} + +func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func Closesocket(s Handle) (err error) { + r1, _, e1 := syscall.Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := syscall.Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func GetHostByName(name string) (h *Hostent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return + } + return _GetHostByName(_p0) +} + +func _GetHostByName(name *byte) (h *Hostent, err error) { + r0, _, e1 := syscall.Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + h = (*Hostent)(unsafe.Pointer(r0)) + if h == nil { + err = errnoErr(e1) + } + return +} + +func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func GetProtoByName(name string) (p *Protoent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return + } + return _GetProtoByName(_p0) +} + +func _GetProtoByName(name *byte) (p *Protoent, err error) { + r0, _, e1 := syscall.Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + p = (*Protoent)(unsafe.Pointer(r0)) + if p == nil { + err = errnoErr(e1) + } + return +} + +func GetServByName(name string, proto string) (s *Servent, err error) { + var _p0 *byte + _p0, err = syscall.BytePtrFromString(name) + if err != nil { + return + } + var _p1 *byte + _p1, err = syscall.BytePtrFromString(proto) + if err != nil { + return + } + return _GetServByName(_p0, _p1) +} + +func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { + r0, _, e1 := syscall.Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0) + s = (*Servent)(unsafe.Pointer(r0)) + if s == nil { + err = errnoErr(e1) + } + return +} + +func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { + r1, _, e1 := syscall.Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func listen(s Handle, backlog int32) (err error) { + r1, _, e1 := syscall.Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func Ntohs(netshort uint16) (u uint16) { + r0, _, _ := syscall.Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0) + u = uint16(r0) + return +} + +func recvfrom(s Handle, buf []byte, flags int32, from *RawSockaddrAny, fromlen *int32) (n int32, err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r0, _, e1 := syscall.Syscall6(procrecvfrom.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen))) + n = int32(r0) + if n == -1 { + err = errnoErr(e1) + } + return +} + +func sendto(s Handle, buf []byte, flags int32, to unsafe.Pointer, tolen int32) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := syscall.Syscall6(procsendto.Addr(), 6, uintptr(s), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(flags), uintptr(to), uintptr(tolen)) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { + r1, _, e1 := syscall.Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func shutdown(s Handle, how int32) (err error) { + r1, _, e1 := syscall.Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { + r0, _, e1 := syscall.Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol)) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) } return } @@ -3713,11 +3047,7 @@ func WTSQueryUserToken(session uint32, token *Token) (err error) { func WTSEnumerateSessions(handle Handle, reserved uint32, version uint32, sessions **WTS_SESSION_INFO, count *uint32) (err error) { r1, _, e1 := syscall.Syscall6(procWTSEnumerateSessionsW.Addr(), 5, uintptr(handle), uintptr(reserved), uintptr(version), uintptr(unsafe.Pointer(sessions)), uintptr(unsafe.Pointer(count)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } @@ -3727,357 +3057,10 @@ func WTSFreeMemory(ptr uintptr) { return } -func getSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) - if r0 != 0 { - ret = syscall.Errno(r0) - } - return -} - -func SetSecurityInfo(handle Handle, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) { - syscall.Syscall9(procSetSecurityInfo.Addr(), 7, uintptr(handle), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) - return -} - -func getNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - var _p0 *uint16 - _p0, ret = syscall.UTF16PtrFromString(objectName) - if ret != nil { - return - } - return _getNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl, sd) -} - -func _getNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner **SID, group **SID, dacl **ACL, sacl **ACL, sd **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procGetNamedSecurityInfoW.Addr(), 8, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(sd)), 0) - if r0 != 0 { - ret = syscall.Errno(r0) - } - return -} - -func SetNamedSecurityInfo(objectName string, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { - var _p0 *uint16 - _p0, ret = syscall.UTF16PtrFromString(objectName) - if ret != nil { - return - } - return _SetNamedSecurityInfo(_p0, objectType, securityInformation, owner, group, dacl, sacl) -} - -func _SetNamedSecurityInfo(objectName *uint16, objectType SE_OBJECT_TYPE, securityInformation SECURITY_INFORMATION, owner *SID, group *SID, dacl *ACL, sacl *ACL) (ret error) { - r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfoW.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) - } - return -} - -func buildSecurityDescriptor(owner *TRUSTEE, group *TRUSTEE, countAccessEntries uint32, accessEntries *EXPLICIT_ACCESS, countAuditEntries uint32, auditEntries *EXPLICIT_ACCESS, oldSecurityDescriptor *SECURITY_DESCRIPTOR, sizeNewSecurityDescriptor *uint32, newSecurityDescriptor **SECURITY_DESCRIPTOR) (ret error) { - r0, _, _ := syscall.Syscall9(procBuildSecurityDescriptorW.Addr(), 9, uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(countAccessEntries), uintptr(unsafe.Pointer(accessEntries)), uintptr(countAuditEntries), uintptr(unsafe.Pointer(auditEntries)), uintptr(unsafe.Pointer(oldSecurityDescriptor)), uintptr(unsafe.Pointer(sizeNewSecurityDescriptor)), uintptr(unsafe.Pointer(newSecurityDescriptor))) - if r0 != 0 { - ret = syscall.Errno(r0) - } - return -} - -func initializeSecurityDescriptor(absoluteSD *SECURITY_DESCRIPTOR, revision uint32) (err error) { - r1, _, e1 := syscall.Syscall(procInitializeSecurityDescriptor.Addr(), 2, uintptr(unsafe.Pointer(absoluteSD)), uintptr(revision), 0) +func WTSQueryUserToken(session uint32, token *Token) (err error) { + r1, _, e1 := syscall.Syscall(procWTSQueryUserToken.Addr(), 2, uintptr(session), uintptr(unsafe.Pointer(token)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, control *SECURITY_DESCRIPTOR_CONTROL, revision *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(control)), uintptr(unsafe.Pointer(revision))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent *bool, dacl **ACL, daclDefaulted *bool) (err error) { - var _p0 uint32 - if *daclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if *daclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) - *daclPresent = _p0 != 0 - *daclDefaulted = _p1 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent *bool, sacl **ACL, saclDefaulted *bool) (err error) { - var _p0 uint32 - if *saclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if *saclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(&_p0)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(&_p1)), 0, 0) - *saclPresent = _p0 != 0 - *saclDefaulted = _p1 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner **SID, ownerDefaulted *bool) (err error) { - var _p0 uint32 - if *ownerDefaulted { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(&_p0))) - *ownerDefaulted = _p0 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group **SID, groupDefaulted *bool) (err error) { - var _p0 uint32 - if *groupDefaulted { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procGetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(&_p0))) - *groupDefaulted = _p0 != 0 - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func getSecurityDescriptorLength(sd *SECURITY_DESCRIPTOR) (len uint32) { - r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) - len = uint32(r0) - return -} - -func getSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) (ret error) { - r0, _, _ := syscall.Syscall(procGetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) - if r0 != 0 { - ret = syscall.Errno(r0) - } - return -} - -func isValidSecurityDescriptor(sd *SECURITY_DESCRIPTOR) (isValid bool) { - r0, _, _ := syscall.Syscall(procIsValidSecurityDescriptor.Addr(), 1, uintptr(unsafe.Pointer(sd)), 0, 0) - isValid = r0 != 0 - return -} - -func setSecurityDescriptorControl(sd *SECURITY_DESCRIPTOR, controlBitsOfInterest SECURITY_DESCRIPTOR_CONTROL, controlBitsToSet SECURITY_DESCRIPTOR_CONTROL) (err error) { - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorControl.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(controlBitsOfInterest), uintptr(controlBitsToSet)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setSecurityDescriptorDacl(sd *SECURITY_DESCRIPTOR, daclPresent bool, dacl *ACL, daclDefaulted bool) (err error) { - var _p0 uint32 - if daclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if daclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(dacl)), uintptr(_p1), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setSecurityDescriptorSacl(sd *SECURITY_DESCRIPTOR, saclPresent bool, sacl *ACL, saclDefaulted bool) (err error) { - var _p0 uint32 - if saclPresent { - _p0 = 1 - } else { - _p0 = 0 - } - var _p1 uint32 - if saclDefaulted { - _p1 = 1 - } else { - _p1 = 0 - } - r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(unsafe.Pointer(sd)), uintptr(_p0), uintptr(unsafe.Pointer(sacl)), uintptr(_p1), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setSecurityDescriptorOwner(sd *SECURITY_DESCRIPTOR, owner *SID, ownerDefaulted bool) (err error) { - var _p0 uint32 - if ownerDefaulted { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorOwner.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(owner)), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setSecurityDescriptorGroup(sd *SECURITY_DESCRIPTOR, group *SID, groupDefaulted bool) (err error) { - var _p0 uint32 - if groupDefaulted { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procSetSecurityDescriptorGroup.Addr(), 3, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(group)), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setSecurityDescriptorRMControl(sd *SECURITY_DESCRIPTOR, rmControl *uint8) { - syscall.Syscall(procSetSecurityDescriptorRMControl.Addr(), 2, uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(rmControl)), 0) - return -} - -func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { - var _p0 *uint16 - _p0, err = syscall.UTF16PtrFromString(str) - if err != nil { - return - } - return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size) -} - -func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd **SECURITY_DESCRIPTOR, size *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func convertSecurityDescriptorToStringSecurityDescriptor(sd *SECURITY_DESCRIPTOR, revision uint32, securityInformation SECURITY_INFORMATION, str **uint16, strLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(securityInformation), uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(strLen)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func makeAbsoluteSD(selfRelativeSD *SECURITY_DESCRIPTOR, absoluteSD *SECURITY_DESCRIPTOR, absoluteSDSize *uint32, dacl *ACL, daclSize *uint32, sacl *ACL, saclSize *uint32, owner *SID, ownerSize *uint32, group *SID, groupSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(absoluteSDSize)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclSize)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(saclSize)), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(ownerSize)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(groupSize)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(unsafe.Pointer(absoluteSD)), uintptr(unsafe.Pointer(selfRelativeSD)), uintptr(unsafe.Pointer(selfRelativeSDSize))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) { - r0, _, _ := syscall.Syscall6(procSetEntriesInAclW.Addr(), 4, uintptr(countExplicitEntries), uintptr(unsafe.Pointer(explicitEntries)), uintptr(unsafe.Pointer(oldACL)), uintptr(unsafe.Pointer(newACL)), 0, 0) - if r0 != 0 { - ret = syscall.Errno(r0) + err = errnoErr(e1) } return } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 4be3a2b6800..906a19e02bf 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -40,7 +40,7 @@ golang.org/x/mod/sumdb/dirhash golang.org/x/mod/sumdb/note golang.org/x/mod/sumdb/tlog golang.org/x/mod/zip -# golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d +# golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 ## explicit golang.org/x/sys/internal/unsafeheader golang.org/x/sys/unix @@ -72,6 +72,7 @@ golang.org/x/tools/go/analysis/passes/shift golang.org/x/tools/go/analysis/passes/stdmethods golang.org/x/tools/go/analysis/passes/stringintconv golang.org/x/tools/go/analysis/passes/structtag +golang.org/x/tools/go/analysis/passes/testinggoroutine golang.org/x/tools/go/analysis/passes/tests golang.org/x/tools/go/analysis/passes/unmarshal golang.org/x/tools/go/analysis/passes/unreachable diff --git a/src/go.mod b/src/go.mod index 3bdfbef052c..a56c61606fc 100644 --- a/src/go.mod +++ b/src/go.mod @@ -5,6 +5,6 @@ go 1.16 require ( golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a golang.org/x/net v0.0.0-20200927032502-5d4f70055728 - golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect + golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 // indirect golang.org/x/text v0.3.4-0.20200826142016-a8b467125457 // indirect ) diff --git a/src/go.sum b/src/go.sum index 6a038874099..391e47740f6 100644 --- a/src/go.sum +++ b/src/go.sum @@ -8,8 +8,8 @@ golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73IhgqJ71c9s80WsQnh0Es= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 h1:a/mKvvZr9Jcc8oKfcmgzyp7OwF73JPWsQLvH1z2Kxck= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.4-0.20200826142016-a8b467125457 h1:K2Vq+FTHFbV5auJiAahir8LO9HUqufuVbQYSNzZopos= golang.org/x/text v0.3.4-0.20200826142016-a8b467125457/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/src/internal/syscall/windows/registry/zsyscall_windows.go b/src/internal/syscall/windows/registry/zsyscall_windows.go index c3f3a8a2154..cab13193749 100644 --- a/src/internal/syscall/windows/registry/zsyscall_windows.go +++ b/src/internal/syscall/windows/registry/zsyscall_windows.go @@ -18,6 +18,7 @@ const ( var ( errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL ) // errnoErr returns common boxed Errno values, to prevent @@ -25,7 +26,7 @@ var ( func errnoErr(e syscall.Errno) error { switch e { case 0: - return nil + return errERROR_EINVAL case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } @@ -41,10 +42,10 @@ var ( procRegCreateKeyExW = modadvapi32.NewProc("RegCreateKeyExW") procRegDeleteKeyW = modadvapi32.NewProc("RegDeleteKeyW") - procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW") - procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW") procRegDeleteValueW = modadvapi32.NewProc("RegDeleteValueW") + procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW") procRegLoadMUIStringW = modadvapi32.NewProc("RegLoadMUIStringW") + procRegSetValueExW = modadvapi32.NewProc("RegSetValueExW") procExpandEnvironmentStringsW = modkernel32.NewProc("ExpandEnvironmentStringsW") ) @@ -64,8 +65,8 @@ func regDeleteKey(key syscall.Handle, subkey *uint16) (regerrno error) { return } -func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) { - r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize)) +func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) { + r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -80,16 +81,16 @@ func regEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint3 return } -func regDeleteValue(key syscall.Handle, name *uint16) (regerrno error) { - r0, _, _ := syscall.Syscall(procRegDeleteValueW.Addr(), 2, uintptr(key), uintptr(unsafe.Pointer(name)), 0) +func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) { + r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0) if r0 != 0 { regerrno = syscall.Errno(r0) } return } -func regLoadMUIString(key syscall.Handle, name *uint16, buf *uint16, buflen uint32, buflenCopied *uint32, flags uint32, dir *uint16) (regerrno error) { - r0, _, _ := syscall.Syscall9(procRegLoadMUIStringW.Addr(), 7, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(unsafe.Pointer(buflenCopied)), uintptr(flags), uintptr(unsafe.Pointer(dir)), 0, 0) +func regSetValueEx(key syscall.Handle, valueName *uint16, reserved uint32, vtype uint32, buf *byte, bufsize uint32) (regerrno error) { + r0, _, _ := syscall.Syscall6(procRegSetValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(valueName)), uintptr(reserved), uintptr(vtype), uintptr(unsafe.Pointer(buf)), uintptr(bufsize)) if r0 != 0 { regerrno = syscall.Errno(r0) } @@ -100,11 +101,7 @@ func expandEnvironmentStrings(src *uint16, dst *uint16, size uint32) (n uint32, r0, _, e1 := syscall.Syscall(procExpandEnvironmentStringsW.Addr(), 3, uintptr(unsafe.Pointer(src)), uintptr(unsafe.Pointer(dst)), uintptr(size)) n = uint32(r0) if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } diff --git a/src/internal/syscall/windows/zsyscall_windows.go b/src/internal/syscall/windows/zsyscall_windows.go index 1eb8c2dfd21..170b239486d 100644 --- a/src/internal/syscall/windows/zsyscall_windows.go +++ b/src/internal/syscall/windows/zsyscall_windows.go @@ -18,6 +18,7 @@ const ( var ( errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL ) // errnoErr returns common boxed Errno values, to prevent @@ -25,7 +26,7 @@ var ( func errnoErr(e syscall.Errno) error { switch e { case 0: - return nil + return errERROR_EINVAL case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } @@ -36,44 +37,109 @@ func errnoErr(e syscall.Errno) error { } var ( + modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) modiphlpapi = syscall.NewLazyDLL(sysdll.Add("iphlpapi.dll")) modkernel32 = syscall.NewLazyDLL(sysdll.Add("kernel32.dll")) - modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll")) modnetapi32 = syscall.NewLazyDLL(sysdll.Add("netapi32.dll")) - moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll")) - modadvapi32 = syscall.NewLazyDLL(sysdll.Add("advapi32.dll")) modpsapi = syscall.NewLazyDLL(sysdll.Add("psapi.dll")) + moduserenv = syscall.NewLazyDLL(sysdll.Add("userenv.dll")) + modws2_32 = syscall.NewLazyDLL(sysdll.Add("ws2_32.dll")) - procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") - procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") - procMoveFileExW = modkernel32.NewProc("MoveFileExW") - procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") - procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") - procWSASocketW = modws2_32.NewProc("WSASocketW") - procLockFileEx = modkernel32.NewProc("LockFileEx") - procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") - procGetACP = modkernel32.NewProc("GetACP") - procGetConsoleCP = modkernel32.NewProc("GetConsoleCP") - procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") - procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") - procNetShareAdd = modnetapi32.NewProc("NetShareAdd") - procNetShareDel = modnetapi32.NewProc("NetShareDel") - procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW") - procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") - procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") - procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") - procRevertToSelf = modadvapi32.NewProc("RevertToSelf") - procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") - procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges") procDuplicateTokenEx = modadvapi32.NewProc("DuplicateTokenEx") + procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf") + procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW") + procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken") + procRevertToSelf = modadvapi32.NewProc("RevertToSelf") procSetTokenInformation = modadvapi32.NewProc("SetTokenInformation") - procGetProfilesDirectoryW = moduserenv.NewProc("GetProfilesDirectoryW") + procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") + procGetACP = modkernel32.NewProc("GetACP") + procGetComputerNameExW = modkernel32.NewProc("GetComputerNameExW") + procGetConsoleCP = modkernel32.NewProc("GetConsoleCP") + procGetCurrentThread = modkernel32.NewProc("GetCurrentThread") + procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procGetFinalPathNameByHandleW = modkernel32.NewProc("GetFinalPathNameByHandleW") + procGetModuleFileNameW = modkernel32.NewProc("GetModuleFileNameW") + procLockFileEx = modkernel32.NewProc("LockFileEx") + procMoveFileExW = modkernel32.NewProc("MoveFileExW") + procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") + procSetFileInformationByHandle = modkernel32.NewProc("SetFileInformationByHandle") + procUnlockFileEx = modkernel32.NewProc("UnlockFileEx") + procNetShareAdd = modnetapi32.NewProc("NetShareAdd") + procNetShareDel = modnetapi32.NewProc("NetShareDel") procNetUserGetLocalGroups = modnetapi32.NewProc("NetUserGetLocalGroups") procGetProcessMemoryInfo = modpsapi.NewProc("GetProcessMemoryInfo") - procGetFileInformationByHandleEx = modkernel32.NewProc("GetFileInformationByHandleEx") + procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") + procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") + procGetProfilesDirectoryW = moduserenv.NewProc("GetProfilesDirectoryW") + procWSASocketW = modws2_32.NewProc("WSASocketW") ) +func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) { + var _p0 uint32 + if disableAllPrivileges { + _p0 = 1 + } + r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) + ret = uint32(r0) + if true { + err = errnoErr(e1) + } + return +} + +func DuplicateTokenEx(hExistingToken syscall.Token, dwDesiredAccess uint32, lpTokenAttributes *syscall.SecurityAttributes, impersonationLevel uint32, tokenType TokenType, phNewToken *syscall.Token) (err error) { + r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(hExistingToken), uintptr(dwDesiredAccess), uintptr(unsafe.Pointer(lpTokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(phNewToken))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ImpersonateSelf(impersonationlevel uint32) (err error) { + r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) { + r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) { + var _p0 uint32 + if openasself { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(h), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func RevertToSelf() (err error) { + r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32, tokenInformation uintptr, tokenInformationLength uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(tokenHandle), uintptr(tokenInformationClass), uintptr(tokenInformation), uintptr(tokenInformationLength), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { r0, _, _ := syscall.Syscall6(procGetAdaptersAddresses.Addr(), 5, uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer)), 0) if r0 != 0 { @@ -82,114 +148,23 @@ func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapter return } -func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { - r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(fn)), uintptr(len)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) { - r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protinfo)), uintptr(group), uintptr(flags)) - handle = syscall.Handle(r0) - if handle == syscall.InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) { - r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - func GetACP() (acp uint32) { r0, _, _ := syscall.Syscall(procGetACP.Addr(), 0, 0, 0, 0) acp = uint32(r0) return } -func GetConsoleCP() (ccp uint32) { - r0, _, _ := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0) - ccp = uint32(r0) +func GetComputerNameEx(nameformat uint32, buf *uint16, n *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetComputerNameExW.Addr(), 3, uintptr(nameformat), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n))) + if r1 == 0 { + err = errnoErr(e1) + } return } -func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) { - r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) - nwrite = int32(r0) - if nwrite == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } +func GetConsoleCP() (ccp uint32) { + r0, _, _ := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0) + ccp = uint32(r0) return } @@ -197,11 +172,74 @@ func GetCurrentThread() (pseudoHandle syscall.Handle, err error) { r0, _, e1 := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0) pseudoHandle = syscall.Handle(r0) if pseudoHandle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) + } + return +} + +func GetFileInformationByHandleEx(handle syscall.Handle, class uint32, info *byte, bufsize uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(info)), uintptr(bufsize), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) { + r0, _, e1 := syscall.Syscall(procGetModuleFileNameW.Addr(), 3, uintptr(module), uintptr(unsafe.Pointer(fn)), uintptr(len)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func LockFileEx(file syscall.Handle, flags uint32, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procLockFileEx.Addr(), 6, uintptr(file), uintptr(flags), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) { + r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) { + r0, _, e1 := syscall.Syscall6(procMultiByteToWideChar.Addr(), 6, uintptr(codePage), uintptr(dwFlags), uintptr(unsafe.Pointer(str)), uintptr(nstr), uintptr(unsafe.Pointer(wchar)), uintptr(nwchar)) + nwrite = int32(r0) + if nwrite == 0 { + err = errnoErr(e1) + } + return +} + +func SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procSetFileInformationByHandle.Addr(), 4, uintptr(handle), uintptr(fileInformationClass), uintptr(buf), uintptr(bufsize), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func UnlockFileEx(file syscall.Handle, reserved uint32, bytesLow uint32, bytesHigh uint32, overlapped *syscall.Overlapped) (err error) { + r1, _, e1 := syscall.Syscall6(procUnlockFileEx.Addr(), 5, uintptr(file), uintptr(reserved), uintptr(bytesLow), uintptr(bytesHigh), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) } return } @@ -222,158 +260,6 @@ func NetShareDel(serverName *uint16, netName *uint16, reserved uint32) (neterr e return } -func GetFinalPathNameByHandle(file syscall.Handle, filePath *uint16, filePathSize uint32, flags uint32) (n uint32, err error) { - r0, _, e1 := syscall.Syscall6(procGetFinalPathNameByHandleW.Addr(), 4, uintptr(file), uintptr(unsafe.Pointer(filePath)), uintptr(filePathSize), uintptr(flags), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) { - var _p0 uint32 - if inheritExisting { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DestroyEnvironmentBlock(block *uint16) (err error) { - r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func ImpersonateSelf(impersonationlevel uint32) (err error) { - r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(impersonationlevel), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func RevertToSelf() (err error) { - r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func OpenThreadToken(h syscall.Handle, access uint32, openasself bool, token *syscall.Token) (err error) { - var _p0 uint32 - if openasself { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(h), uintptr(access), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func LookupPrivilegeValue(systemname *uint16, name *uint16, luid *LUID) (err error) { - r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemname)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func adjustTokenPrivileges(token syscall.Token, disableAllPrivileges bool, newstate *TOKEN_PRIVILEGES, buflen uint32, prevstate *TOKEN_PRIVILEGES, returnlen *uint32) (ret uint32, err error) { - var _p0 uint32 - if disableAllPrivileges { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(newstate)), uintptr(buflen), uintptr(unsafe.Pointer(prevstate)), uintptr(unsafe.Pointer(returnlen))) - ret = uint32(r0) - if true { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func DuplicateTokenEx(hExistingToken syscall.Token, dwDesiredAccess uint32, lpTokenAttributes *syscall.SecurityAttributes, impersonationLevel uint32, tokenType TokenType, phNewToken *syscall.Token) (err error) { - r1, _, e1 := syscall.Syscall6(procDuplicateTokenEx.Addr(), 6, uintptr(hExistingToken), uintptr(dwDesiredAccess), uintptr(unsafe.Pointer(lpTokenAttributes)), uintptr(impersonationLevel), uintptr(tokenType), uintptr(unsafe.Pointer(phNewToken))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func SetTokenInformation(tokenHandle syscall.Token, tokenInformationClass uint32, tokenInformation uintptr, tokenInformationLength uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procSetTokenInformation.Addr(), 4, uintptr(tokenHandle), uintptr(tokenInformationClass), uintptr(tokenInformation), uintptr(tokenInformationLength), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - -func GetProfilesDirectory(dir *uint16, dirLen *uint32) (err error) { - r1, _, e1 := syscall.Syscall(procGetProfilesDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } - } - return -} - func NetUserGetLocalGroups(serverName *uint16, userName *uint16, level uint32, flags uint32, buf **byte, prefMaxLen uint32, entriesRead *uint32, totalEntries *uint32) (neterr error) { r0, _, _ := syscall.Syscall9(procNetUserGetLocalGroups.Addr(), 8, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(flags), uintptr(unsafe.Pointer(buf)), uintptr(prefMaxLen), uintptr(unsafe.Pointer(entriesRead)), uintptr(unsafe.Pointer(totalEntries)), 0) if r0 != 0 { @@ -385,23 +271,44 @@ func NetUserGetLocalGroups(serverName *uint16, userName *uint16, level uint32, f func GetProcessMemoryInfo(handle syscall.Handle, memCounters *PROCESS_MEMORY_COUNTERS, cb uint32) (err error) { r1, _, e1 := syscall.Syscall(procGetProcessMemoryInfo.Addr(), 3, uintptr(handle), uintptr(unsafe.Pointer(memCounters)), uintptr(cb)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) } return } -func GetFileInformationByHandleEx(handle syscall.Handle, class uint32, info *byte, bufsize uint32) (err error) { - r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(class), uintptr(unsafe.Pointer(info)), uintptr(bufsize), 0, 0) +func CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) { + var _p0 uint32 + if inheritExisting { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = syscall.EINVAL - } + err = errnoErr(e1) + } + return +} + +func DestroyEnvironmentBlock(block *uint16) (err error) { + r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(unsafe.Pointer(block)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetProfilesDirectory(dir *uint16, dirLen *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procGetProfilesDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func WSASocket(af int32, typ int32, protocol int32, protinfo *syscall.WSAProtocolInfo, group uint32, flags uint32) (handle syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall6(procWSASocketW.Addr(), 6, uintptr(af), uintptr(typ), uintptr(protocol), uintptr(unsafe.Pointer(protinfo)), uintptr(group), uintptr(flags)) + handle = syscall.Handle(r0) + if handle == syscall.InvalidHandle { + err = errnoErr(e1) } return } diff --git a/src/syscall/zsyscall_windows.go b/src/syscall/zsyscall_windows.go index b4222f0528b..5d03ca9de9b 100644 --- a/src/syscall/zsyscall_windows.go +++ b/src/syscall/zsyscall_windows.go @@ -17,6 +17,7 @@ const ( var ( errERROR_IO_PENDING error = Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = EINVAL ) // errnoErr returns common boxed Errno values, to prevent @@ -24,7 +25,7 @@ var ( func errnoErr(e Errno) error { switch e { case 0: - return nil + return errERROR_EINVAL case errnoERROR_IO_PENDING: return errERROR_IO_PENDING } @@ -35,586 +36,185 @@ func errnoErr(e Errno) error { } var ( - modkernel32 = NewLazyDLL(sysdll.Add("kernel32.dll")) modadvapi32 = NewLazyDLL(sysdll.Add("advapi32.dll")) - modshell32 = NewLazyDLL(sysdll.Add("shell32.dll")) - modmswsock = NewLazyDLL(sysdll.Add("mswsock.dll")) modcrypt32 = NewLazyDLL(sysdll.Add("crypt32.dll")) - modws2_32 = NewLazyDLL(sysdll.Add("ws2_32.dll")) moddnsapi = NewLazyDLL(sysdll.Add("dnsapi.dll")) modiphlpapi = NewLazyDLL(sysdll.Add("iphlpapi.dll")) - modsecur32 = NewLazyDLL(sysdll.Add("secur32.dll")) + modkernel32 = NewLazyDLL(sysdll.Add("kernel32.dll")) + modmswsock = NewLazyDLL(sysdll.Add("mswsock.dll")) modnetapi32 = NewLazyDLL(sysdll.Add("netapi32.dll")) + modsecur32 = NewLazyDLL(sysdll.Add("secur32.dll")) + modshell32 = NewLazyDLL(sysdll.Add("shell32.dll")) moduserenv = NewLazyDLL(sysdll.Add("userenv.dll")) + modws2_32 = NewLazyDLL(sysdll.Add("ws2_32.dll")) - procGetLastError = modkernel32.NewProc("GetLastError") - procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") - procFreeLibrary = modkernel32.NewProc("FreeLibrary") - procGetProcAddress = modkernel32.NewProc("GetProcAddress") - procGetVersion = modkernel32.NewProc("GetVersion") - procFormatMessageW = modkernel32.NewProc("FormatMessageW") - procExitProcess = modkernel32.NewProc("ExitProcess") - procCreateFileW = modkernel32.NewProc("CreateFileW") - procReadFile = modkernel32.NewProc("ReadFile") - procWriteFile = modkernel32.NewProc("WriteFile") - procSetFilePointer = modkernel32.NewProc("SetFilePointer") - procCloseHandle = modkernel32.NewProc("CloseHandle") - procGetStdHandle = modkernel32.NewProc("GetStdHandle") - procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") - procFindNextFileW = modkernel32.NewProc("FindNextFileW") - procFindClose = modkernel32.NewProc("FindClose") - procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") - procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") - procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") - procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") - procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") - procDeleteFileW = modkernel32.NewProc("DeleteFileW") - procMoveFileW = modkernel32.NewProc("MoveFileW") - procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") - procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") - procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") - procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") - procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") - procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") - procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") - procCancelIo = modkernel32.NewProc("CancelIo") - procCancelIoEx = modkernel32.NewProc("CancelIoEx") - procCreateProcessW = modkernel32.NewProc("CreateProcessW") - procCreateProcessAsUserW = modadvapi32.NewProc("CreateProcessAsUserW") - procOpenProcess = modkernel32.NewProc("OpenProcess") - procTerminateProcess = modkernel32.NewProc("TerminateProcess") - procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") - procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") - procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess") - procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") - procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") - procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") - procGetTempPathW = modkernel32.NewProc("GetTempPathW") - procCreatePipe = modkernel32.NewProc("CreatePipe") - procGetFileType = modkernel32.NewProc("GetFileType") - procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") - procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") - procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") - procSystemFunction036 = modadvapi32.NewProc("SystemFunction036") - procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") - procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") - procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") - procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") - procSetFileTime = modkernel32.NewProc("SetFileTime") - procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") - procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") - procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") - procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") - procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") - procLocalFree = modkernel32.NewProc("LocalFree") - procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") - procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") - procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") - procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") - procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") - procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") - procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") - procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") - procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") - procVirtualLock = modkernel32.NewProc("VirtualLock") - procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") - procTransmitFile = modmswsock.NewProc("TransmitFile") - procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") - procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") - procCertOpenStore = modcrypt32.NewProc("CertOpenStore") - procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") - procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") - procCertCloseStore = modcrypt32.NewProc("CertCloseStore") - procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") - procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") - procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") - procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") - procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") - procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") - procRegCloseKey = modadvapi32.NewProc("RegCloseKey") - procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") - procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") - procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") - procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") - procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") - procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") - procReadConsoleW = modkernel32.NewProc("ReadConsoleW") - procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") - procProcess32FirstW = modkernel32.NewProc("Process32FirstW") - procProcess32NextW = modkernel32.NewProc("Process32NextW") - procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") - procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") - procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") - procWSAStartup = modws2_32.NewProc("WSAStartup") - procWSACleanup = modws2_32.NewProc("WSACleanup") - procWSAIoctl = modws2_32.NewProc("WSAIoctl") - procsocket = modws2_32.NewProc("socket") - procsetsockopt = modws2_32.NewProc("setsockopt") - procgetsockopt = modws2_32.NewProc("getsockopt") - procbind = modws2_32.NewProc("bind") - procconnect = modws2_32.NewProc("connect") - procgetsockname = modws2_32.NewProc("getsockname") - procgetpeername = modws2_32.NewProc("getpeername") - proclisten = modws2_32.NewProc("listen") - procshutdown = modws2_32.NewProc("shutdown") - procclosesocket = modws2_32.NewProc("closesocket") - procAcceptEx = modmswsock.NewProc("AcceptEx") - procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") - procWSARecv = modws2_32.NewProc("WSARecv") - procWSASend = modws2_32.NewProc("WSASend") - procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") - procWSASendTo = modws2_32.NewProc("WSASendTo") - procgethostbyname = modws2_32.NewProc("gethostbyname") - procgetservbyname = modws2_32.NewProc("getservbyname") - procntohs = modws2_32.NewProc("ntohs") - procgetprotobyname = modws2_32.NewProc("getprotobyname") - procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") - procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") - procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") - procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") - procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") - procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") - procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") - procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") - procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") - procTranslateNameW = modsecur32.NewProc("TranslateNameW") - procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") - procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") - procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") - procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") - procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") - procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW") procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW") - procGetLengthSid = modadvapi32.NewProc("GetLengthSid") procCopySid = modadvapi32.NewProc("CopySid") - procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") + procCreateProcessAsUserW = modadvapi32.NewProc("CreateProcessAsUserW") + procCryptAcquireContextW = modadvapi32.NewProc("CryptAcquireContextW") + procCryptGenRandom = modadvapi32.NewProc("CryptGenRandom") + procCryptReleaseContext = modadvapi32.NewProc("CryptReleaseContext") + procGetLengthSid = modadvapi32.NewProc("GetLengthSid") procGetTokenInformation = modadvapi32.NewProc("GetTokenInformation") - procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") + procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW") + procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW") + procOpenProcessToken = modadvapi32.NewProc("OpenProcessToken") + procRegCloseKey = modadvapi32.NewProc("RegCloseKey") + procRegEnumKeyExW = modadvapi32.NewProc("RegEnumKeyExW") + procRegOpenKeyExW = modadvapi32.NewProc("RegOpenKeyExW") + procRegQueryInfoKeyW = modadvapi32.NewProc("RegQueryInfoKeyW") + procRegQueryValueExW = modadvapi32.NewProc("RegQueryValueExW") + procSystemFunction036 = modadvapi32.NewProc("SystemFunction036") + procCertAddCertificateContextToStore = modcrypt32.NewProc("CertAddCertificateContextToStore") + procCertCloseStore = modcrypt32.NewProc("CertCloseStore") + procCertCreateCertificateContext = modcrypt32.NewProc("CertCreateCertificateContext") + procCertEnumCertificatesInStore = modcrypt32.NewProc("CertEnumCertificatesInStore") + procCertFreeCertificateChain = modcrypt32.NewProc("CertFreeCertificateChain") + procCertFreeCertificateContext = modcrypt32.NewProc("CertFreeCertificateContext") + procCertGetCertificateChain = modcrypt32.NewProc("CertGetCertificateChain") + procCertOpenStore = modcrypt32.NewProc("CertOpenStore") + procCertOpenSystemStoreW = modcrypt32.NewProc("CertOpenSystemStoreW") + procCertVerifyCertificateChainPolicy = modcrypt32.NewProc("CertVerifyCertificateChainPolicy") + procDnsNameCompare_W = moddnsapi.NewProc("DnsNameCompare_W") + procDnsQuery_W = moddnsapi.NewProc("DnsQuery_W") + procDnsRecordListFree = moddnsapi.NewProc("DnsRecordListFree") + procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") + procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") + procCancelIo = modkernel32.NewProc("CancelIo") + procCancelIoEx = modkernel32.NewProc("CancelIoEx") + procCloseHandle = modkernel32.NewProc("CloseHandle") + procCreateDirectoryW = modkernel32.NewProc("CreateDirectoryW") + procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") + procCreateFileW = modkernel32.NewProc("CreateFileW") + procCreateHardLinkW = modkernel32.NewProc("CreateHardLinkW") + procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort") + procCreatePipe = modkernel32.NewProc("CreatePipe") + procCreateProcessW = modkernel32.NewProc("CreateProcessW") + procCreateSymbolicLinkW = modkernel32.NewProc("CreateSymbolicLinkW") + procCreateToolhelp32Snapshot = modkernel32.NewProc("CreateToolhelp32Snapshot") + procDeleteFileW = modkernel32.NewProc("DeleteFileW") + procDeviceIoControl = modkernel32.NewProc("DeviceIoControl") + procDuplicateHandle = modkernel32.NewProc("DuplicateHandle") + procExitProcess = modkernel32.NewProc("ExitProcess") + procFindClose = modkernel32.NewProc("FindClose") + procFindFirstFileW = modkernel32.NewProc("FindFirstFileW") + procFindNextFileW = modkernel32.NewProc("FindNextFileW") + procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") + procFlushViewOfFile = modkernel32.NewProc("FlushViewOfFile") + procFormatMessageW = modkernel32.NewProc("FormatMessageW") + procFreeEnvironmentStringsW = modkernel32.NewProc("FreeEnvironmentStringsW") + procFreeLibrary = modkernel32.NewProc("FreeLibrary") + procGetCommandLineW = modkernel32.NewProc("GetCommandLineW") + procGetComputerNameW = modkernel32.NewProc("GetComputerNameW") + procGetConsoleMode = modkernel32.NewProc("GetConsoleMode") + procGetCurrentDirectoryW = modkernel32.NewProc("GetCurrentDirectoryW") + procGetCurrentProcess = modkernel32.NewProc("GetCurrentProcess") + procGetCurrentProcessId = modkernel32.NewProc("GetCurrentProcessId") + procGetEnvironmentStringsW = modkernel32.NewProc("GetEnvironmentStringsW") + procGetEnvironmentVariableW = modkernel32.NewProc("GetEnvironmentVariableW") + procGetExitCodeProcess = modkernel32.NewProc("GetExitCodeProcess") + procGetFileAttributesExW = modkernel32.NewProc("GetFileAttributesExW") + procGetFileAttributesW = modkernel32.NewProc("GetFileAttributesW") + procGetFileInformationByHandle = modkernel32.NewProc("GetFileInformationByHandle") + procGetFileType = modkernel32.NewProc("GetFileType") + procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") + procGetLastError = modkernel32.NewProc("GetLastError") + procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetProcAddress = modkernel32.NewProc("GetProcAddress") + procGetProcessTimes = modkernel32.NewProc("GetProcessTimes") + procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus") + procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") + procGetStartupInfoW = modkernel32.NewProc("GetStartupInfoW") + procGetStdHandle = modkernel32.NewProc("GetStdHandle") procGetSystemDirectoryW = modkernel32.NewProc("GetSystemDirectoryW") + procGetSystemTimeAsFileTime = modkernel32.NewProc("GetSystemTimeAsFileTime") + procGetTempPathW = modkernel32.NewProc("GetTempPathW") + procGetTimeZoneInformation = modkernel32.NewProc("GetTimeZoneInformation") + procGetVersion = modkernel32.NewProc("GetVersion") + procLoadLibraryW = modkernel32.NewProc("LoadLibraryW") + procLocalFree = modkernel32.NewProc("LocalFree") + procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") + procMoveFileW = modkernel32.NewProc("MoveFileW") + procOpenProcess = modkernel32.NewProc("OpenProcess") + procPostQueuedCompletionStatus = modkernel32.NewProc("PostQueuedCompletionStatus") + procProcess32FirstW = modkernel32.NewProc("Process32FirstW") + procProcess32NextW = modkernel32.NewProc("Process32NextW") + procReadConsoleW = modkernel32.NewProc("ReadConsoleW") + procReadDirectoryChangesW = modkernel32.NewProc("ReadDirectoryChangesW") + procReadFile = modkernel32.NewProc("ReadFile") + procRemoveDirectoryW = modkernel32.NewProc("RemoveDirectoryW") + procSetCurrentDirectoryW = modkernel32.NewProc("SetCurrentDirectoryW") + procSetEndOfFile = modkernel32.NewProc("SetEndOfFile") + procSetEnvironmentVariableW = modkernel32.NewProc("SetEnvironmentVariableW") + procSetFileAttributesW = modkernel32.NewProc("SetFileAttributesW") + procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes") + procSetFilePointer = modkernel32.NewProc("SetFilePointer") + procSetFileTime = modkernel32.NewProc("SetFileTime") + procSetHandleInformation = modkernel32.NewProc("SetHandleInformation") + procTerminateProcess = modkernel32.NewProc("TerminateProcess") + procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") + procVirtualLock = modkernel32.NewProc("VirtualLock") + procVirtualUnlock = modkernel32.NewProc("VirtualUnlock") + procWaitForSingleObject = modkernel32.NewProc("WaitForSingleObject") + procWriteConsoleW = modkernel32.NewProc("WriteConsoleW") + procWriteFile = modkernel32.NewProc("WriteFile") + procAcceptEx = modmswsock.NewProc("AcceptEx") + procGetAcceptExSockaddrs = modmswsock.NewProc("GetAcceptExSockaddrs") + procTransmitFile = modmswsock.NewProc("TransmitFile") + procNetApiBufferFree = modnetapi32.NewProc("NetApiBufferFree") + procNetGetJoinInformation = modnetapi32.NewProc("NetGetJoinInformation") + procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") + procGetUserNameExW = modsecur32.NewProc("GetUserNameExW") + procTranslateNameW = modsecur32.NewProc("TranslateNameW") + procCommandLineToArgvW = modshell32.NewProc("CommandLineToArgvW") + procGetUserProfileDirectoryW = moduserenv.NewProc("GetUserProfileDirectoryW") + procFreeAddrInfoW = modws2_32.NewProc("FreeAddrInfoW") + procGetAddrInfoW = modws2_32.NewProc("GetAddrInfoW") + procWSACleanup = modws2_32.NewProc("WSACleanup") + procWSAEnumProtocolsW = modws2_32.NewProc("WSAEnumProtocolsW") + procWSAIoctl = modws2_32.NewProc("WSAIoctl") + procWSARecv = modws2_32.NewProc("WSARecv") + procWSARecvFrom = modws2_32.NewProc("WSARecvFrom") + procWSASend = modws2_32.NewProc("WSASend") + procWSASendTo = modws2_32.NewProc("WSASendTo") + procWSAStartup = modws2_32.NewProc("WSAStartup") + procbind = modws2_32.NewProc("bind") + procclosesocket = modws2_32.NewProc("closesocket") + procconnect = modws2_32.NewProc("connect") + procgethostbyname = modws2_32.NewProc("gethostbyname") + procgetpeername = modws2_32.NewProc("getpeername") + procgetprotobyname = modws2_32.NewProc("getprotobyname") + procgetservbyname = modws2_32.NewProc("getservbyname") + procgetsockname = modws2_32.NewProc("getsockname") + procgetsockopt = modws2_32.NewProc("getsockopt") + proclisten = modws2_32.NewProc("listen") + procntohs = modws2_32.NewProc("ntohs") + procsetsockopt = modws2_32.NewProc("setsockopt") + procshutdown = modws2_32.NewProc("shutdown") + procsocket = modws2_32.NewProc("socket") ) -func GetLastError() (lasterr error) { - r0, _, _ := Syscall(procGetLastError.Addr(), 0, 0, 0, 0) - if r0 != 0 { - lasterr = Errno(r0) - } - return -} - -func LoadLibrary(libname string) (handle Handle, err error) { - var _p0 *uint16 - _p0, err = UTF16PtrFromString(libname) - if err != nil { - return - } - return _LoadLibrary(_p0) -} - -func _LoadLibrary(libname *uint16) (handle Handle, err error) { - r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(libname)), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func FreeLibrary(handle Handle) (err error) { - r1, _, e1 := Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0) +func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) { + r1, _, e1 := Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(procname) - if err != nil { - return - } - return _GetProcAddress(module, _p0) -} - -func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { - r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0) - proc = uintptr(r0) - if proc == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetVersion() (ver uint32, err error) { - r0, _, e1 := Syscall(procGetVersion.Addr(), 0, 0, 0, 0) - ver = uint32(r0) - if ver == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { - var _p0 *uint16 - if len(buf) > 0 { - _p0 = &buf[0] - } - r0, _, e1 := Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func ExitProcess(exitcode uint32) { - Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) - return -} - -func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) { - r0, _, e1 := Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) +func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { + r1, _, e1 := Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { - var _p0 *byte - if len(buf) > 0 { - _p0 = &buf[0] - } - r1, _, e1 := Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) +func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { + r1, _, e1 := Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { - r0, _, e1 := Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) - newlowoffset = uint32(r0) - if newlowoffset == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CloseHandle(handle Handle) (err error) { - r1, _, e1 := Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetStdHandle(stdhandle int) (handle Handle, err error) { - r0, _, e1 := Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) { - r0, _, e1 := Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func findNextFile1(handle Handle, data *win32finddata1) (err error) { - r1, _, e1 := Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func FindClose(handle Handle) (err error) { - r1, _, e1 := Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { - r1, _, e1 := Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func SetCurrentDirectory(path *uint16) (err error) { - r1, _, e1 := Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { - r1, _, e1 := Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func RemoveDirectory(path *uint16) (err error) { - r1, _, e1 := Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func DeleteFile(path *uint16) (err error) { - r1, _, e1 := Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func MoveFile(from *uint16, to *uint16) (err error) { - r1, _, e1 := Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetComputerName(buf *uint16, n *uint32) (err error) { - r1, _, e1 := Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func SetEndOfFile(handle Handle) (err error) { - r1, _, e1 := Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetSystemTimeAsFileTime(time *Filetime) { - Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) - return -} - -func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { - r0, _, e1 := Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0) - rc = uint32(r0) - if rc == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { - r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { - r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CancelIo(s Handle) (err error) { - r1, _, e1 := Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CancelIoEx(s Handle, o *Overlapped) (err error) { - r1, _, e1 := Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { - var _p0 uint32 - if inheritHandles { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } @@ -623,165 +223,10 @@ func CreateProcessAsUser(token Token, appName *uint16, commandLine *uint16, proc var _p0 uint32 if inheritHandles { _p0 = 1 - } else { - _p0 = 0 } r1, _, e1 := Syscall12(procCreateProcessAsUserW.Addr(), 11, uintptr(token), uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) { - var _p0 uint32 - if inheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r0, _, e1 := Syscall(procOpenProcess.Addr(), 3, uintptr(da), uintptr(_p0), uintptr(pid)) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func TerminateProcess(handle Handle, exitcode uint32) (err error) { - r1, _, e1 := Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { - r1, _, e1 := Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetStartupInfo(startupInfo *StartupInfo) (err error) { - r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetCurrentProcess() (pseudoHandle Handle, err error) { - r0, _, e1 := Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0) - pseudoHandle = Handle(r0) - if pseudoHandle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { - r1, _, e1 := Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) { - var _p0 uint32 - if bInheritHandle { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { - r0, _, e1 := Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0) - event = uint32(r0) - if event == 0xffffffff { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { - r0, _, e1 := Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) { - r1, _, e1 := Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetFileType(filehandle Handle) (n uint32, err error) { - r0, _, e1 := Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } @@ -789,23 +234,7 @@ func GetFileType(filehandle Handle) (n uint32, err error) { func CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) { r1, _, e1 := Syscall6(procCryptAcquireContextW.Addr(), 5, uintptr(unsafe.Pointer(provhandle)), uintptr(unsafe.Pointer(container)), uintptr(unsafe.Pointer(provider)), uintptr(provtype), uintptr(flags), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { - r1, _, e1 := Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } @@ -813,446 +242,53 @@ func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { func CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) { r1, _, e1 := Syscall(procCryptGenRandom.Addr(), 3, uintptr(provhandle), uintptr(buflen), uintptr(unsafe.Pointer(buf))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func RtlGenRandom(buf *uint8, bytes uint32) (err error) { - r1, _, e1 := Syscall(procSystemFunction036.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(bytes), 0) +func CryptReleaseContext(provhandle Handle, flags uint32) (err error) { + r1, _, e1 := Syscall(procCryptReleaseContext.Addr(), 2, uintptr(provhandle), uintptr(flags), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func GetEnvironmentStrings() (envs *uint16, err error) { - r0, _, e1 := Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0) - envs = (*uint16)(unsafe.Pointer(r0)) - if envs == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } +func GetLengthSid(sid *SID) (len uint32) { + r0, _, _ := Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) + len = uint32(r0) return } -func FreeEnvironmentStrings(envs *uint16) (err error) { - r1, _, e1 := Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0) +func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) { + r1, _, e1 := Syscall6(procGetTokenInformation.Addr(), 5, uintptr(t), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { - r0, _, e1 := Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { - r1, _, e1 := Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) +func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { + r1, _, e1 := Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { - r1, _, e1 := Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) +func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { + r1, _, e1 := Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func GetFileAttributes(name *uint16) (attrs uint32, err error) { - r0, _, e1 := Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - attrs = uint32(r0) - if attrs == INVALID_FILE_ATTRIBUTES { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func SetFileAttributes(name *uint16, attrs uint32) (err error) { - r1, _, e1 := Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0) +func OpenProcessToken(h Handle, access uint32, token *Token) (err error) { + r1, _, e1 := Syscall(procOpenProcessToken.Addr(), 3, uintptr(h), uintptr(access), uintptr(unsafe.Pointer(token))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { - r1, _, e1 := Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetCommandLine() (cmd *uint16) { - r0, _, _ := Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0) - cmd = (*uint16)(unsafe.Pointer(r0)) - return -} - -func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { - r0, _, e1 := Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) - argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0)) - if argv == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func LocalFree(hmem Handle) (handle Handle, err error) { - r0, _, e1 := Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0) - handle = Handle(r0) - if handle != 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { - r1, _, e1 := Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func FlushFileBuffers(handle Handle) (err error) { - r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { - r0, _, e1 := Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { - r0, _, e1 := Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) - n = uint32(r0) - if n == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { - r0, _, e1 := Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) - handle = Handle(r0) - if handle == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { - r0, _, e1 := Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0) - addr = uintptr(r0) - if addr == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func UnmapViewOfFile(addr uintptr) (err error) { - r1, _, e1 := Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func FlushViewOfFile(addr uintptr, length uintptr) (err error) { - r1, _, e1 := Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func VirtualLock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func VirtualUnlock(addr uintptr, length uintptr) (err error) { - r1, _, e1 := Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { - r1, _, e1 := Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { - var _p0 uint32 - if watchSubTree { - _p0 = 1 - } else { - _p0 = 0 - } - r1, _, e1 := Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { - r0, _, e1 := Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0) - store = Handle(r0) - if store == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { - r0, _, e1 := Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) { - r0, _, e1 := Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0) - context = (*CertContext)(unsafe.Pointer(r0)) - if context == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) { - r1, _, e1 := Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertCloseStore(store Handle, flags uint32) (err error) { - r1, _, e1 := Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) { - r1, _, e1 := Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertFreeCertificateChain(ctx *CertChainContext) { - Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) - return -} - -func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) { - r0, _, e1 := Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) - context = (*CertContext)(unsafe.Pointer(r0)) - if context == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertFreeCertificateContext(ctx *CertContext) (err error) { - r1, _, e1 := Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) { - r1, _, e1 := Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) { - r0, _, _ := Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0) - if r0 != 0 { - regerrno = Errno(r0) + err = errnoErr(e1) } return } @@ -1265,14 +301,6 @@ func RegCloseKey(key Handle) (regerrno error) { return } -func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) { - r0, _, _ := Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) - if r0 != 0 { - regerrno = Errno(r0) - } - return -} - func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) { r0, _, _ := Syscall9(procRegEnumKeyExW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(lastWriteTime)), 0) if r0 != 0 { @@ -1281,6 +309,22 @@ func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reser return } +func RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) { + r0, _, _ := Syscall6(procRegOpenKeyExW.Addr(), 5, uintptr(key), uintptr(unsafe.Pointer(subkey)), uintptr(options), uintptr(desiredAccess), uintptr(unsafe.Pointer(result)), 0) + if r0 != 0 { + regerrno = Errno(r0) + } + return +} + +func RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) { + r0, _, _ := Syscall12(procRegQueryInfoKeyW.Addr(), 12, uintptr(key), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(classLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(subkeysLen)), uintptr(unsafe.Pointer(maxSubkeyLen)), uintptr(unsafe.Pointer(maxClassLen)), uintptr(unsafe.Pointer(valuesLen)), uintptr(unsafe.Pointer(maxValueNameLen)), uintptr(unsafe.Pointer(maxValueLen)), uintptr(unsafe.Pointer(saLen)), uintptr(unsafe.Pointer(lastWriteTime))) + if r0 != 0 { + regerrno = Errno(r0) + } + return +} + func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) { r0, _, _ := Syscall6(procRegQueryValueExW.Addr(), 6, uintptr(key), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(valtype)), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(buflen))) if r0 != 0 { @@ -1289,413 +333,98 @@ func RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32 return } -func getCurrentProcessId() (pid uint32) { - r0, _, _ := Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0) - pid = uint32(r0) - return -} - -func GetConsoleMode(console Handle, mode *uint32) (err error) { - r1, _, e1 := Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) +func RtlGenRandom(buf *uint8, bytes uint32) (err error) { + r1, _, e1 := Syscall(procSystemFunction036.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(bytes), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { - r1, _, e1 := Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0) +func CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) { + r1, _, e1 := Syscall6(procCertAddCertificateContextToStore.Addr(), 4, uintptr(store), uintptr(unsafe.Pointer(certContext)), uintptr(addDisposition), uintptr(unsafe.Pointer(storeContext)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { - r1, _, e1 := Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0) +func CertCloseStore(store Handle, flags uint32) (err error) { + r1, _, e1 := Syscall(procCertCloseStore.Addr(), 2, uintptr(store), uintptr(flags), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) { - r0, _, e1 := Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0) +func CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) { + r0, _, e1 := Syscall(procCertCreateCertificateContext.Addr(), 3, uintptr(certEncodingType), uintptr(unsafe.Pointer(certEncoded)), uintptr(encodedLen)) + context = (*CertContext)(unsafe.Pointer(r0)) + if context == nil { + err = errnoErr(e1) + } + return +} + +func CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) { + r0, _, e1 := Syscall(procCertEnumCertificatesInStore.Addr(), 2, uintptr(store), uintptr(unsafe.Pointer(prevContext)), 0) + context = (*CertContext)(unsafe.Pointer(r0)) + if context == nil { + err = errnoErr(e1) + } + return +} + +func CertFreeCertificateChain(ctx *CertChainContext) { + Syscall(procCertFreeCertificateChain.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + return +} + +func CertFreeCertificateContext(ctx *CertContext) (err error) { + r1, _, e1 := Syscall(procCertFreeCertificateContext.Addr(), 1, uintptr(unsafe.Pointer(ctx)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) { + r1, _, e1 := Syscall9(procCertGetCertificateChain.Addr(), 8, uintptr(engine), uintptr(unsafe.Pointer(leaf)), uintptr(unsafe.Pointer(time)), uintptr(additionalStore), uintptr(unsafe.Pointer(para)), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(chainCtx)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) { + r0, _, e1 := Syscall6(procCertOpenStore.Addr(), 5, uintptr(storeProvider), uintptr(msgAndCertEncodingType), uintptr(cryptProv), uintptr(flags), uintptr(para), 0) handle = Handle(r0) if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) +func CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) { + r0, _, e1 := Syscall(procCertOpenSystemStoreW.Addr(), 2, uintptr(hprov), uintptr(unsafe.Pointer(name)), 0) + store = Handle(r0) + if store == 0 { + err = errnoErr(e1) + } + return +} + +func CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) { + r1, _, e1 := Syscall6(procCertVerifyCertificateChainPolicy.Addr(), 4, uintptr(policyOID), uintptr(unsafe.Pointer(chain)), uintptr(unsafe.Pointer(para)), uintptr(unsafe.Pointer(status)), 0, 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { - r1, _, e1 := Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) { - r1, _, e1 := Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) { - r1, _, e1 := Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { - r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) - if r0 != 0 { - sockerr = Errno(r0) - } - return -} - -func WSACleanup() (err error) { - r1, _, e1 := Syscall(procWSACleanup.Addr(), 0, 0, 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { - r1, _, e1 := Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { - r0, _, e1 := Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol)) - handle = Handle(r0) - if handle == InvalidHandle { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { - r1, _, e1 := Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { - r1, _, e1 := Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { - r1, _, e1 := Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { - r1, _, e1 := Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func listen(s Handle, backlog int32) (err error) { - r1, _, e1 := Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func shutdown(s Handle, how int32) (err error) { - r1, _, e1 := Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func Closesocket(s Handle) (err error) { - r1, _, e1 := Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { - r1, _, e1 := Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { - Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0) - return -} - -func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { - r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) - if r1 == socket_error { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetHostByName(name string) (h *Hostent, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - return _GetHostByName(_p0) -} - -func _GetHostByName(name *byte) (h *Hostent, err error) { - r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - h = (*Hostent)(unsafe.Pointer(r0)) - if h == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetServByName(name string, proto string) (s *Servent, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - var _p1 *byte - _p1, err = BytePtrFromString(proto) - if err != nil { - return - } - return _GetServByName(_p0, _p1) -} - -func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { - r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0) - s = (*Servent)(unsafe.Pointer(r0)) - if s == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func Ntohs(netshort uint16) (u uint16) { - r0, _, _ := Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0) - u = uint16(r0) - return -} - -func GetProtoByName(name string) (p *Protoent, err error) { - var _p0 *byte - _p0, err = BytePtrFromString(name) - if err != nil { - return - } - return _GetProtoByName(_p0) -} - -func _GetProtoByName(name *byte) (p *Protoent, err error) { - r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) - p = (*Protoent)(unsafe.Pointer(r0)) - if p == nil { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } +func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) { + r0, _, _ := Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0) + same = r0 != 0 return } @@ -1721,25 +450,14 @@ func DnsRecordListFree(rl *DNSRecord, freetype uint32) { return } -func DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) { - r0, _, _ := Syscall(procDnsNameCompare_W.Addr(), 2, uintptr(unsafe.Pointer(name1)), uintptr(unsafe.Pointer(name2)), 0) - same = r0 != 0 - return -} - -func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { - r0, _, _ := Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0) +func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { + r0, _, _ := Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0) if r0 != 0 { - sockerr = Errno(r0) + errcode = Errno(r0) } return } -func FreeAddrInfoW(addrinfo *AddrinfoW) { - Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0) - return -} - func GetIfEntry(pIfRow *MibIfRow) (errcode error) { r0, _, _ := Syscall(procGetIfEntry.Addr(), 1, uintptr(unsafe.Pointer(pIfRow)), 0, 0) if r0 != 0 { @@ -1748,10 +466,595 @@ func GetIfEntry(pIfRow *MibIfRow) (errcode error) { return } -func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { - r0, _, _ := Syscall(procGetAdaptersInfo.Addr(), 2, uintptr(unsafe.Pointer(ai)), uintptr(unsafe.Pointer(ol)), 0) +func CancelIo(s Handle) (err error) { + r1, _, e1 := Syscall(procCancelIo.Addr(), 1, uintptr(s), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CancelIoEx(s Handle, o *Overlapped) (err error) { + r1, _, e1 := Syscall(procCancelIoEx.Addr(), 2, uintptr(s), uintptr(unsafe.Pointer(o)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CloseHandle(handle Handle) (err error) { + r1, _, e1 := Syscall(procCloseHandle.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) { + r1, _, e1 := Syscall(procCreateDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(sa)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { + r0, _, e1 := Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) { + r0, _, e1 := Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) { + r1, _, e1 := Syscall(procCreateHardLinkW.Addr(), 3, uintptr(unsafe.Pointer(filename)), uintptr(unsafe.Pointer(existingfilename)), uintptr(reserved)) + if r1&0xff == 0 { + err = errnoErr(e1) + } + return +} + +func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error) { + r0, _, e1 := Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(filehandle), uintptr(cphandle), uintptr(key), uintptr(threadcnt), 0, 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error) { + r1, _, e1 := Syscall6(procCreatePipe.Addr(), 4, uintptr(unsafe.Pointer(readhandle)), uintptr(unsafe.Pointer(writehandle)), uintptr(unsafe.Pointer(sa)), uintptr(size), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) { + var _p0 uint32 + if inheritHandles { + _p0 = 1 + } + r1, _, e1 := Syscall12(procCreateProcessW.Addr(), 10, uintptr(unsafe.Pointer(appName)), uintptr(unsafe.Pointer(commandLine)), uintptr(unsafe.Pointer(procSecurity)), uintptr(unsafe.Pointer(threadSecurity)), uintptr(_p0), uintptr(creationFlags), uintptr(unsafe.Pointer(env)), uintptr(unsafe.Pointer(currentDir)), uintptr(unsafe.Pointer(startupInfo)), uintptr(unsafe.Pointer(outProcInfo)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) { + r1, _, e1 := Syscall(procCreateSymbolicLinkW.Addr(), 3, uintptr(unsafe.Pointer(symlinkfilename)), uintptr(unsafe.Pointer(targetfilename)), uintptr(flags)) + if r1&0xff == 0 { + err = errnoErr(e1) + } + return +} + +func CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) { + r0, _, e1 := Syscall(procCreateToolhelp32Snapshot.Addr(), 2, uintptr(flags), uintptr(processId), 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func DeleteFile(path *uint16) (err error) { + r1, _, e1 := Syscall(procDeleteFileW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(ioControlCode), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferSize), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferSize), uintptr(unsafe.Pointer(bytesReturned)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error) { + var _p0 uint32 + if bInheritHandle { + _p0 = 1 + } + r1, _, e1 := Syscall9(procDuplicateHandle.Addr(), 7, uintptr(hSourceProcessHandle), uintptr(hSourceHandle), uintptr(hTargetProcessHandle), uintptr(unsafe.Pointer(lpTargetHandle)), uintptr(dwDesiredAccess), uintptr(_p0), uintptr(dwOptions), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ExitProcess(exitcode uint32) { + Syscall(procExitProcess.Addr(), 1, uintptr(exitcode), 0, 0) + return +} + +func FindClose(handle Handle) (err error) { + r1, _, e1 := Syscall(procFindClose.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) { + r0, _, e1 := Syscall(procFindFirstFileW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(data)), 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func findNextFile1(handle Handle, data *win32finddata1) (err error) { + r1, _, e1 := Syscall(procFindNextFileW.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FlushFileBuffers(handle Handle) (err error) { + r1, _, e1 := Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FlushViewOfFile(addr uintptr, length uintptr) (err error) { + r1, _, e1 := Syscall(procFlushViewOfFile.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func formatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) { + var _p0 *uint16 + if len(buf) > 0 { + _p0 = &buf[0] + } + r0, _, e1 := Syscall9(procFormatMessageW.Addr(), 7, uintptr(flags), uintptr(msgsrc), uintptr(msgid), uintptr(langid), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(args)), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func FreeEnvironmentStrings(envs *uint16) (err error) { + r1, _, e1 := Syscall(procFreeEnvironmentStringsW.Addr(), 1, uintptr(unsafe.Pointer(envs)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func FreeLibrary(handle Handle) (err error) { + r1, _, e1 := Syscall(procFreeLibrary.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetCommandLine() (cmd *uint16) { + r0, _, _ := Syscall(procGetCommandLineW.Addr(), 0, 0, 0, 0) + cmd = (*uint16)(unsafe.Pointer(r0)) + return +} + +func GetComputerName(buf *uint16, n *uint32) (err error) { + r1, _, e1 := Syscall(procGetComputerNameW.Addr(), 2, uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(n)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetConsoleMode(console Handle, mode *uint32) (err error) { + r1, _, e1 := Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := Syscall(procGetCurrentDirectoryW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetCurrentProcess() (pseudoHandle Handle, err error) { + r0, _, e1 := Syscall(procGetCurrentProcess.Addr(), 0, 0, 0, 0) + pseudoHandle = Handle(r0) + if pseudoHandle == 0 { + err = errnoErr(e1) + } + return +} + +func getCurrentProcessId() (pid uint32) { + r0, _, _ := Syscall(procGetCurrentProcessId.Addr(), 0, 0, 0, 0) + pid = uint32(r0) + return +} + +func GetEnvironmentStrings() (envs *uint16, err error) { + r0, _, e1 := Syscall(procGetEnvironmentStringsW.Addr(), 0, 0, 0, 0) + envs = (*uint16)(unsafe.Pointer(r0)) + if envs == nil { + err = errnoErr(e1) + } + return +} + +func GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) { + r0, _, e1 := Syscall(procGetEnvironmentVariableW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(size)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetExitCodeProcess(handle Handle, exitcode *uint32) (err error) { + r1, _, e1 := Syscall(procGetExitCodeProcess.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(exitcode)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) { + r1, _, e1 := Syscall(procGetFileAttributesExW.Addr(), 3, uintptr(unsafe.Pointer(name)), uintptr(level), uintptr(unsafe.Pointer(info))) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileAttributes(name *uint16) (attrs uint32, err error) { + r0, _, e1 := Syscall(procGetFileAttributesW.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + attrs = uint32(r0) + if attrs == INVALID_FILE_ATTRIBUTES { + err = errnoErr(e1) + } + return +} + +func GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error) { + r1, _, e1 := Syscall(procGetFileInformationByHandle.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(data)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetFileType(filehandle Handle) (n uint32, err error) { + r0, _, e1 := Syscall(procGetFileType.Addr(), 1, uintptr(filehandle), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) { + r0, _, e1 := Syscall6(procGetFullPathNameW.Addr(), 4, uintptr(unsafe.Pointer(path)), uintptr(buflen), uintptr(unsafe.Pointer(buf)), uintptr(unsafe.Pointer(fname)), 0, 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetLastError() (lasterr error) { + r0, _, _ := Syscall(procGetLastError.Addr(), 0, 0, 0, 0) if r0 != 0 { - errcode = Errno(r0) + lasterr = Errno(r0) + } + return +} + +func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := Syscall(procGetLongPathNameW.Addr(), 3, uintptr(unsafe.Pointer(path)), uintptr(unsafe.Pointer(buf)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcAddress(module Handle, procname string) (proc uintptr, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(procname) + if err != nil { + return + } + return _GetProcAddress(module, _p0) +} + +func _GetProcAddress(module Handle, procname *byte) (proc uintptr, err error) { + r0, _, e1 := Syscall(procGetProcAddress.Addr(), 2, uintptr(module), uintptr(unsafe.Pointer(procname)), 0) + proc = uintptr(r0) + if proc == 0 { + err = errnoErr(e1) + } + return +} + +func GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error) { + r1, _, e1 := Syscall6(procGetProcessTimes.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(creationTime)), uintptr(unsafe.Pointer(exitTime)), uintptr(unsafe.Pointer(kernelTime)), uintptr(unsafe.Pointer(userTime)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error) { + r1, _, e1 := Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(cphandle), uintptr(unsafe.Pointer(qty)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(overlapped)), uintptr(timeout), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetStartupInfo(startupInfo *StartupInfo) (err error) { + r1, _, e1 := Syscall(procGetStartupInfoW.Addr(), 1, uintptr(unsafe.Pointer(startupInfo)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetStdHandle(stdhandle int) (handle Handle, err error) { + r0, _, e1 := Syscall(procGetStdHandle.Addr(), 1, uintptr(stdhandle), 0, 0) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) + } + return +} + +func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { + r0, _, e1 := Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) + len = uint32(r0) + if len == 0 { + err = errnoErr(e1) + } + return +} + +func GetSystemTimeAsFileTime(time *Filetime) { + Syscall(procGetSystemTimeAsFileTime.Addr(), 1, uintptr(unsafe.Pointer(time)), 0, 0) + return +} + +func GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) { + r0, _, e1 := Syscall(procGetTempPathW.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0) + n = uint32(r0) + if n == 0 { + err = errnoErr(e1) + } + return +} + +func GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) { + r0, _, e1 := Syscall(procGetTimeZoneInformation.Addr(), 1, uintptr(unsafe.Pointer(tzi)), 0, 0) + rc = uint32(r0) + if rc == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func GetVersion() (ver uint32, err error) { + r0, _, e1 := Syscall(procGetVersion.Addr(), 0, 0, 0, 0) + ver = uint32(r0) + if ver == 0 { + err = errnoErr(e1) + } + return +} + +func LoadLibrary(libname string) (handle Handle, err error) { + var _p0 *uint16 + _p0, err = UTF16PtrFromString(libname) + if err != nil { + return + } + return _LoadLibrary(_p0) +} + +func _LoadLibrary(libname *uint16) (handle Handle, err error) { + r0, _, e1 := Syscall(procLoadLibraryW.Addr(), 1, uintptr(unsafe.Pointer(libname)), 0, 0) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func LocalFree(hmem Handle) (handle Handle, err error) { + r0, _, e1 := Syscall(procLocalFree.Addr(), 1, uintptr(hmem), 0, 0) + handle = Handle(r0) + if handle != 0 { + err = errnoErr(e1) + } + return +} + +func MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) { + r0, _, e1 := Syscall6(procMapViewOfFile.Addr(), 5, uintptr(handle), uintptr(access), uintptr(offsetHigh), uintptr(offsetLow), uintptr(length), 0) + addr = uintptr(r0) + if addr == 0 { + err = errnoErr(e1) + } + return +} + +func MoveFile(from *uint16, to *uint16) (err error) { + r1, _, e1 := Syscall(procMoveFileW.Addr(), 2, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error) { + var _p0 uint32 + if inheritHandle { + _p0 = 1 + } + r0, _, e1 := Syscall(procOpenProcess.Addr(), 3, uintptr(da), uintptr(_p0), uintptr(pid)) + handle = Handle(r0) + if handle == 0 { + err = errnoErr(e1) + } + return +} + +func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := Syscall(procProcess32FirstW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) { + r1, _, e1 := Syscall(procProcess32NextW.Addr(), 2, uintptr(snapshot), uintptr(unsafe.Pointer(procEntry)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) { + r1, _, e1 := Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { + var _p0 uint32 + if watchSubTree { + _p0 = 1 + } + r1, _, e1 := Syscall9(procReadDirectoryChangesW.Addr(), 8, uintptr(handle), uintptr(unsafe.Pointer(buf)), uintptr(buflen), uintptr(_p0), uintptr(mask), uintptr(unsafe.Pointer(retlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := Syscall6(procReadFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func RemoveDirectory(path *uint16) (err error) { + r1, _, e1 := Syscall(procRemoveDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetCurrentDirectory(path *uint16) (err error) { + r1, _, e1 := Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetEndOfFile(handle Handle) (err error) { + r1, _, e1 := Syscall(procSetEndOfFile.Addr(), 1, uintptr(handle), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetEnvironmentVariable(name *uint16, value *uint16) (err error) { + r1, _, e1 := Syscall(procSetEnvironmentVariableW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(value)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func SetFileAttributes(name *uint16, attrs uint32) (err error) { + r1, _, e1 := Syscall(procSetFileAttributesW.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(attrs), 0) + if r1 == 0 { + err = errnoErr(e1) } return } @@ -1759,54 +1062,120 @@ func GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) { func SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) { r1, _, e1 := Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(handle), uintptr(flags), 0) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { - r0, _, e1 := Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) - n = int32(r0) - if n == -1 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } +func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { + r0, _, e1 := Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) + newlowoffset = uint32(r0) + if newlowoffset == 0xffffffff { + err = errnoErr(e1) } return } -func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { - r1, _, e1 := Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } +func SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error) { + r1, _, e1 := Syscall6(procSetFileTime.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(ctime)), uintptr(unsafe.Pointer(atime)), uintptr(unsafe.Pointer(wtime)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) } return } -func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { - r1, _, e1 := Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) - if r1&0xff == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } +func SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error) { + r1, _, e1 := Syscall(procSetHandleInformation.Addr(), 3, uintptr(handle), uintptr(mask), uintptr(flags)) + if r1 == 0 { + err = errnoErr(e1) } return } -func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { - r0, _, _ := Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) +func TerminateProcess(handle Handle, exitcode uint32) (err error) { + r1, _, e1 := Syscall(procTerminateProcess.Addr(), 2, uintptr(handle), uintptr(exitcode), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func UnmapViewOfFile(addr uintptr) (err error) { + r1, _, e1 := Syscall(procUnmapViewOfFile.Addr(), 1, uintptr(addr), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualLock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := Syscall(procVirtualLock.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func VirtualUnlock(addr uintptr, length uintptr) (err error) { + r1, _, e1 := Syscall(procVirtualUnlock.Addr(), 2, uintptr(addr), uintptr(length), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) { + r0, _, e1 := Syscall(procWaitForSingleObject.Addr(), 2, uintptr(handle), uintptr(waitMilliseconds), 0) + event = uint32(r0) + if event == 0xffffffff { + err = errnoErr(e1) + } + return +} + +func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) { + r1, _, e1 := Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r1, _, e1 := Syscall6(procWriteFile.Addr(), 5, uintptr(handle), uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), uintptr(unsafe.Pointer(done)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) { + r1, _, e1 := Syscall9(procAcceptEx.Addr(), 8, uintptr(ls), uintptr(as), uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(overlapped)), 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) { + Syscall9(procGetAcceptExSockaddrs.Addr(), 8, uintptr(unsafe.Pointer(buf)), uintptr(rxdatalen), uintptr(laddrlen), uintptr(raddrlen), uintptr(unsafe.Pointer(lrsa)), uintptr(unsafe.Pointer(lrsalen)), uintptr(unsafe.Pointer(rrsa)), uintptr(unsafe.Pointer(rrsalen)), 0) + return +} + +func TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) { + r1, _, e1 := Syscall9(procTransmitFile.Addr(), 7, uintptr(s), uintptr(handle), uintptr(bytesToWrite), uintptr(bytsPerSend), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(transmitFileBuf)), uintptr(flags), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func NetApiBufferFree(buf *byte) (neterr error) { + r0, _, _ := Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) if r0 != 0 { neterr = Errno(r0) } @@ -1821,100 +1190,35 @@ func NetGetJoinInformation(server *uint16, name **uint16, bufType *uint32) (nete return } -func NetApiBufferFree(buf *byte) (neterr error) { - r0, _, _ := Syscall(procNetApiBufferFree.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) +func NetUserGetInfo(serverName *uint16, userName *uint16, level uint32, buf **byte) (neterr error) { + r0, _, _ := Syscall6(procNetUserGetInfo.Addr(), 4, uintptr(unsafe.Pointer(serverName)), uintptr(unsafe.Pointer(userName)), uintptr(level), uintptr(unsafe.Pointer(buf)), 0, 0) if r0 != 0 { neterr = Errno(r0) } return } -func LookupAccountSid(systemName *uint16, sid *SID, name *uint16, nameLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } +func GetUserNameEx(nameFormat uint32, nameBuffre *uint16, nSize *uint32) (err error) { + r1, _, e1 := Syscall(procGetUserNameExW.Addr(), 3, uintptr(nameFormat), uintptr(unsafe.Pointer(nameBuffre)), uintptr(unsafe.Pointer(nSize))) + if r1&0xff == 0 { + err = errnoErr(e1) } return } -func LookupAccountName(systemName *uint16, accountName *uint16, sid *SID, sidLen *uint32, refdDomainName *uint16, refdDomainNameLen *uint32, use *uint32) (err error) { - r1, _, e1 := Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidLen)), uintptr(unsafe.Pointer(refdDomainName)), uintptr(unsafe.Pointer(refdDomainNameLen)), uintptr(unsafe.Pointer(use)), 0, 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } +func TranslateName(accName *uint16, accNameFormat uint32, desiredNameFormat uint32, translatedName *uint16, nSize *uint32) (err error) { + r1, _, e1 := Syscall6(procTranslateNameW.Addr(), 5, uintptr(unsafe.Pointer(accName)), uintptr(accNameFormat), uintptr(desiredNameFormat), uintptr(unsafe.Pointer(translatedName)), uintptr(unsafe.Pointer(nSize)), 0) + if r1&0xff == 0 { + err = errnoErr(e1) } return } -func ConvertSidToStringSid(sid *SID, stringSid **uint16) (err error) { - r1, _, e1 := Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(stringSid)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func ConvertStringSidToSid(stringSid *uint16, sid **SID) (err error) { - r1, _, e1 := Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(stringSid)), uintptr(unsafe.Pointer(sid)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetLengthSid(sid *SID) (len uint32) { - r0, _, _ := Syscall(procGetLengthSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) - len = uint32(r0) - return -} - -func CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) { - r1, _, e1 := Syscall(procCopySid.Addr(), 3, uintptr(destSidLen), uintptr(unsafe.Pointer(destSid)), uintptr(unsafe.Pointer(srcSid))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func OpenProcessToken(h Handle, access uint32, token *Token) (err error) { - r1, _, e1 := Syscall(procOpenProcessToken.Addr(), 3, uintptr(h), uintptr(access), uintptr(unsafe.Pointer(token))) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } - } - return -} - -func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) { - r1, _, e1 := Syscall6(procGetTokenInformation.Addr(), 5, uintptr(t), uintptr(infoClass), uintptr(unsafe.Pointer(info)), uintptr(infoLen), uintptr(unsafe.Pointer(returnedLen)), 0) - if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } +func CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) { + r0, _, e1 := Syscall(procCommandLineToArgvW.Addr(), 2, uintptr(unsafe.Pointer(cmd)), uintptr(unsafe.Pointer(argc)), 0) + argv = (*[8192]*[8192]uint16)(unsafe.Pointer(r0)) + if argv == nil { + err = errnoErr(e1) } return } @@ -1922,24 +1226,231 @@ func GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, func GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) { r1, _, e1 := Syscall(procGetUserProfileDirectoryW.Addr(), 3, uintptr(t), uintptr(unsafe.Pointer(dir)), uintptr(unsafe.Pointer(dirLen))) if r1 == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } + err = errnoErr(e1) } return } -func getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) { - r0, _, e1 := Syscall(procGetSystemDirectoryW.Addr(), 2, uintptr(unsafe.Pointer(dir)), uintptr(dirLen), 0) - len = uint32(r0) - if len == 0 { - if e1 != 0 { - err = errnoErr(e1) - } else { - err = EINVAL - } +func FreeAddrInfoW(addrinfo *AddrinfoW) { + Syscall(procFreeAddrInfoW.Addr(), 1, uintptr(unsafe.Pointer(addrinfo)), 0, 0) + return +} + +func GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) { + r0, _, _ := Syscall6(procGetAddrInfoW.Addr(), 4, uintptr(unsafe.Pointer(nodename)), uintptr(unsafe.Pointer(servicename)), uintptr(unsafe.Pointer(hints)), uintptr(unsafe.Pointer(result)), 0, 0) + if r0 != 0 { + sockerr = Errno(r0) + } + return +} + +func WSACleanup() (err error) { + r1, _, e1 := Syscall(procWSACleanup.Addr(), 0, 0, 0, 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) { + r0, _, e1 := Syscall(procWSAEnumProtocolsW.Addr(), 3, uintptr(unsafe.Pointer(protocols)), uintptr(unsafe.Pointer(protocolBuffer)), uintptr(unsafe.Pointer(bufferLength))) + n = int32(r0) + if n == -1 { + err = errnoErr(e1) + } + return +} + +func WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) { + r1, _, e1 := Syscall9(procWSAIoctl.Addr(), 9, uintptr(s), uintptr(iocc), uintptr(unsafe.Pointer(inbuf)), uintptr(cbif), uintptr(unsafe.Pointer(outbuf)), uintptr(cbob), uintptr(unsafe.Pointer(cbbr)), uintptr(unsafe.Pointer(overlapped)), uintptr(completionRoutine)) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := Syscall9(procWSARecv.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := Syscall9(procWSARecvFrom.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(recvd)), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(fromlen)), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := Syscall9(procWSASend.Addr(), 7, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)), 0, 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) { + r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(to)), uintptr(tolen), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func WSAStartup(verreq uint32, data *WSAData) (sockerr error) { + r0, _, _ := Syscall(procWSAStartup.Addr(), 2, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) + if r0 != 0 { + sockerr = Errno(r0) + } + return +} + +func bind(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func Closesocket(s Handle) (err error) { + r1, _, e1 := Syscall(procclosesocket.Addr(), 1, uintptr(s), 0, 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func connect(s Handle, name unsafe.Pointer, namelen int32) (err error) { + r1, _, e1 := Syscall(procconnect.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen)) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func GetHostByName(name string) (h *Hostent, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + return _GetHostByName(_p0) +} + +func _GetHostByName(name *byte) (h *Hostent, err error) { + r0, _, e1 := Syscall(procgethostbyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + h = (*Hostent)(unsafe.Pointer(r0)) + if h == nil { + err = errnoErr(e1) + } + return +} + +func getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func GetProtoByName(name string) (p *Protoent, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + return _GetProtoByName(_p0) +} + +func _GetProtoByName(name *byte) (p *Protoent, err error) { + r0, _, e1 := Syscall(procgetprotobyname.Addr(), 1, uintptr(unsafe.Pointer(name)), 0, 0) + p = (*Protoent)(unsafe.Pointer(r0)) + if p == nil { + err = errnoErr(e1) + } + return +} + +func GetServByName(name string, proto string) (s *Servent, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(proto) + if err != nil { + return + } + return _GetServByName(_p0, _p1) +} + +func _GetServByName(name *byte, proto *byte) (s *Servent, err error) { + r0, _, e1 := Syscall(procgetservbyname.Addr(), 2, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(proto)), 0) + s = (*Servent)(unsafe.Pointer(r0)) + if s == nil { + err = errnoErr(e1) + } + return +} + +func getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) { + r1, _, e1 := Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen))) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) { + r1, _, e1 := Syscall6(procgetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(unsafe.Pointer(optlen)), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func listen(s Handle, backlog int32) (err error) { + r1, _, e1 := Syscall(proclisten.Addr(), 2, uintptr(s), uintptr(backlog), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func Ntohs(netshort uint16) (u uint16) { + r0, _, _ := Syscall(procntohs.Addr(), 1, uintptr(netshort), 0, 0) + u = uint16(r0) + return +} + +func Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) { + r1, _, e1 := Syscall6(procsetsockopt.Addr(), 5, uintptr(s), uintptr(level), uintptr(optname), uintptr(unsafe.Pointer(optval)), uintptr(optlen), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func shutdown(s Handle, how int32) (err error) { + r1, _, e1 := Syscall(procshutdown.Addr(), 2, uintptr(s), uintptr(how), 0) + if r1 == socket_error { + err = errnoErr(e1) + } + return +} + +func socket(af int32, typ int32, protocol int32) (handle Handle, err error) { + r0, _, e1 := Syscall(procsocket.Addr(), 3, uintptr(af), uintptr(typ), uintptr(protocol)) + handle = Handle(r0) + if handle == InvalidHandle { + err = errnoErr(e1) } return } diff --git a/src/vendor/golang.org/x/sys/cpu/cpu.go b/src/vendor/golang.org/x/sys/cpu/cpu.go index 5cce25ed9b6..f77701fe868 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu.go @@ -29,26 +29,46 @@ type CacheLinePad struct{ _ [cacheLineSize]byte } // and HasAVX2 are only set if the OS supports XMM and YMM // registers in addition to the CPUID feature bit being set. var X86 struct { - _ CacheLinePad - HasAES bool // AES hardware implementation (AES NI) - HasADX bool // Multi-precision add-carry instruction extensions - HasAVX bool // Advanced vector extension - HasAVX2 bool // Advanced vector extension 2 - HasBMI1 bool // Bit manipulation instruction set 1 - HasBMI2 bool // Bit manipulation instruction set 2 - HasERMS bool // Enhanced REP for MOVSB and STOSB - HasFMA bool // Fused-multiply-add instructions - HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. - HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM - HasPOPCNT bool // Hamming weight instruction POPCNT. - HasRDRAND bool // RDRAND instruction (on-chip random number generator) - HasRDSEED bool // RDSEED instruction (on-chip random number generator) - HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) - HasSSE3 bool // Streaming SIMD extension 3 - HasSSSE3 bool // Supplemental streaming SIMD extension 3 - HasSSE41 bool // Streaming SIMD extension 4 and 4.1 - HasSSE42 bool // Streaming SIMD extension 4 and 4.2 - _ CacheLinePad + _ CacheLinePad + HasAES bool // AES hardware implementation (AES NI) + HasADX bool // Multi-precision add-carry instruction extensions + HasAVX bool // Advanced vector extension + HasAVX2 bool // Advanced vector extension 2 + HasAVX512 bool // Advanced vector extension 512 + HasAVX512F bool // Advanced vector extension 512 Foundation Instructions + HasAVX512CD bool // Advanced vector extension 512 Conflict Detection Instructions + HasAVX512ER bool // Advanced vector extension 512 Exponential and Reciprocal Instructions + HasAVX512PF bool // Advanced vector extension 512 Prefetch Instructions Instructions + HasAVX512VL bool // Advanced vector extension 512 Vector Length Extensions + HasAVX512BW bool // Advanced vector extension 512 Byte and Word Instructions + HasAVX512DQ bool // Advanced vector extension 512 Doubleword and Quadword Instructions + HasAVX512IFMA bool // Advanced vector extension 512 Integer Fused Multiply Add + HasAVX512VBMI bool // Advanced vector extension 512 Vector Byte Manipulation Instructions + HasAVX5124VNNIW bool // Advanced vector extension 512 Vector Neural Network Instructions Word variable precision + HasAVX5124FMAPS bool // Advanced vector extension 512 Fused Multiply Accumulation Packed Single precision + HasAVX512VPOPCNTDQ bool // Advanced vector extension 512 Double and quad word population count instructions + HasAVX512VPCLMULQDQ bool // Advanced vector extension 512 Vector carry-less multiply operations + HasAVX512VNNI bool // Advanced vector extension 512 Vector Neural Network Instructions + HasAVX512GFNI bool // Advanced vector extension 512 Galois field New Instructions + HasAVX512VAES bool // Advanced vector extension 512 Vector AES instructions + HasAVX512VBMI2 bool // Advanced vector extension 512 Vector Byte Manipulation Instructions 2 + HasAVX512BITALG bool // Advanced vector extension 512 Bit Algorithms + HasAVX512BF16 bool // Advanced vector extension 512 BFloat16 Instructions + HasBMI1 bool // Bit manipulation instruction set 1 + HasBMI2 bool // Bit manipulation instruction set 2 + HasERMS bool // Enhanced REP for MOVSB and STOSB + HasFMA bool // Fused-multiply-add instructions + HasOSXSAVE bool // OS supports XSAVE/XRESTOR for saving/restoring XMM registers. + HasPCLMULQDQ bool // PCLMULQDQ instruction - most often used for AES-GCM + HasPOPCNT bool // Hamming weight instruction POPCNT. + HasRDRAND bool // RDRAND instruction (on-chip random number generator) + HasRDSEED bool // RDSEED instruction (on-chip random number generator) + HasSSE2 bool // Streaming SIMD extension 2 (always available on amd64) + HasSSE3 bool // Streaming SIMD extension 3 + HasSSSE3 bool // Supplemental streaming SIMD extension 3 + HasSSE41 bool // Streaming SIMD extension 4 and 4.1 + HasSSE42 bool // Streaming SIMD extension 4 and 4.2 + _ CacheLinePad } // ARM64 contains the supported CPU features of the diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_arm64.go b/src/vendor/golang.org/x/sys/cpu/cpu_arm64.go index 951078f2e82..87dd5e30215 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_arm64.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_arm64.go @@ -39,31 +39,34 @@ func initOptions() { func archInit() { switch runtime.GOOS { - case "android", "darwin", "ios", "netbsd": - // Android and iOS don't seem to allow reading these registers. - // - // NetBSD: - // ID_AA64ISAR0_EL1 is a privileged register and cannot be read from EL0. - // It can be read via sysctl(3). Example for future implementers: - // https://nxr.netbsd.org/xref/src/usr.sbin/cpuctl/arch/aarch64.c - // - // Fake the minimal features expected by - // TestARM64minimalFeatures. - ARM64.HasASIMD = true - ARM64.HasFP = true - case "linux": + case "freebsd": + readARM64Registers() + case "linux", "netbsd": doinit() default: - readARM64Registers() + // Most platforms don't seem to allow reading these registers. + // + // OpenBSD: + // See https://golang.org/issue/31746 + setMinimalFeatures() } } +// setMinimalFeatures fakes the minimal ARM64 features expected by +// TestARM64minimalFeatures. +func setMinimalFeatures() { + ARM64.HasASIMD = true + ARM64.HasFP = true +} + func readARM64Registers() { Initialized = true - // ID_AA64ISAR0_EL1 - isar0 := getisar0() + parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0()) +} +func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { + // ID_AA64ISAR0_EL1 switch extractBits(isar0, 4, 7) { case 1: ARM64.HasAES = true @@ -121,8 +124,6 @@ func readARM64Registers() { } // ID_AA64ISAR1_EL1 - isar1 := getisar1() - switch extractBits(isar1, 0, 3) { case 1: ARM64.HasDCPOP = true @@ -144,8 +145,6 @@ func readARM64Registers() { } // ID_AA64PFR0_EL1 - pfr0 := getpfr0() - switch extractBits(pfr0, 16, 19) { case 0: ARM64.HasFP = true diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go b/src/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go index b88d6b8f662..1517ac61d31 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_linux_s390x.go @@ -17,86 +17,7 @@ const ( hwcap_VXE = 8192 ) -// bitIsSet reports whether the bit at index is set. The bit index -// is in big endian order, so bit index 0 is the leftmost bit. -func bitIsSet(bits []uint64, index uint) bool { - return bits[index/64]&((1<<63)>>(index%64)) != 0 -} - -// function is the code for the named cryptographic function. -type function uint8 - -const ( - // KM{,A,C,CTR} function codes - aes128 function = 18 // AES-128 - aes192 function = 19 // AES-192 - aes256 function = 20 // AES-256 - - // K{I,L}MD function codes - sha1 function = 1 // SHA-1 - sha256 function = 2 // SHA-256 - sha512 function = 3 // SHA-512 - sha3_224 function = 32 // SHA3-224 - sha3_256 function = 33 // SHA3-256 - sha3_384 function = 34 // SHA3-384 - sha3_512 function = 35 // SHA3-512 - shake128 function = 36 // SHAKE-128 - shake256 function = 37 // SHAKE-256 - - // KLMD function codes - ghash function = 65 // GHASH -) - -// queryResult contains the result of a Query function -// call. Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type queryResult struct { - bits [2]uint64 -} - -// Has reports whether the given functions are present. -func (q *queryResult) Has(fns ...function) bool { - if len(fns) == 0 { - panic("no function codes provided") - } - for _, f := range fns { - if !bitIsSet(q.bits[:], uint(f)) { - return false - } - } - return true -} - -// facility is a bit index for the named facility. -type facility uint8 - -const ( - // cryptography facilities - msa4 facility = 77 // message-security-assist extension 4 - msa8 facility = 146 // message-security-assist extension 8 -) - -// facilityList contains the result of an STFLE call. -// Bits are numbered in big endian order so the -// leftmost bit (the MSB) is at index 0. -type facilityList struct { - bits [4]uint64 -} - -// Has reports whether the given facilities are present. -func (s *facilityList) Has(fs ...facility) bool { - if len(fs) == 0 { - panic("no facility bits provided") - } - for _, f := range fs { - if !bitIsSet(s.bits[:], uint(f)) { - return false - } - } - return true -} - -func doinit() { +func initS390Xbase() { // test HWCAP bit vector has := func(featureMask uint) bool { return hwCap&featureMask == featureMask @@ -116,44 +37,4 @@ func doinit() { if S390X.HasVX { S390X.HasVXE = has(hwcap_VXE) } - - // We need implementations of stfle, km and so on - // to detect cryptographic features. - if !haveAsmFunctions() { - return - } - - // optional cryptographic functions - if S390X.HasMSA { - aes := []function{aes128, aes192, aes256} - - // cipher message - km, kmc := kmQuery(), kmcQuery() - S390X.HasAES = km.Has(aes...) - S390X.HasAESCBC = kmc.Has(aes...) - if S390X.HasSTFLE { - facilities := stfle() - if facilities.Has(msa4) { - kmctr := kmctrQuery() - S390X.HasAESCTR = kmctr.Has(aes...) - } - if facilities.Has(msa8) { - kma := kmaQuery() - S390X.HasAESGCM = kma.Has(aes...) - } - } - - // compute message digest - kimd := kimdQuery() // intermediate (no padding) - klmd := klmdQuery() // last (padding) - S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) - S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) - S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) - S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist - sha3 := []function{ - sha3_224, sha3_256, sha3_384, sha3_512, - shake128, shake256, - } - S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) - } } diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go b/src/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go new file mode 100644 index 00000000000..ebfb3fc8e76 --- /dev/null +++ b/src/vendor/golang.org/x/sys/cpu/cpu_netbsd_arm64.go @@ -0,0 +1,173 @@ +// Copyright 2020 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 cpu + +import ( + "syscall" + "unsafe" +) + +// Minimal copy of functionality from x/sys/unix so the cpu package can call +// sysctl without depending on x/sys/unix. + +const ( + _CTL_QUERY = -2 + + _SYSCTL_VERS_1 = 0x1000000 +) + +var _zero uintptr + +func sysctl(mib []int32, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) { + var _p0 unsafe.Pointer + if len(mib) > 0 { + _p0 = unsafe.Pointer(&mib[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + _, _, errno := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(_p0), + uintptr(len(mib)), + uintptr(unsafe.Pointer(old)), + uintptr(unsafe.Pointer(oldlen)), + uintptr(unsafe.Pointer(new)), + uintptr(newlen)) + if errno != 0 { + return errno + } + return nil +} + +type sysctlNode struct { + Flags uint32 + Num int32 + Name [32]int8 + Ver uint32 + __rsvd uint32 + Un [16]byte + _sysctl_size [8]byte + _sysctl_func [8]byte + _sysctl_parent [8]byte + _sysctl_desc [8]byte +} + +func sysctlNodes(mib []int32) ([]sysctlNode, error) { + var olen uintptr + + // Get a list of all sysctl nodes below the given MIB by performing + // a sysctl for the given MIB with CTL_QUERY appended. + mib = append(mib, _CTL_QUERY) + qnode := sysctlNode{Flags: _SYSCTL_VERS_1} + qp := (*byte)(unsafe.Pointer(&qnode)) + sz := unsafe.Sizeof(qnode) + if err := sysctl(mib, nil, &olen, qp, sz); err != nil { + return nil, err + } + + // Now that we know the size, get the actual nodes. + nodes := make([]sysctlNode, olen/sz) + np := (*byte)(unsafe.Pointer(&nodes[0])) + if err := sysctl(mib, np, &olen, qp, sz); err != nil { + return nil, err + } + + return nodes, nil +} + +func nametomib(name string) ([]int32, error) { + // Split name into components. + var parts []string + last := 0 + for i := 0; i < len(name); i++ { + if name[i] == '.' { + parts = append(parts, name[last:i]) + last = i + 1 + } + } + parts = append(parts, name[last:]) + + mib := []int32{} + // Discover the nodes and construct the MIB OID. + for partno, part := range parts { + nodes, err := sysctlNodes(mib) + if err != nil { + return nil, err + } + for _, node := range nodes { + n := make([]byte, 0) + for i := range node.Name { + if node.Name[i] != 0 { + n = append(n, byte(node.Name[i])) + } + } + if string(n) == part { + mib = append(mib, int32(node.Num)) + break + } + } + if len(mib) != partno+1 { + return nil, err + } + } + + return mib, nil +} + +// aarch64SysctlCPUID is struct aarch64_sysctl_cpu_id from NetBSD's +type aarch64SysctlCPUID struct { + midr uint64 /* Main ID Register */ + revidr uint64 /* Revision ID Register */ + mpidr uint64 /* Multiprocessor Affinity Register */ + aa64dfr0 uint64 /* A64 Debug Feature Register 0 */ + aa64dfr1 uint64 /* A64 Debug Feature Register 1 */ + aa64isar0 uint64 /* A64 Instruction Set Attribute Register 0 */ + aa64isar1 uint64 /* A64 Instruction Set Attribute Register 1 */ + aa64mmfr0 uint64 /* A64 Memory Model Feature Register 0 */ + aa64mmfr1 uint64 /* A64 Memory Model Feature Register 1 */ + aa64mmfr2 uint64 /* A64 Memory Model Feature Register 2 */ + aa64pfr0 uint64 /* A64 Processor Feature Register 0 */ + aa64pfr1 uint64 /* A64 Processor Feature Register 1 */ + aa64zfr0 uint64 /* A64 SVE Feature ID Register 0 */ + mvfr0 uint32 /* Media and VFP Feature Register 0 */ + mvfr1 uint32 /* Media and VFP Feature Register 1 */ + mvfr2 uint32 /* Media and VFP Feature Register 2 */ + pad uint32 + clidr uint64 /* Cache Level ID Register */ + ctr uint64 /* Cache Type Register */ +} + +func sysctlCPUID(name string) (*aarch64SysctlCPUID, error) { + mib, err := nametomib(name) + if err != nil { + return nil, err + } + + out := aarch64SysctlCPUID{} + n := unsafe.Sizeof(out) + _, _, errno := syscall.Syscall6( + syscall.SYS___SYSCTL, + uintptr(unsafe.Pointer(&mib[0])), + uintptr(len(mib)), + uintptr(unsafe.Pointer(&out)), + uintptr(unsafe.Pointer(&n)), + uintptr(0), + uintptr(0)) + if errno != 0 { + return nil, errno + } + return &out, nil +} + +func doinit() { + cpuid, err := sysctlCPUID("machdep.cpu0.cpu_id") + if err != nil { + setMinimalFeatures() + return + } + parseARM64SystemRegisters(cpuid.aa64isar0, cpuid.aa64isar1, cpuid.aa64pfr0) + + Initialized = true +} diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go b/src/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go index 3ffc4afa03c..16c1c4090ee 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_other_arm64.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !linux,arm64 +// +build !linux,!netbsd +// +build arm64 package cpu diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go b/src/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go new file mode 100644 index 00000000000..f49fad67783 --- /dev/null +++ b/src/vendor/golang.org/x/sys/cpu/cpu_other_mips64x.go @@ -0,0 +1,12 @@ +// Copyright 2020 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. + +// +build !linux +// +build mips64 mips64le + +package cpu + +func archInit() { + Initialized = true +} diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_s390x.go b/src/vendor/golang.org/x/sys/cpu/cpu_s390x.go index 544cd621cee..5881b8833f5 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_s390x.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_s390x.go @@ -8,10 +8,10 @@ const cacheLineSize = 256 func initOptions() { options = []option{ - {Name: "zarch", Feature: &S390X.HasZARCH}, - {Name: "stfle", Feature: &S390X.HasSTFLE}, - {Name: "ldisp", Feature: &S390X.HasLDISP}, - {Name: "eimm", Feature: &S390X.HasEIMM}, + {Name: "zarch", Feature: &S390X.HasZARCH, Required: true}, + {Name: "stfle", Feature: &S390X.HasSTFLE, Required: true}, + {Name: "ldisp", Feature: &S390X.HasLDISP, Required: true}, + {Name: "eimm", Feature: &S390X.HasEIMM, Required: true}, {Name: "dfp", Feature: &S390X.HasDFP}, {Name: "etf3eh", Feature: &S390X.HasETF3EH}, {Name: "msa", Feature: &S390X.HasMSA}, @@ -28,3 +28,145 @@ func initOptions() { {Name: "vxe", Feature: &S390X.HasVXE}, } } + +// bitIsSet reports whether the bit at index is set. The bit index +// is in big endian order, so bit index 0 is the leftmost bit. +func bitIsSet(bits []uint64, index uint) bool { + return bits[index/64]&((1<<63)>>(index%64)) != 0 +} + +// facility is a bit index for the named facility. +type facility uint8 + +const ( + // mandatory facilities + zarch facility = 1 // z architecture mode is active + stflef facility = 7 // store-facility-list-extended + ldisp facility = 18 // long-displacement + eimm facility = 21 // extended-immediate + + // miscellaneous facilities + dfp facility = 42 // decimal-floating-point + etf3eh facility = 30 // extended-translation 3 enhancement + + // cryptography facilities + msa facility = 17 // message-security-assist + msa3 facility = 76 // message-security-assist extension 3 + msa4 facility = 77 // message-security-assist extension 4 + msa5 facility = 57 // message-security-assist extension 5 + msa8 facility = 146 // message-security-assist extension 8 + msa9 facility = 155 // message-security-assist extension 9 + + // vector facilities + vx facility = 129 // vector facility + vxe facility = 135 // vector-enhancements 1 + vxe2 facility = 148 // vector-enhancements 2 +) + +// facilityList contains the result of an STFLE call. +// Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type facilityList struct { + bits [4]uint64 +} + +// Has reports whether the given facilities are present. +func (s *facilityList) Has(fs ...facility) bool { + if len(fs) == 0 { + panic("no facility bits provided") + } + for _, f := range fs { + if !bitIsSet(s.bits[:], uint(f)) { + return false + } + } + return true +} + +// function is the code for the named cryptographic function. +type function uint8 + +const ( + // KM{,A,C,CTR} function codes + aes128 function = 18 // AES-128 + aes192 function = 19 // AES-192 + aes256 function = 20 // AES-256 + + // K{I,L}MD function codes + sha1 function = 1 // SHA-1 + sha256 function = 2 // SHA-256 + sha512 function = 3 // SHA-512 + sha3_224 function = 32 // SHA3-224 + sha3_256 function = 33 // SHA3-256 + sha3_384 function = 34 // SHA3-384 + sha3_512 function = 35 // SHA3-512 + shake128 function = 36 // SHAKE-128 + shake256 function = 37 // SHAKE-256 + + // KLMD function codes + ghash function = 65 // GHASH +) + +// queryResult contains the result of a Query function +// call. Bits are numbered in big endian order so the +// leftmost bit (the MSB) is at index 0. +type queryResult struct { + bits [2]uint64 +} + +// Has reports whether the given functions are present. +func (q *queryResult) Has(fns ...function) bool { + if len(fns) == 0 { + panic("no function codes provided") + } + for _, f := range fns { + if !bitIsSet(q.bits[:], uint(f)) { + return false + } + } + return true +} + +func doinit() { + initS390Xbase() + + // We need implementations of stfle, km and so on + // to detect cryptographic features. + if !haveAsmFunctions() { + return + } + + // optional cryptographic functions + if S390X.HasMSA { + aes := []function{aes128, aes192, aes256} + + // cipher message + km, kmc := kmQuery(), kmcQuery() + S390X.HasAES = km.Has(aes...) + S390X.HasAESCBC = kmc.Has(aes...) + if S390X.HasSTFLE { + facilities := stfle() + if facilities.Has(msa4) { + kmctr := kmctrQuery() + S390X.HasAESCTR = kmctr.Has(aes...) + } + if facilities.Has(msa8) { + kma := kmaQuery() + S390X.HasAESGCM = kma.Has(aes...) + } + } + + // compute message digest + kimd := kimdQuery() // intermediate (no padding) + klmd := klmdQuery() // last (padding) + S390X.HasSHA1 = kimd.Has(sha1) && klmd.Has(sha1) + S390X.HasSHA256 = kimd.Has(sha256) && klmd.Has(sha256) + S390X.HasSHA512 = kimd.Has(sha512) && klmd.Has(sha512) + S390X.HasGHASH = kimd.Has(ghash) // KLMD-GHASH does not exist + sha3 := []function{ + sha3_224, sha3_256, sha3_384, sha3_512, + shake128, shake256, + } + S390X.HasSHA3 = kimd.Has(sha3...) && klmd.Has(sha3...) + } +} diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_x86.go b/src/vendor/golang.org/x/sys/cpu/cpu_x86.go index 2ad039d40eb..48d42933195 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_x86.go +++ b/src/vendor/golang.org/x/sys/cpu/cpu_x86.go @@ -16,6 +16,26 @@ func initOptions() { {Name: "aes", Feature: &X86.HasAES}, {Name: "avx", Feature: &X86.HasAVX}, {Name: "avx2", Feature: &X86.HasAVX2}, + {Name: "avx512", Feature: &X86.HasAVX512}, + {Name: "avx512f", Feature: &X86.HasAVX512F}, + {Name: "avx512cd", Feature: &X86.HasAVX512CD}, + {Name: "avx512er", Feature: &X86.HasAVX512ER}, + {Name: "avx512pf", Feature: &X86.HasAVX512PF}, + {Name: "avx512vl", Feature: &X86.HasAVX512VL}, + {Name: "avx512bw", Feature: &X86.HasAVX512BW}, + {Name: "avx512dq", Feature: &X86.HasAVX512DQ}, + {Name: "avx512ifma", Feature: &X86.HasAVX512IFMA}, + {Name: "avx512vbmi", Feature: &X86.HasAVX512VBMI}, + {Name: "avx512vnniw", Feature: &X86.HasAVX5124VNNIW}, + {Name: "avx5124fmaps", Feature: &X86.HasAVX5124FMAPS}, + {Name: "avx512vpopcntdq", Feature: &X86.HasAVX512VPOPCNTDQ}, + {Name: "avx512vpclmulqdq", Feature: &X86.HasAVX512VPCLMULQDQ}, + {Name: "avx512vnni", Feature: &X86.HasAVX512VNNI}, + {Name: "avx512gfni", Feature: &X86.HasAVX512GFNI}, + {Name: "avx512vaes", Feature: &X86.HasAVX512VAES}, + {Name: "avx512vbmi2", Feature: &X86.HasAVX512VBMI2}, + {Name: "avx512bitalg", Feature: &X86.HasAVX512BITALG}, + {Name: "avx512bf16", Feature: &X86.HasAVX512BF16}, {Name: "bmi1", Feature: &X86.HasBMI1}, {Name: "bmi2", Feature: &X86.HasBMI2}, {Name: "erms", Feature: &X86.HasERMS}, @@ -59,12 +79,15 @@ func archInit() { X86.HasOSXSAVE = isSet(27, ecx1) X86.HasRDRAND = isSet(30, ecx1) - osSupportsAVX := false + var osSupportsAVX, osSupportsAVX512 bool // For XGETBV, OSXSAVE bit is required and sufficient. if X86.HasOSXSAVE { eax, _ := xgetbv() // Check if XMM and YMM registers have OS support. osSupportsAVX = isSet(1, eax) && isSet(2, eax) + + // Check if OPMASK and ZMM registers have OS support. + osSupportsAVX512 = osSupportsAVX && isSet(5, eax) && isSet(6, eax) && isSet(7, eax) } X86.HasAVX = isSet(28, ecx1) && osSupportsAVX @@ -73,7 +96,7 @@ func archInit() { return } - _, ebx7, _, _ := cpuid(7, 0) + _, ebx7, ecx7, edx7 := cpuid(7, 0) X86.HasBMI1 = isSet(3, ebx7) X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX X86.HasBMI2 = isSet(8, ebx7) @@ -81,6 +104,30 @@ func archInit() { X86.HasRDSEED = isSet(18, ebx7) X86.HasADX = isSet(19, ebx7) + X86.HasAVX512 = isSet(16, ebx7) && osSupportsAVX512 // Because avx-512 foundation is the core required extension + if X86.HasAVX512 { + X86.HasAVX512F = true + X86.HasAVX512CD = isSet(28, ebx7) + X86.HasAVX512ER = isSet(27, ebx7) + X86.HasAVX512PF = isSet(26, ebx7) + X86.HasAVX512VL = isSet(31, ebx7) + X86.HasAVX512BW = isSet(30, ebx7) + X86.HasAVX512DQ = isSet(17, ebx7) + X86.HasAVX512IFMA = isSet(21, ebx7) + X86.HasAVX512VBMI = isSet(1, ecx7) + X86.HasAVX5124VNNIW = isSet(2, edx7) + X86.HasAVX5124FMAPS = isSet(3, edx7) + X86.HasAVX512VPOPCNTDQ = isSet(14, ecx7) + X86.HasAVX512VPCLMULQDQ = isSet(10, ecx7) + X86.HasAVX512VNNI = isSet(11, ecx7) + X86.HasAVX512GFNI = isSet(8, ecx7) + X86.HasAVX512VAES = isSet(9, ecx7) + X86.HasAVX512VBMI2 = isSet(6, ecx7) + X86.HasAVX512BITALG = isSet(12, ecx7) + + eax71, _, _, _ := cpuid(7, 1) + X86.HasAVX512BF16 = isSet(5, eax71) + } } func isSet(bitpos uint, value uint32) bool { diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_zos.go b/src/vendor/golang.org/x/sys/cpu/cpu_zos.go new file mode 100644 index 00000000000..5f54683a22e --- /dev/null +++ b/src/vendor/golang.org/x/sys/cpu/cpu_zos.go @@ -0,0 +1,10 @@ +// Copyright 2020 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 cpu + +func archInit() { + doinit() + Initialized = true +} diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go b/src/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go new file mode 100644 index 00000000000..ccb1b708aba --- /dev/null +++ b/src/vendor/golang.org/x/sys/cpu/cpu_zos_s390x.go @@ -0,0 +1,25 @@ +// Copyright 2020 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 cpu + +func initS390Xbase() { + // get the facilities list + facilities := stfle() + + // mandatory + S390X.HasZARCH = facilities.Has(zarch) + S390X.HasSTFLE = facilities.Has(stflef) + S390X.HasLDISP = facilities.Has(ldisp) + S390X.HasEIMM = facilities.Has(eimm) + + // optional + S390X.HasETF3EH = facilities.Has(etf3eh) + S390X.HasDFP = facilities.Has(dfp) + S390X.HasMSA = facilities.Has(msa) + S390X.HasVX = facilities.Has(vx) + if S390X.HasVX { + S390X.HasVXE = facilities.Has(vxe) + } +} diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 36d76e77b5e..9c4f479c0d8 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -18,7 +18,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d +# golang.org/x/sys v0.0.0-20201101102859-da207088b7d1 ## explicit golang.org/x/sys/cpu # golang.org/x/text v0.3.4-0.20200826142016-a8b467125457 From 05e6d28849293266028c0bc9e9b0f8d0da38a2e2 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 1 Nov 2020 17:48:42 -0500 Subject: [PATCH 324/403] runtime: default to MADV_DONTNEED on Linux In Go 1.12, we changed the runtime to use MADV_FREE when available on Linux (falling back to MADV_DONTNEED) in CL 135395 to address issue #23687. While MADV_FREE is somewhat faster than MADV_DONTNEED, it doesn't affect many of the statistics that MADV_DONTNEED does until the memory is actually reclaimed under OS memory pressure. This generally leads to poor user experience, like confusing stats in top and other monitoring tools; and bad integration with management systems that respond to memory usage. We've seen numerous issues about this user experience, including #41818, #39295, #37585, #33376, and #30904, many questions on Go mailing lists, and requests for mechanisms to change this behavior at run-time, such as #40870. There are also issues that may be a result of this, but root-causing it can be difficult, such as #41444 and #39174. And there's some evidence it may even be incompatible with Android's process management in #37569. This CL changes the default to prefer MADV_DONTNEED over MADV_FREE, to favor user-friendliness and minimal surprise over performance. I think it's become clear that Linux's implementation of MADV_FREE ultimately doesn't meet our needs. We've also made many improvements to the scavenger since Go 1.12. In particular, it is now far more prompt and it is self-paced, so it will simply trickle memory back to the system a little more slowly with this change. This can still be overridden by setting GODEBUG=madvdontneed=0. Fixes #42330 (meta-issue). Fixes #41818, #39295, #37585, #33376, #30904 (many of which were already closed as "working as intended"). Change-Id: Ib6aa7f2dc8419b32516cc5a5fc402faf576c92e4 Reviewed-on: https://go-review.googlesource.com/c/go/+/267100 Trust: Austin Clements Reviewed-by: Michael Knyszek --- src/runtime/extern.go | 8 ++++---- src/runtime/runtime1.go | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/runtime/extern.go b/src/runtime/extern.go index b75507b8f85..dacdf4f3830 100644 --- a/src/runtime/extern.go +++ b/src/runtime/extern.go @@ -91,10 +91,10 @@ It is a comma-separated list of name=val pairs setting these named variables: # bytes memory allocated on the heap # allocs number of heap allocations - madvdontneed: setting madvdontneed=1 will use MADV_DONTNEED - instead of MADV_FREE on Linux when returning memory to the - kernel. This is less efficient, but causes RSS numbers to drop - more quickly. + madvdontneed: setting madvdontneed=0 will use MADV_FREE + instead of MADV_DONTNEED on Linux when returning memory to the + kernel. This is more efficient, but means RSS numbers will + drop only when the OS is under memory pressure. memprofilerate: setting memprofilerate=X will update the value of runtime.MemProfileRate. When set to 0 memory profiling is disabled. Refer to the description of diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index 0f182ac58e6..30b7044bffc 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -352,6 +352,17 @@ func parsedebugvars() { // defaults debug.cgocheck = 1 debug.invalidptr = 1 + if GOOS == "linux" { + // On Linux, MADV_FREE is faster than MADV_DONTNEED, + // but doesn't affect many of the statistics that + // MADV_DONTNEED does until the memory is actually + // reclaimed. This generally leads to poor user + // experience, like confusing stats in top and other + // monitoring tools; and bad integration with + // management systems that respond to memory usage. + // Hence, default to MADV_DONTNEED. + debug.madvdontneed = 1 + } for p := gogetenv("GODEBUG"); p != ""; { field := "" From d1efaed17a7a4bf4b2dd8a8f975069dfd8251ca4 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 2 Nov 2020 19:19:12 +0000 Subject: [PATCH 325/403] cmd/go: support cgo files in overlays This is a roll-forward of golang.org/cl/262618, which was reverted in golang.org/cl/267037. The only differences between this CL and the original are the three calls to fflush from the C files in build_overlay.txt, to guarantee that the string we're expecting is actually written out. This requires rewriting the paths of the files passed to the cgo tool toolchain to use the overlaid paths instead of the disk paths of files. Because the directories of the overlaid paths don't exist in general, the cgo tool have been updated to run in base.Cwd instead of the package directory. For #39958 Change-Id: If7e5e057c62c0c22ddb724f9fe650902fc5f4832 Reviewed-on: https://go-review.googlesource.com/c/go/+/267197 Reviewed-by: Bryan C. Mills Trust: Michael Matloob --- src/cmd/go/internal/work/exec.go | 48 +++++++++-- src/cmd/go/internal/work/gc.go | 9 +- src/cmd/go/testdata/script/build_overlay.txt | 83 ++++++++++++++++++- .../go/testdata/script/build_trimpath_cgo.txt | 28 +++++++ 4 files changed, 156 insertions(+), 12 deletions(-) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 838b00a00d2..a1a357e2acc 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -8,6 +8,7 @@ package work import ( "bytes" + "cmd/go/internal/fsys" "context" "encoding/json" "errors" @@ -2242,8 +2243,6 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s // when -trimpath is enabled. if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") { if cfg.BuildTrimpath { - // TODO(#39958): handle overlays - // Keep in sync with Action.trimpath. // The trimmed paths are a little different, but we need to trim in the // same situations. @@ -2313,7 +2312,8 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag cmdargs := []interface{}{cmd, "-o", outfile, objs, flags} dir := p.Dir - out, err := b.runOut(a, dir, b.cCompilerEnv(), cmdargs...) + out, err := b.runOut(a, base.Cwd, b.cCompilerEnv(), cmdargs...) + if len(out) > 0 { // Filter out useless linker warnings caused by bugs outside Go. // See also cmd/link/internal/ld's hostlink method. @@ -2641,7 +2641,8 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...) } - // Allows including _cgo_export.h from .[ch] files in the package. + // Allows including _cgo_export.h, as well as the user's .h files, + // from .[ch] files in the package. cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", objdir) // cgo @@ -2654,6 +2655,8 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cfiles = append(cfiles, f+".cgo2.c") } + hfiles := append([]string{}, p.HFiles...) + // TODO: make cgo not depend on $GOARCH? cgoflags := []string{} @@ -2698,7 +2701,38 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h") } - if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { + execdir := p.Dir + + // If any of the Cgo, C, or H files are overlaid, copy them all to + // objdir to ensure that they refer to the right header files. + // TODO(#39958): Ideally, we'd always do this, but this could + // subtly break some cgo files that include .h files across directory + // boundaries, even though they shouldn't. + hasOverlay := false + cgoFileLists := [][]string{cgofiles, gccfiles, gxxfiles, mfiles, ffiles, hfiles} +OverlayLoop: + for _, fs := range cgoFileLists { + for _, f := range fs { + if _, ok := fsys.OverlayPath(mkAbs(p.Dir, f)); ok { + hasOverlay = true + break OverlayLoop + } + } + } + if hasOverlay { + execdir = objdir + for _, fs := range cgoFileLists { + for i := range fs { + opath, _ := fsys.OverlayPath(mkAbs(p.Dir, fs[i])) + fs[i] = objdir + filepath.Base(fs[i]) + if err := b.copyFile(fs[i], opath, 0666, false); err != nil { + return nil, nil, err + } + } + } + } + + if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { return nil, nil, err } outGo = append(outGo, gofiles...) @@ -2792,7 +2826,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe return err } - linkobj := str.StringList(ofile, outObj, p.SysoFiles) + linkobj := str.StringList(ofile, outObj, mkAbsFiles(p.Dir, p.SysoFiles)) dynobj := objdir + "_cgo_.o" // we need to use -pie for Linux/ARM to get accurate imported sym @@ -2817,7 +2851,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = []string{"-dynlinker"} // record path to dynamic linker } - return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + return b.run(a, base.Cwd, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) } // Run SWIG on all SWIG input files. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index e79173485db..4ba9be78296 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -262,7 +262,7 @@ func (a *Action) trimpath() string { if len(objdir) > 1 && objdir[len(objdir)-1] == filepath.Separator { objdir = objdir[:len(objdir)-1] } - rewrite := objdir + "=>" + rewrite := "" rewriteDir := a.Package.Dir if cfg.BuildTrimpath { @@ -271,7 +271,7 @@ func (a *Action) trimpath() string { } else { rewriteDir = a.Package.ImportPath } - rewrite += ";" + a.Package.Dir + "=>" + rewriteDir + rewrite += a.Package.Dir + "=>" + rewriteDir + ";" } // Add rewrites for overlays. The 'from' and 'to' paths in overlays don't need to have @@ -280,11 +280,14 @@ func (a *Action) trimpath() string { if fsys.OverlayFile != "" { for _, filename := range a.Package.AllFiles() { overlayPath, ok := fsys.OverlayPath(filepath.Join(a.Package.Dir, filename)) + rewrite += filepath.Join(objdir, filename) + "=>" + filepath.Join(rewriteDir, filename) + ";" if !ok { continue } - rewrite += ";" + overlayPath + "=>" + filepath.Join(rewriteDir, filename) + rewrite += overlayPath + "=>" + filepath.Join(rewriteDir, filename) + ";" } + } else { + rewrite += objdir + "=>" } return rewrite diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt index 0602e706e9e..be473a85db9 100644 --- a/src/cmd/go/testdata/script/build_overlay.txt +++ b/src/cmd/go/testdata/script/build_overlay.txt @@ -1,9 +1,11 @@ [short] skip # Test building in overlays. -# TODO(matloob): add a test case where the destination file in the replace map +# TODO(#39958): add a test case where the destination file in the replace map # isn't a go file. Either completely exclude that case in fs.IsDirWithGoFiles # if the compiler doesn't allow it, or test that it works all the way. +# TODO(#39958): add a test that both gc and gccgo assembly files can include .h +# files. # The main package (m) is contained in an overlay. It imports m/dir2 which has one # file in an overlay and one file outside the overlay, which in turn imports m/dir, @@ -29,6 +31,18 @@ exec ./print_trimpath_two_files$GOEXE stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go +go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace +exec ./main_cgo_replace$GOEXE +stdout '^hello cgo$' + +go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote +exec ./main_cgo_quote$GOEXE +stdout '^hello cgo$' + +go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle +exec ./main_cgo_angle$GOEXE +stdout '^hello cgo$' + # Run same tests but with gccgo. env GO111MODULE=off [!exec:gccgo] stop @@ -46,6 +60,19 @@ go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -tr exec ./print_trimpath_gccgo$GOEXE stdout ^\.[/\\]printpath[/\\]main.go + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_replace_gccgo$GOEXE ./cgo_hello_replace +exec ./main_cgo_replace_gccgo$GOEXE +stdout '^hello cgo$' + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_quote_gccgo$GOEXE ./cgo_hello_quote +exec ./main_cgo_quote_gccgo$GOEXE +stdout '^hello cgo$' + +go build -compiler=gccgo -overlay overlay.json -o main_cgo_angle_gccgo$GOEXE ./cgo_hello_angle +exec ./main_cgo_angle_gccgo$GOEXE +stdout '^hello cgo$' + -- m/go.mod -- // TODO(matloob): how do overlays work with go.mod (especially if mod=readonly) module m @@ -71,9 +98,32 @@ the actual code is in the overlay "dir/g.go": "overlay/dir_g.go", "dir2/i.go": "overlay/dir2_i.go", "printpath/main.go": "overlay/printpath.go", - "printpath/other.go": "overlay2/printpath2.go" + "printpath/other.go": "overlay2/printpath2.go", + "cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h", + "cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go", + "cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h", + "cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go", + "cgo_hello_angle/cgo_header.h": "overlay/cgo_head.h" } } +-- m/cgo_hello_replace/cgo_hello_replace.go -- +package main + +// #include "cgo_header.h" +import "C" + +func main() { + C.say_hello() +} +-- m/cgo_hello_replace/cgo_header.h -- + // Test that this header is replaced with one that has the proper declaration. +void say_goodbye(); + +-- m/cgo_hello_replace/goodbye.c -- +#include + +void say_hello() { puts("hello cgo\n"); fflush(stdout); } + -- m/overlay/f.go -- package main @@ -128,3 +178,32 @@ import "m/dir" func printMessage() { dir.PrintMessage() } +-- m/overlay/cgo_hello_quote.go -- +package main + +// #include "cgo_header.h" +import "C" + +func main() { + C.say_hello() +} +-- m/overlay/cgo_hello_angle.go -- +package main + +// #include +import "C" + +func main() { + C.say_hello() +} +-- m/overlay/cgo_head.h -- +void say_hello(); +-- m/cgo_hello_quote/hello.c -- +#include + +void say_hello() { puts("hello cgo\n"); fflush(stdout); } +-- m/cgo_hello_angle/hello.c -- +#include + +void say_hello() { puts("hello cgo\n"); fflush(stdout); } + diff --git a/src/cmd/go/testdata/script/build_trimpath_cgo.txt b/src/cmd/go/testdata/script/build_trimpath_cgo.txt index 4608d9ac6bf..3187b4d6439 100644 --- a/src/cmd/go/testdata/script/build_trimpath_cgo.txt +++ b/src/cmd/go/testdata/script/build_trimpath_cgo.txt @@ -20,10 +20,38 @@ go build -trimpath -o hello.exe . go run ./list-dwarf hello.exe ! stdout gopath/src + +# Do the above, with the cgo (but not .c) sources in an overlay +# Check that the source path appears when -trimpath is not used. +mkdir $WORK/overlay +cp hello.go $WORK/overlay/hello.go +mkdir hello_overlay +cp hello.c hello_overlay/hello.c +go build -overlay overlay.json -o hello_overlay.exe ./hello_overlay +grep -q gopath[/\\]src hello_overlay.exe +! grep -q $WORK[/\\]overlay hello_overlay.exe +go run ./list-dwarf hello_overlay.exe +stdout gopath[/\\]src +! stdout $WORK[/\\]overlay + +# Check that the source path does not appear when -trimpath is used. +go build -overlay overlay.json -trimpath -o hello_overlay.exe ./hello_overlay +! grep -q gopath[/\\]src hello_overlay.exe +! grep -q $WORK[/\\]overlay hello_overlay.exe +go run ./list-dwarf hello_overlay.exe +! stdout gopath/src +! stdout $WORK[/\\]overlay + -- go.mod -- module m go 1.14 +-- overlay.json -- +{ + "Replace": { + "hello_overlay/hello.go": "../../overlay/hello.go" + } +} -- hello.c -- #include From 4fcb5068f6aa907166535531862cfd4a3dec6be7 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 2 Nov 2020 11:43:50 -0500 Subject: [PATCH 326/403] doc/go1.16: document switch to MADV_DONTNEED Updates #42330. Change-Id: Ifda10a5c3dca30acf1258e9e0af202e9beffc68e Reviewed-on: https://go-review.googlesource.com/c/go/+/267137 Trust: Austin Clements Reviewed-by: Michael Knyszek --- doc/go1.16.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/go1.16.html b/doc/go1.16.html index 3592d0b6631..5d293078861 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -161,6 +161,18 @@ Do not send CLs removing the interior tags from such phrases. TODO

+

+ On Linux, the runtime now defaults to releasing memory to the + operating system promptly (using MADV_DONTNEED), rather + than lazily when the operating system is under memory pressure + (using MADV_FREE). This means process-level memory + statistics like RSS will more accurately reflect the amount of + physical memory being used by Go processes. Systems that are + currently using GODEBUG=madvdontneed=1 to improve + memory monitoring behavior no longer need to set this environment + variable. +

+

Compiler

From ac766e37182f36cd0a3247e44a4143d2d2132e42 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 2 Nov 2020 16:58:38 +0000 Subject: [PATCH 327/403] runtime: make getMCache inlineable This change moves the responsibility of throwing if an mcache is not available to the caller, because the inlining cost of throw is set very high in the compiler. Even if it was reduced down to the cost of a usual function call, it would still be too expensive, so just move it out. This choice also makes sense in the context of #42339 since we're going to have to handle the case where we don't have an mcache to update stats in a few contexts anyhow. Also, add getMCache to the list of functions that should be inlined to prevent future regressions. getMCache is called on the allocation fast path and because its not inlined actually causes a significant regression (~10%) in some microbenchmarks. Fixes #42305. Change-Id: I64ac5e4f26b730bd4435ea1069a4a50f55411ced Reviewed-on: https://go-review.googlesource.com/c/go/+/267157 Trust: Michael Knyszek Run-TryBot: Michael Knyszek Reviewed-by: Michael Pratt TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/inl_test.go | 1 + src/runtime/malloc.go | 9 ++++++++- src/runtime/mcache.go | 7 ++----- src/runtime/mgcscavenge.go | 3 +++ src/runtime/mheap.go | 12 ++++++++++++ 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl_test.go b/src/cmd/compile/internal/gc/inl_test.go index afa6b983151..02735e50fb7 100644 --- a/src/cmd/compile/internal/gc/inl_test.go +++ b/src/cmd/compile/internal/gc/inl_test.go @@ -51,6 +51,7 @@ func TestIntendedInlining(t *testing.T) { "funcPC", "getArgInfoFast", "getm", + "getMCache", "isDirectIface", "itabHashFunc", "noescape", diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 4b798d129c3..551acd07969 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -975,6 +975,9 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer { shouldhelpgc := false dataSize := size c := getMCache() + if c == nil { + throw("mallocgc called without a P or outside bootstrapping") + } var span *mspan var x unsafe.Pointer noscan := typ == nil || typ.ptrdata == 0 @@ -1202,7 +1205,11 @@ func reflect_unsafe_NewArray(typ *_type, n int) unsafe.Pointer { } func profilealloc(mp *m, x unsafe.Pointer, size uintptr) { - getMCache().nextSample = nextSample() + c := getMCache() + if c == nil { + throw("profilealloc called without a P or outside bootstrapping") + } + c.nextSample = nextSample() mProf_Malloc(x, size) } diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go index c9342a41c9c..847a5dedf31 100644 --- a/src/runtime/mcache.go +++ b/src/runtime/mcache.go @@ -124,8 +124,8 @@ func freemcache(c *mcache) { // getMCache is a convenience function which tries to obtain an mcache. // -// Must be running with a P when called (so the caller must be in a -// non-preemptible state) or must be called during bootstrapping. +// Returns nil if we're not bootstrapping or we don't have a P. The caller's +// P must not change, so we must be in a non-preemptible state. func getMCache() *mcache { // Grab the mcache, since that's where stats live. pp := getg().m.p.ptr() @@ -136,9 +136,6 @@ func getMCache() *mcache { // mcache0 is cleared when bootstrapping is complete, // by procresize. c = mcache0 - if c == nil { - throw("getMCache called with no P or outside bootstrapping") - } } else { c = pp.mcache } diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index a242577bd9f..ab4e28a60b1 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -734,6 +734,9 @@ func (p *pageAlloc) scavengeRangeLocked(ci chunkIdx, base, npages uint) uintptr // Update consistent accounting too. c := getMCache() + if c == nil { + throw("scavengeRangeLocked called without a P or outside bootstrapping") + } stats := memstats.heapStats.acquire(c) atomic.Xaddint64(&stats.committed, -nbytes) atomic.Xaddint64(&stats.released, nbytes) diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 66a59cb999a..6b29f34a823 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -1247,6 +1247,10 @@ HaveSpan: } // Update consistent stats. c := getMCache() + if c == nil { + // TODO(mknyszek): Remove this and handle this case to fix #42339. + throw("allocSpan called without P or outside bootstrapping") + } stats := memstats.heapStats.acquire(c) atomic.Xaddint64(&stats.committed, int64(scav)) atomic.Xaddint64(&stats.released, -int64(scav)) @@ -1341,6 +1345,10 @@ func (h *mheap) grow(npage uintptr) bool { // just add directly to heap_released. atomic.Xadd64(&memstats.heap_released, int64(asize)) c := getMCache() + if c == nil { + // TODO(mknyszek): Remove this and handle this case to fix #42339. + throw("grow called without P or outside bootstrapping") + } stats := memstats.heapStats.acquire(c) atomic.Xaddint64(&stats.released, int64(asize)) memstats.heapStats.release(c) @@ -1440,6 +1448,10 @@ func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { } // Update consistent stats. c := getMCache() + if c == nil { + // TODO(mknyszek): Remove this and handle this case to fix #42339. + throw("freeSpanLocked called without P or outside bootstrapping") + } stats := memstats.heapStats.acquire(c) switch typ { case spanAllocHeap: From 39a5ee52b9b41b1e4f4cf821c78ef5b7be68d181 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Mon, 2 Nov 2020 19:03:16 +0000 Subject: [PATCH 328/403] runtime: decouple consistent stats from mcache and allow P-less update This change modifies the consistent stats implementation to keep the per-P sequence counter on each P instead of each mcache. A valid mcache is not available everywhere that we want to call e.g. allocSpan, as per issue #42339. By decoupling these two, we can add a mechanism to allow contexts without a P to update stats consistently. In this CL, we achieve that with a mutex. In practice, it will be very rare for an M to update these stats without a P. Furthermore, the stats reader also only needs to hold the mutex across the update to "gen" since once that changes, writers are free to continue updating the new stats generation. Contention could thus only arise between writers without a P, and as mentioned earlier, those should be rare. A nice side-effect of this change is that the consistent stats acquire and release API becomes simpler. Fixes #42339. Change-Id: Ied74ab256f69abd54b550394c8ad7c4c40a5fe34 Reviewed-on: https://go-review.googlesource.com/c/go/+/267158 Run-TryBot: Michael Knyszek Trust: Michael Knyszek Reviewed-by: Michael Pratt --- src/runtime/mcache.go | 16 +++---- src/runtime/mgcscavenge.go | 8 +--- src/runtime/mgcsweep.go | 10 ++-- src/runtime/mheap.go | 27 +++-------- src/runtime/mstats.go | 95 ++++++++++++++++++++++++-------------- src/runtime/proc.go | 4 ++ src/runtime/runtime2.go | 8 +++- 7 files changed, 88 insertions(+), 80 deletions(-) diff --git a/src/runtime/mcache.go b/src/runtime/mcache.go index 847a5dedf31..bb7475b6f36 100644 --- a/src/runtime/mcache.go +++ b/src/runtime/mcache.go @@ -50,10 +50,6 @@ type mcache struct { // in this mcache are stale and need to the flushed so they // can be swept. This is done in acquirep. flushGen uint32 - - // statsSeq is a counter indicating whether this P is currently - // writing any stats. Its value is even when not, odd when it is. - statsSeq uint32 } // A gclink is a node in a linked list of blocks, like mlink, @@ -178,9 +174,9 @@ func (c *mcache) refill(spc spanClass) { // Assume all objects from this span will be allocated in the // mcache. If it gets uncached, we'll adjust this. - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xadduintptr(&stats.smallAllocCount[spc.sizeclass()], uintptr(s.nelems)-uintptr(s.allocCount)) - memstats.heapStats.release(c) + memstats.heapStats.release() // Update heap_live with the same assumption. usedBytes := uintptr(s.allocCount) * s.elemsize @@ -229,10 +225,10 @@ func (c *mcache) allocLarge(size uintptr, needzero bool, noscan bool) *mspan { if s == nil { throw("out of memory") } - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xadduintptr(&stats.largeAlloc, npages*pageSize) atomic.Xadduintptr(&stats.largeAllocCount, 1) - memstats.heapStats.release(c) + memstats.heapStats.release() // Update heap_live and revise pacing if needed. atomic.Xadd64(&memstats.heap_live, int64(npages*pageSize)) @@ -263,9 +259,9 @@ func (c *mcache) releaseAll() { if s != &emptymspan { // Adjust nsmallalloc in case the span wasn't fully allocated. n := uintptr(s.nelems) - uintptr(s.allocCount) - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xadduintptr(&stats.smallAllocCount[spanClass(i).sizeclass()], -n) - memstats.heapStats.release(c) + memstats.heapStats.release() if s.sweepgen != sg+1 { // refill conservatively counted unallocated slots in heap_live. // Undo this. diff --git a/src/runtime/mgcscavenge.go b/src/runtime/mgcscavenge.go index ab4e28a60b1..38f09309dc8 100644 --- a/src/runtime/mgcscavenge.go +++ b/src/runtime/mgcscavenge.go @@ -733,14 +733,10 @@ func (p *pageAlloc) scavengeRangeLocked(ci chunkIdx, base, npages uint) uintptr atomic.Xadd64(&memstats.heap_released, nbytes) // Update consistent accounting too. - c := getMCache() - if c == nil { - throw("scavengeRangeLocked called without a P or outside bootstrapping") - } - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xaddint64(&stats.committed, -nbytes) atomic.Xaddint64(&stats.released, nbytes) - memstats.heapStats.release(c) + memstats.heapStats.release() return addr } diff --git a/src/runtime/mgcsweep.go b/src/runtime/mgcsweep.go index 83914356301..76bc4246e59 100644 --- a/src/runtime/mgcsweep.go +++ b/src/runtime/mgcsweep.go @@ -339,8 +339,6 @@ func (s *mspan) sweep(preserve bool) bool { spc := s.spanclass size := s.elemsize - c := _g_.m.p.ptr().mcache - // The allocBits indicate which unmarked objects don't need to be // processed since they were free at the end of the last GC cycle // and were not allocated since then. @@ -505,9 +503,9 @@ func (s *mspan) sweep(preserve bool) bool { // wasn't totally filled, but then swept, still has all of its // free slots zeroed. s.needzero = 1 - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xadduintptr(&stats.smallFreeCount[spc.sizeclass()], uintptr(nfreed)) - memstats.heapStats.release(c) + memstats.heapStats.release() } if !preserve { // The caller may not have removed this span from whatever @@ -552,10 +550,10 @@ func (s *mspan) sweep(preserve bool) bool { } else { mheap_.freeSpan(s) } - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xadduintptr(&stats.largeFreeCount, 1) atomic.Xadduintptr(&stats.largeFree, size) - memstats.heapStats.release(c) + memstats.heapStats.release() return true } diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index 6b29f34a823..b8429eee948 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -1246,12 +1246,7 @@ HaveSpan: memstats.heap_sys.add(-int64(nbytes)) } // Update consistent stats. - c := getMCache() - if c == nil { - // TODO(mknyszek): Remove this and handle this case to fix #42339. - throw("allocSpan called without P or outside bootstrapping") - } - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xaddint64(&stats.committed, int64(scav)) atomic.Xaddint64(&stats.released, -int64(scav)) switch typ { @@ -1264,7 +1259,7 @@ HaveSpan: case spanAllocWorkBuf: atomic.Xaddint64(&stats.inWorkBufs, int64(nbytes)) } - memstats.heapStats.release(c) + memstats.heapStats.release() // Publish the span in various locations. @@ -1344,14 +1339,9 @@ func (h *mheap) grow(npage uintptr) bool { // size which is always > physPageSize, so its safe to // just add directly to heap_released. atomic.Xadd64(&memstats.heap_released, int64(asize)) - c := getMCache() - if c == nil { - // TODO(mknyszek): Remove this and handle this case to fix #42339. - throw("grow called without P or outside bootstrapping") - } - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() atomic.Xaddint64(&stats.released, int64(asize)) - memstats.heapStats.release(c) + memstats.heapStats.release() // Recalculate nBase. // We know this won't overflow, because sysAlloc returned @@ -1447,12 +1437,7 @@ func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { memstats.heap_sys.add(int64(nbytes)) } // Update consistent stats. - c := getMCache() - if c == nil { - // TODO(mknyszek): Remove this and handle this case to fix #42339. - throw("freeSpanLocked called without P or outside bootstrapping") - } - stats := memstats.heapStats.acquire(c) + stats := memstats.heapStats.acquire() switch typ { case spanAllocHeap: atomic.Xaddint64(&stats.inHeap, -int64(nbytes)) @@ -1463,7 +1448,7 @@ func (h *mheap) freeSpanLocked(s *mspan, typ spanAllocType) { case spanAllocWorkBuf: atomic.Xaddint64(&stats.inWorkBufs, -int64(nbytes)) } - memstats.heapStats.release(c) + memstats.heapStats.release() // Mark the space as free. h.pages.free(s.base(), s.npages) diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index 3829355d7b4..6defaedabe0 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -158,7 +158,7 @@ type mstats struct { // heapStats is a set of statistics heapStats consistentHeapStats - _ uint32 // ensure gcPauseDist is aligned + // _ uint32 // ensure gcPauseDist is aligned // gcPauseDist represents the distribution of all GC-related // application pauses in the runtime. @@ -818,10 +818,11 @@ type consistentHeapStats struct { // Writers always atomically update the delta at index gen. // // Readers operate by rotating gen (0 -> 1 -> 2 -> 0 -> ...) - // and synchronizing with writers by observing each mcache's - // statsSeq field. If the reader observes a P (to which the - // mcache is bound) not writing, it can be sure that it will - // pick up the new gen value the next time it writes. + // and synchronizing with writers by observing each P's + // statsSeq field. If the reader observes a P not writing, + // it can be sure that it will pick up the new gen value the + // next time it writes. + // // The reader then takes responsibility by clearing space // in the ring buffer for the next reader to rotate gen to // that space (i.e. it merges in values from index (gen-2) mod 3 @@ -830,7 +831,7 @@ type consistentHeapStats struct { // Note that this means only one reader can be reading at a time. // There is no way for readers to synchronize. // - // This process is why we need ring buffer of size 3 instead + // This process is why we need a ring buffer of size 3 instead // of 2: one is for the writers, one contains the most recent // data, and the last one is clear so writers can begin writing // to it the moment gen is updated. @@ -840,24 +841,34 @@ type consistentHeapStats struct { // are writing, and can take on the value of 0, 1, or 2. // This value is updated atomically. gen uint32 + + // noPLock is intended to provide mutual exclusion for updating + // stats when no P is available. It does not block other writers + // with a P, only other writers without a P and the reader. Because + // stats are usually updated when a P is available, contention on + // this lock should be minimal. + noPLock mutex } // acquire returns a heapStatsDelta to be updated. In effect, // it acquires the shard for writing. release must be called -// as soon as the relevant deltas are updated. c must be -// a valid mcache not being used by any other thread. +// as soon as the relevant deltas are updated. // // The returned heapStatsDelta must be updated atomically. // -// Note however, that this is unsafe to call concurrently -// with other writers and there must be only one writer -// at a time. -func (m *consistentHeapStats) acquire(c *mcache) *heapStatsDelta { - seq := atomic.Xadd(&c.statsSeq, 1) - if seq%2 == 0 { - // Should have been incremented to odd. - print("runtime: seq=", seq, "\n") - throw("bad sequence number") +// The caller's P must not change between acquire and +// release. This also means that the caller should not +// acquire a P or release its P in between. +func (m *consistentHeapStats) acquire() *heapStatsDelta { + if pp := getg().m.p.ptr(); pp != nil { + seq := atomic.Xadd(&pp.statsSeq, 1) + if seq%2 == 0 { + // Should have been incremented to odd. + print("runtime: seq=", seq, "\n") + throw("bad sequence number") + } + } else { + lock(&m.noPLock) } gen := atomic.Load(&m.gen) % 3 return &m.stats[gen] @@ -868,14 +879,19 @@ func (m *consistentHeapStats) acquire(c *mcache) *heapStatsDelta { // acquire must no longer be accessed or modified after // release is called. // -// The mcache passed here must be the same as the one -// passed to acquire. -func (m *consistentHeapStats) release(c *mcache) { - seq := atomic.Xadd(&c.statsSeq, 1) - if seq%2 != 0 { - // Should have been incremented to even. - print("runtime: seq=", seq, "\n") - throw("bad sequence number") +// The caller's P must not change between acquire and +// release. This also means that the caller should not +// acquire a P or release its P in between. +func (m *consistentHeapStats) release() { + if pp := getg().m.p.ptr(); pp != nil { + seq := atomic.Xadd(&pp.statsSeq, 1) + if seq%2 != 0 { + // Should have been incremented to even. + print("runtime: seq=", seq, "\n") + throw("bad sequence number") + } + } else { + unlock(&m.noPLock) } } @@ -916,25 +932,33 @@ func (m *consistentHeapStats) read(out *heapStatsDelta) { // so it doesn't change out from under us. mp := acquirem() + // Get the current generation. We can be confident that this + // will not change since read is serialized and is the only + // one that modifies currGen. + currGen := atomic.Load(&m.gen) + prevGen := currGen - 1 + if currGen == 0 { + prevGen = 2 + } + + // Prevent writers without a P from writing while we update gen. + lock(&m.noPLock) + // Rotate gen, effectively taking a snapshot of the state of // these statistics at the point of the exchange by moving // writers to the next set of deltas. // // This exchange is safe to do because we won't race // with anyone else trying to update this value. - currGen := atomic.Load(&m.gen) atomic.Xchg(&m.gen, (currGen+1)%3) - prevGen := currGen - 1 - if currGen == 0 { - prevGen = 2 - } + + // Allow P-less writers to continue. They'll be writing to the + // next generation now. + unlock(&m.noPLock) + for _, p := range allp { - c := p.mcache - if c == nil { - continue - } // Spin until there are no more writers. - for atomic.Load(&c.statsSeq)%2 != 0 { + for atomic.Load(&p.statsSeq)%2 != 0 { } } @@ -951,5 +975,6 @@ func (m *consistentHeapStats) read(out *heapStatsDelta) { // Finally, copy out the complete delta. *out = m.stats[currGen] + releasem(mp) } diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 79529ac7ec7..87949a26949 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -577,6 +577,10 @@ func schedinit() { lockInit(&trace.lock, lockRankTrace) lockInit(&cpuprof.lock, lockRankCpuprof) lockInit(&trace.stackTab.lock, lockRankTraceStackTab) + // Enforce that this lock is always a leaf lock. + // All of this lock's critical sections should be + // extremely short. + lockInit(&memstats.heapStats.noPLock, lockRankLeafRank) // raceinit must be the first call to race detector. // In particular, it must be done before mallocinit below calls racemapshadow. diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index 82fedd804b1..c9376827da1 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -654,8 +654,8 @@ type p struct { timerModifiedEarliest uint64 // Per-P GC state - gcAssistTime int64 // Nanoseconds in assistAlloc - gcFractionalMarkTime int64 // Nanoseconds in fractional mark worker (atomic) + gcAssistTime int64 // Nanoseconds in assistAlloc + gcFractionalMarkTime int64 // Nanoseconds in fractional mark worker (atomic) // gcMarkWorkerMode is the mode for the next mark worker to run in. // That is, this is used to communicate with the worker goroutine @@ -679,6 +679,10 @@ type p struct { runSafePointFn uint32 // if 1, run sched.safePointFn at next safe point + // statsSeq is a counter indicating whether this P is currently + // writing any stats. Its value is even when not, odd when it is. + statsSeq uint32 + // Lock for timers. We normally access the timers while running // on this P, but the scheduler can also do it from a different P. timersLock mutex From 3a76627df4f6bd38a3cfa21aeddcb871f6df1881 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sun, 1 Nov 2020 15:28:21 -0500 Subject: [PATCH 329/403] cmd/link: use internal linking for -race mode on darwin/arm64 The code I wrote in ldmacho.go in CL 266373 was plainly wrong. It didn't carry rAdd over correctly. Fixed. Also added sign extension (as ld64 does). Internal linking with -race mode now works. Enable it. Updates #38485. Change-Id: I78aa949687bf6a0987913059059160b018c7560e Reviewed-on: https://go-review.googlesource.com/c/go/+/267097 Trust: Cherry Zhang Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/config.go | 2 +- src/cmd/link/internal/loadmacho/ldmacho.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index cd64d86a4af..0cb3cc25c06 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -206,7 +206,7 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { // When the race flag is set, the LLVM tsan relocatable file is linked // into the final binary, which means external linking is required because // internal linking does not support it. - if *flagRace && (ctxt.Arch.InFamily(sys.PPC64) || ctxt.IsDarwin() && ctxt.IsARM64()) { + if *flagRace && ctxt.Arch.InFamily(sys.PPC64) { return true, "race on " + objabi.GOARCH } diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index d26869e23a7..6d1d9bb29ed 100644 --- a/src/cmd/link/internal/loadmacho/ldmacho.go +++ b/src/cmd/link/internal/loadmacho/ldmacho.go @@ -724,10 +724,8 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, if arch.Family == sys.ARM64 && rel.type_ == MACHO_ARM64_RELOC_ADDEND { // Two relocations. This addend will be applied to the next one. - rAdd = int64(rel.symnum) + rAdd = int64(rel.symnum) << 40 >> 40 // convert unsigned 24-bit to signed 24-bit continue - } else { - rAdd = 0 } rSize = rel.length @@ -789,6 +787,8 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, r.SetSiz(rSize) r.SetSym(rSym) r.SetAdd(rAdd) + + rAdd = 0 // clear rAdd for next iteration } sb.SortRelocs() From ebc1b8ef2854e7006349275bc3b2306022200bbc Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 22 Oct 2020 21:52:50 +0700 Subject: [PATCH 330/403] reflect: update NumMethod doc for interface type Updates #42123 Change-Id: Ieb43b65c88d15b2475b6f3dd9672c44e7831cc34 Reviewed-on: https://go-review.googlesource.com/c/go/+/264357 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Russ Cox --- src/reflect/type.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/reflect/type.go b/src/reflect/type.go index a3a616701b9..a2076bb3f1b 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -50,13 +50,13 @@ type Type interface { // It panics if i is not in the range [0, NumMethod()). // // For a non-interface type T or *T, the returned Method's Type and Func - // fields describe a function whose first argument is the receiver. + // fields describe a function whose first argument is the receiver, + // and only exported methods are accessible. // // For an interface type, the returned Method's Type field gives the // method signature, without a receiver, and the Func field is nil. // - // Only exported methods are accessible and they are sorted in - // lexicographic order. + // Methods are sorted in lexicographic order. Method(int) Method // MethodByName returns the method with that name in the type's @@ -69,7 +69,9 @@ type Type interface { // method signature, without a receiver, and the Func field is nil. MethodByName(string) (Method, bool) - // NumMethod returns the number of exported methods in the type's method set. + // NumMethod returns the number of methods accessible using Method. + // + // Note that NumMethod counts unexported methods only for interface types. NumMethod() int // Name returns the type's name within its package for a defined type. From 45205bc47b88f49020edabed18f99153cadf718e Mon Sep 17 00:00:00 2001 From: Alwin Doss Date: Sun, 1 Nov 2020 04:43:20 +0000 Subject: [PATCH 331/403] os: export ErrProcessDone variable in windows and plan9 Exposes ErrProcessDone variable in windows and plan9 also returns this error code instead of errors.New("os: process already finished") Fixes #42311 Change-Id: Ie807b6526e7b6c27636e6bffe5ff0c904b319be4 GitHub-Last-Rev: 2153e0d7020d8ee9e94087d02977ea049b7fd6a0 GitHub-Pull-Request: golang/go#42313 Reviewed-on: https://go-review.googlesource.com/c/go/+/266997 Reviewed-by: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Dmitri Shuralyov --- src/os/exec.go | 4 ++++ src/os/exec_plan9.go | 3 +-- src/os/exec_unix.go | 3 --- src/os/exec_windows.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/os/exec.go b/src/os/exec.go index cab6a73d94e..edb773a092b 100644 --- a/src/os/exec.go +++ b/src/os/exec.go @@ -5,6 +5,7 @@ package os import ( + "errors" "internal/testlog" "runtime" "sync" @@ -13,6 +14,9 @@ import ( "time" ) +// ErrProcessDone indicates a Process has finished. +var ErrProcessDone = errors.New("os: process already finished") + // Process stores the information about a process created by StartProcess. type Process struct { Pid int diff --git a/src/os/exec_plan9.go b/src/os/exec_plan9.go index ef8dad11b61..85801539116 100644 --- a/src/os/exec_plan9.go +++ b/src/os/exec_plan9.go @@ -5,7 +5,6 @@ package os import ( - "errors" "runtime" "syscall" "time" @@ -52,7 +51,7 @@ func (p *Process) writeProcFile(file string, data string) error { func (p *Process) signal(sig Signal) error { if p.done() { - return errors.New("os: process already finished") + return ErrProcessDone } if e := p.writeProcFile("note", sig.String()); e != nil { return NewSyscallError("signal", e) diff --git a/src/os/exec_unix.go b/src/os/exec_unix.go index 624061297bb..a1703a12594 100644 --- a/src/os/exec_unix.go +++ b/src/os/exec_unix.go @@ -59,9 +59,6 @@ func (p *Process) wait() (ps *ProcessState, err error) { return ps, nil } -// ErrProcessDone indicates a Process has finished. -var ErrProcessDone = errors.New("os: process already finished") - func (p *Process) signal(sig Signal) error { if p.Pid == -1 { return errors.New("os: process already released") diff --git a/src/os/exec_windows.go b/src/os/exec_windows.go index 24ddf89bb6a..5710401acdb 100644 --- a/src/os/exec_windows.go +++ b/src/os/exec_windows.go @@ -61,7 +61,7 @@ func (p *Process) signal(sig Signal) error { return syscall.EINVAL } if p.done() { - return errors.New("os: process already finished") + return ErrProcessDone } if sig == Kill { err := terminateProcess(p.Pid, 1) From cc0930cd1d200a126a3ae8ac3d1bea986cfc30fe Mon Sep 17 00:00:00 2001 From: kemalelmizan Date: Fri, 28 Aug 2020 06:39:43 +0700 Subject: [PATCH 332/403] cmd/doc: adding validation before adding comment marker Previous fix in issue #20929 for adding comment marker does not check whether string field have // prefix or not. This commit ensures string field does not contain // before adding prefix to the line. Test also included in this commit. Fixes #40992 Change-Id: Ibc5e8ef147eeb2ed732fb9e19815c8b21fcfb2ab Reviewed-on: https://go-review.googlesource.com/c/go/+/251237 Run-TryBot: Robert Griesemer TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Robert Griesemer Trust: Dmitri Shuralyov --- src/go/doc/comment.go | 2 +- src/go/doc/comment_test.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/go/doc/comment.go b/src/go/doc/comment.go index da33f21612f..92131a3b83f 100644 --- a/src/go/doc/comment.go +++ b/src/go/doc/comment.go @@ -487,7 +487,7 @@ func (l *lineWrapper) write(text string) { l.out.Write(nl) l.n = 0 l.pendSpace = 0 - needsPrefix = isComment + needsPrefix = isComment && !strings.HasPrefix(f, "//") } if l.n == 0 { l.out.Write([]byte(l.indent)) diff --git a/src/go/doc/comment_test.go b/src/go/doc/comment_test.go index 101f4462878..6d1b209e1e1 100644 --- a/src/go/doc/comment_test.go +++ b/src/go/doc/comment_test.go @@ -152,6 +152,17 @@ A very long line of 46 char for line wrapping. */`, text: `. /* A very long line of 46 char for line . wrapping. A very long line of 46 char . for line wrapping. */ +`, + }, + { + in: `A line of 36 char for line wrapping. +//Another line starting with //`, + out: []block{ + {opPara, []string{"A line of 36 char for line wrapping.\n", + "//Another line starting with //"}}, + }, + text: `. A line of 36 char for line wrapping. +. //Another line starting with // `, }, } From 974def803ee9fd03a755014dcb62d55105c846f1 Mon Sep 17 00:00:00 2001 From: Heisenberg Date: Fri, 4 Sep 2020 16:56:54 +0800 Subject: [PATCH 333/403] go/ast: add test for Filter Change-Id: Ia14659a9c44f9e1504eb88b5693932b9dd4bb286 Reviewed-on: https://go-review.googlesource.com/c/go/+/252939 Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Trust: Dmitri Shuralyov Trust: Robert Griesemer Reviewed-by: Robert Griesemer --- src/go/ast/commentmap_test.go | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/go/ast/commentmap_test.go b/src/go/ast/commentmap_test.go index e372eab745b..38c62b01ab9 100644 --- a/src/go/ast/commentmap_test.go +++ b/src/go/ast/commentmap_test.go @@ -140,4 +140,31 @@ func TestCommentMap(t *testing.T) { } } -// TODO(gri): add tests for Filter. +func TestFilter(t *testing.T) { + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, "", src, parser.ParseComments) + if err != nil { + t.Fatal(err) + } + cmap := NewCommentMap(fset, f, f.Comments) + + // delete variable declaration + for i, decl := range f.Decls { + if gen, ok := decl.(*GenDecl); ok && gen.Tok == token.VAR { + copy(f.Decls[i:], f.Decls[i+1:]) + f.Decls = f.Decls[:len(f.Decls)-1] + break + } + } + + // check if comments are filtered correctly + cc := cmap.Filter(f) + for n, list := range cc { + key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n) + got := ctext(list) + want := res[key] + if key == "25: *ast.GenDecl" || got != want { + t.Errorf("%s: got %q; want %q", key, got, want) + } + } +} From 393f2bb067088cdbdb8d5848e6880b2ce65ddaf9 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 19 May 2020 18:56:01 +1000 Subject: [PATCH 334/403] cmd/dist,cmd/go,runtime: add support for cgo on linux/riscv64 Fixes #36641 Change-Id: I51868d83ce341d78d33b221d184c5a5110c60d14 Reviewed-on: https://go-review.googlesource.com/c/go/+/263598 Trust: Joel Sing Run-TryBot: Joel Sing TryBot-Result: Go Bot Reviewed-by: Cherry Zhang --- .../cgo/test/testdata/issue9400/asm_riscv64.s | 31 +++ src/cmd/dist/build.go | 2 +- src/cmd/dist/test.go | 6 +- .../testdata/script/build_plugin_non_main.txt | 3 +- src/cmd/nm/nm_cgo_test.go | 2 +- src/runtime/asm_riscv64.s | 190 ++++++++++++++++-- src/runtime/cgo/asm_riscv64.s | 84 ++++++++ src/runtime/cgo/gcc_linux_riscv64.c | 74 +++++++ src/runtime/cgo/gcc_riscv64.S | 80 ++++++++ src/runtime/cgocall.go | 2 +- src/runtime/tls_riscv64.s | 16 +- 11 files changed, 469 insertions(+), 21 deletions(-) create mode 100644 misc/cgo/test/testdata/issue9400/asm_riscv64.s create mode 100644 src/runtime/cgo/asm_riscv64.s create mode 100644 src/runtime/cgo/gcc_linux_riscv64.c create mode 100644 src/runtime/cgo/gcc_riscv64.S diff --git a/misc/cgo/test/testdata/issue9400/asm_riscv64.s b/misc/cgo/test/testdata/issue9400/asm_riscv64.s new file mode 100644 index 00000000000..20fcc0066d6 --- /dev/null +++ b/misc/cgo/test/testdata/issue9400/asm_riscv64.s @@ -0,0 +1,31 @@ +// Copyright 2020 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. + +// +build riscv64 +// +build !gccgo + +#include "textflag.h" + +TEXT ·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0 + // Rewind stack pointer so anything that happens on the stack + // will clobber the test pattern created by the caller + ADD $(1024*8), X2 + + // Ask signaller to setgid + MOV $1, X5 + FENCE + MOVW X5, ·Baton(SB) + FENCE + + // Wait for setgid completion +loop: + FENCE + MOVW ·Baton(SB), X5 + OR X6, X6, X6 // hint that we're in a spin loop + BNE ZERO, X5, loop + FENCE + + // Restore stack + ADD $(-1024*8), X2 + RET diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index d822a83e442..20cb04d797e 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -1549,7 +1549,7 @@ var cgoEnabled = map[string]bool{ "linux/mipsle": true, "linux/mips64": true, "linux/mips64le": true, - "linux/riscv64": false, // Issue 36641 + "linux/riscv64": true, "linux/s390x": true, "linux/sparc64": true, "android/386": true, diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 9c25392cc03..d12a52b1cc2 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -953,7 +953,7 @@ func (t *tester) internalLink() bool { // Internally linking cgo is incomplete on some architectures. // https://golang.org/issue/10373 // https://golang.org/issue/14449 - if goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" { + if goarch == "mips64" || goarch == "mips64le" || goarch == "mips" || goarch == "mipsle" || goarch == "riscv64" { return false } if goos == "aix" { @@ -1117,8 +1117,8 @@ func (t *tester) cgoTest(dt *distTest) error { "android-arm", "android-arm64", "dragonfly-amd64", "freebsd-386", "freebsd-amd64", "freebsd-arm", - "linux-386", "linux-amd64", "linux-arm", "linux-ppc64le", "linux-s390x", - "netbsd-386", "netbsd-amd64", "linux-arm64": + "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x", + "netbsd-386", "netbsd-amd64": cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=external") diff --git a/src/cmd/go/testdata/script/build_plugin_non_main.txt b/src/cmd/go/testdata/script/build_plugin_non_main.txt index dba80c29ad2..3c82dced735 100644 --- a/src/cmd/go/testdata/script/build_plugin_non_main.txt +++ b/src/cmd/go/testdata/script/build_plugin_non_main.txt @@ -1,5 +1,6 @@ -# Plugins are only supported on linux,cgo and darwin,cgo. +# Plugins are only supported on linux,cgo (!riscv64) and darwin,cgo. [!linux] [!darwin] skip +[linux] [riscv64] skip [!cgo] skip go build -n testdep diff --git a/src/cmd/nm/nm_cgo_test.go b/src/cmd/nm/nm_cgo_test.go index 9a257e0ed2e..e0414e6b222 100644 --- a/src/cmd/nm/nm_cgo_test.go +++ b/src/cmd/nm/nm_cgo_test.go @@ -24,7 +24,7 @@ func canInternalLink() bool { } case "linux": switch runtime.GOARCH { - case "arm64", "mips64", "mips64le", "mips", "mipsle", "ppc64", "ppc64le": + case "arm64", "mips64", "mips64le", "mips", "mipsle", "ppc64", "ppc64le", "riscv64": return false } case "openbsd": diff --git a/src/runtime/asm_riscv64.s b/src/runtime/asm_riscv64.s index caaf42a7d02..01b42dc3deb 100644 --- a/src/runtime/asm_riscv64.s +++ b/src/runtime/asm_riscv64.s @@ -9,10 +9,9 @@ // func rt0_go() TEXT runtime·rt0_go(SB),NOSPLIT,$0 // X2 = stack; A0 = argc; A1 = argv - ADD $-24, X2 - MOV A0, 8(X2) // argc - MOV A1, 16(X2) // argv + MOV A0, 8(X2) // argc + MOV A1, 16(X2) // argv // create istack out of the given (operating system) stack. // _cgo_init may update stackguard. @@ -28,10 +27,10 @@ TEXT runtime·rt0_go(SB),NOSPLIT,$0 MOV _cgo_init(SB), T0 BEQ T0, ZERO, nocgo - MOV ZERO, A3 // arg 3: not used - MOV ZERO, A2 // arg 2: not used + MOV ZERO, A3 // arg 3: not used + MOV ZERO, A2 // arg 2: not used MOV $setg_gcc<>(SB), A1 // arg 1: setg - MOV g, A0 // arg 0: G + MOV g, A0 // arg 0: G JALR RA, T0 nocgo: @@ -313,10 +312,62 @@ TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8 CALL runtime·badctxt(SB) RET +// Save state of caller into g->sched. Smashes X31. +TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0 + MOV X1, (g_sched+gobuf_pc)(g) + MOV X2, (g_sched+gobuf_sp)(g) + MOV ZERO, (g_sched+gobuf_lr)(g) + MOV ZERO, (g_sched+gobuf_ret)(g) + // Assert ctxt is zero. See func save. + MOV (g_sched+gobuf_ctxt)(g), X31 + BEQ ZERO, X31, 2(PC) + CALL runtime·badctxt(SB) + RET + // func asmcgocall(fn, arg unsafe.Pointer) int32 +// Call fn(arg) on the scheduler stack, +// aligned appropriately for the gcc ABI. +// See cgocall.go for more details. TEXT ·asmcgocall(SB),NOSPLIT,$0-20 - // TODO(jsing): Add support for cgo - issue #36641. - WORD $0 // crash + MOV fn+0(FP), X5 + MOV arg+8(FP), X10 + + MOV X2, X8 // save original stack pointer + MOV g, X9 + + // Figure out if we need to switch to m->g0 stack. + // We get called to create new OS threads too, and those + // come in on the m->g0 stack already. + MOV g_m(g), X6 + MOV m_g0(X6), X7 + BEQ X7, g, g0 + + CALL gosave<>(SB) + MOV X7, g + CALL runtime·save_g(SB) + MOV (g_sched+gobuf_sp)(g), X2 + + // Now on a scheduling stack (a pthread-created stack). +g0: + // Save room for two of our pointers. + ADD $-16, X2 + MOV X9, 0(X2) // save old g on stack + MOV (g_stack+stack_hi)(X9), X9 + SUB X8, X9, X8 + MOV X8, 8(X2) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) + + JALR RA, (X5) + + // Restore g, stack pointer. X10 is return value. + MOV 0(X2), g + CALL runtime·save_g(SB) + MOV (g_stack+stack_hi)(g), X5 + MOV 8(X2), X6 + SUB X6, X5, X6 + MOV X6, X2 + + MOVW X10, ret+16(FP) + RET // func asminit() TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 @@ -444,6 +495,21 @@ CALLFN(·call268435456, 268435456) CALLFN(·call536870912, 536870912) CALLFN(·call1073741824, 1073741824) +// Called from cgo wrappers, this function returns g->m->curg.stack.hi. +// Must obey the gcc calling convention. +TEXT _cgo_topofstack(SB),NOSPLIT,$8 + // g (X27) and REG_TMP (X31) might be clobbered by load_g. + // X27 is callee-save in the gcc calling convention, so save it. + MOV g, savedX27-8(SP) + + CALL runtime·load_g(SB) + MOV g_m(g), X5 + MOV m_curg(X5), X5 + MOV (g_stack+stack_hi)(X5), X10 // return value in X10 + + MOV savedX27-8(SP), g + RET + // func goexit(neverCallThisFunction) // The top-most function running on a goroutine // returns to goexit+PCQuantum. @@ -453,11 +519,111 @@ TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 // traceback from goexit1 must hit code range of goexit MOV ZERO, ZERO // NOP -// cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) +// func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) // See cgocall.go for more details. -TEXT ·cgocallback(SB),NOSPLIT,$0-24 - // TODO(jsing): Add support for cgo - issue #36641. - WORD $0 // crash +TEXT ·cgocallback(SB),NOSPLIT,$24-24 + NO_LOCAL_POINTERS + + // Load m and g from thread-local storage. + MOVBU runtime·iscgo(SB), X5 + BEQ ZERO, X5, nocgo + CALL runtime·load_g(SB) +nocgo: + + // If g is nil, Go did not create the current thread. + // Call needm to obtain one for temporary use. + // In this case, we're running on the thread stack, so there's + // lots of space, but the linker doesn't know. Hide the call from + // the linker analysis by using an indirect call. + BEQ ZERO, g, needm + + MOV g_m(g), X5 + MOV X5, savedm-8(SP) + JMP havem + +needm: + MOV g, savedm-8(SP) // g is zero, so is m. + MOV $runtime·needm(SB), X6 + JALR RA, X6 + + // Set m->sched.sp = SP, so that if a panic happens + // during the function we are about to execute, it will + // have a valid SP to run on the g0 stack. + // The next few lines (after the havem label) + // will save this SP onto the stack and then write + // the same SP back to m->sched.sp. That seems redundant, + // but if an unrecovered panic happens, unwindm will + // restore the g->sched.sp from the stack location + // and then systemstack will try to use it. If we don't set it here, + // that restored SP will be uninitialized (typically 0) and + // will not be usable. + MOV g_m(g), X5 + MOV m_g0(X5), X6 + MOV X2, (g_sched+gobuf_sp)(X6) + +havem: + // Now there's a valid m, and we're running on its m->g0. + // Save current m->g0->sched.sp on stack and then set it to SP. + // Save current sp in m->g0->sched.sp in preparation for + // switch back to m->curg stack. + // NOTE: unwindm knows that the saved g->sched.sp is at 8(X2) aka savedsp-24(SP). + MOV m_g0(X5), X6 + MOV (g_sched+gobuf_sp)(X6), X7 + MOV X7, savedsp-24(SP) // must match frame size + MOV X2, (g_sched+gobuf_sp)(X6) + + // Switch to m->curg stack and call runtime.cgocallbackg. + // Because we are taking over the execution of m->curg + // but *not* resuming what had been running, we need to + // save that information (m->curg->sched) so we can restore it. + // We can restore m->curg->sched.sp easily, because calling + // runtime.cgocallbackg leaves SP unchanged upon return. + // To save m->curg->sched.pc, we push it onto the curg stack and + // open a frame the same size as cgocallback's g0 frame. + // Once we switch to the curg stack, the pushed PC will appear + // to be the return PC of cgocallback, so that the traceback + // will seamlessly trace back into the earlier calls. + MOV m_curg(X5), g + CALL runtime·save_g(SB) + MOV (g_sched+gobuf_sp)(g), X6 // prepare stack as X6 + MOV (g_sched+gobuf_pc)(g), X7 + MOV X7, -(24+8)(X6) // "saved LR"; must match frame size + // Gather our arguments into registers. + MOV fn+0(FP), X7 + MOV frame+8(FP), X8 + MOV ctxt+16(FP), X9 + MOV $-(24+8)(X6), X2 // switch stack; must match frame size + MOV X7, 8(X2) + MOV X8, 16(X2) + MOV X9, 24(X2) + CALL runtime·cgocallbackg(SB) + + // Restore g->sched (== m->curg->sched) from saved values. + MOV 0(X2), X7 + MOV X7, (g_sched+gobuf_pc)(g) + MOV $(24+8)(X2), X6 // must match frame size + MOV X6, (g_sched+gobuf_sp)(g) + + // Switch back to m->g0's stack and restore m->g0->sched.sp. + // (Unlike m->curg, the g0 goroutine never uses sched.pc, + // so we do not have to restore it.) + MOV g_m(g), X5 + MOV m_g0(X5), g + CALL runtime·save_g(SB) + MOV (g_sched+gobuf_sp)(g), X2 + MOV savedsp-24(SP), X6 // must match frame size + MOV X6, (g_sched+gobuf_sp)(g) + + // If the m on entry was nil, we called needm above to borrow an m + // for the duration of the call. Since the call is over, return it with dropm. + MOV savedm-8(SP), X5 + BNE ZERO, X5, droppedm + MOV $runtime·dropm(SB), X6 + JALR RA, X6 +droppedm: + + // Done! + RET TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 EBREAK diff --git a/src/runtime/cgo/asm_riscv64.s b/src/runtime/cgo/asm_riscv64.s new file mode 100644 index 00000000000..b4ddbb020f0 --- /dev/null +++ b/src/runtime/cgo/asm_riscv64.s @@ -0,0 +1,84 @@ +// Copyright 2020 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. + +// +build riscv64 + +#include "textflag.h" + +// Called by C code generated by cmd/cgo. +// func crosscall2(fn, a unsafe.Pointer, n int32, ctxt uintptr) +// Saves C callee-saved registers and calls cgocallback with three arguments. +// fn is the PC of a func(a unsafe.Pointer) function. +TEXT crosscall2(SB),NOSPLIT|NOFRAME,$0 + /* + * Push arguments for fn (X10, X11, X13), along with all callee-save + * registers. Note that at procedure entry the first argument is at + * 8(X2). + */ + ADD $(-8*31), X2 + MOV X10, (8*1)(X2) // fn unsafe.Pointer + MOV X11, (8*2)(X2) // a unsafe.Pointer + MOV X13, (8*3)(X2) // ctxt uintptr + MOV X8, (8*4)(X2) + MOV X9, (8*5)(X2) + MOV X18, (8*6)(X2) + MOV X19, (8*7)(X2) + MOV X20, (8*8)(X2) + MOV X21, (8*9)(X2) + MOV X22, (8*10)(X2) + MOV X23, (8*11)(X2) + MOV X24, (8*12)(X2) + MOV X25, (8*13)(X2) + MOV X26, (8*14)(X2) + MOV g, (8*15)(X2) + MOV X3, (8*16)(X2) + MOV X4, (8*17)(X2) + MOV X1, (8*18)(X2) + MOVD F8, (8*19)(X2) + MOVD F9, (8*20)(X2) + MOVD F18, (8*21)(X2) + MOVD F19, (8*22)(X2) + MOVD F20, (8*23)(X2) + MOVD F21, (8*24)(X2) + MOVD F22, (8*25)(X2) + MOVD F23, (8*26)(X2) + MOVD F24, (8*27)(X2) + MOVD F25, (8*28)(X2) + MOVD F26, (8*29)(X2) + MOVD F27, (8*30)(X2) + + // Initialize Go ABI environment + CALL runtime·load_g(SB) + CALL runtime·cgocallback(SB) + + MOV (8*4)(X2), X8 + MOV (8*5)(X2), X9 + MOV (8*6)(X2), X18 + MOV (8*7)(X2), X19 + MOV (8*8)(X2), X20 + MOV (8*9)(X2), X21 + MOV (8*10)(X2), X22 + MOV (8*11)(X2), X23 + MOV (8*12)(X2), X24 + MOV (8*13)(X2), X25 + MOV (8*14)(X2), X26 + MOV (8*15)(X2), g + MOV (8*16)(X2), X3 + MOV (8*17)(X2), X4 + MOV (8*18)(X2), X1 + MOVD (8*19)(X2), F8 + MOVD (8*20)(X2), F9 + MOVD (8*21)(X2), F18 + MOVD (8*22)(X2), F19 + MOVD (8*23)(X2), F20 + MOVD (8*24)(X2), F21 + MOVD (8*25)(X2), F22 + MOVD (8*26)(X2), F23 + MOVD (8*27)(X2), F24 + MOVD (8*28)(X2), F25 + MOVD (8*29)(X2), F26 + MOVD (8*30)(X2), F27 + ADD $(8*31), X2 + + RET diff --git a/src/runtime/cgo/gcc_linux_riscv64.c b/src/runtime/cgo/gcc_linux_riscv64.c new file mode 100644 index 00000000000..22b76c2fccf --- /dev/null +++ b/src/runtime/cgo/gcc_linux_riscv64.c @@ -0,0 +1,74 @@ +// Copyright 2020 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. + +#include +#include +#include +#include "libcgo.h" +#include "libcgo_unix.h" + +static void *threadentry(void*); + +void (*x_cgo_inittls)(void **tlsg, void **tlsbase); +static void (*setg_gcc)(void*); + +void +_cgo_sys_thread_start(ThreadStart *ts) +{ + pthread_attr_t attr; + sigset_t ign, oset; + pthread_t p; + size_t size; + int err; + + sigfillset(&ign); + pthread_sigmask(SIG_SETMASK, &ign, &oset); + + // Not sure why the memset is necessary here, + // but without it, we get a bogus stack size + // out of pthread_attr_getstacksize. C'est la Linux. + memset(&attr, 0, sizeof attr); + pthread_attr_init(&attr); + size = 0; + pthread_attr_getstacksize(&attr, &size); + // Leave stacklo=0 and set stackhi=size; mstart will do the rest. + ts->g->stackhi = size; + err = _cgo_try_pthread_create(&p, &attr, threadentry, ts); + + pthread_sigmask(SIG_SETMASK, &oset, nil); + + if (err != 0) { + fatalf("pthread_create failed: %s", strerror(err)); + } +} + +extern void crosscall1(void (*fn)(void), void (*setg_gcc)(void*), void *g); +static void* +threadentry(void *v) +{ + ThreadStart ts; + + ts = *(ThreadStart*)v; + free(v); + + crosscall1(ts.fn, setg_gcc, (void*)ts.g); + return nil; +} + +void +x_cgo_init(G *g, void (*setg)(void*), void **tlsg, void **tlsbase) +{ + pthread_attr_t attr; + size_t size; + + setg_gcc = setg; + pthread_attr_init(&attr); + pthread_attr_getstacksize(&attr, &size); + g->stacklo = (uintptr)&attr - size + 4096; + pthread_attr_destroy(&attr); + + if (x_cgo_inittls) { + x_cgo_inittls(tlsg, tlsbase); + } +} diff --git a/src/runtime/cgo/gcc_riscv64.S b/src/runtime/cgo/gcc_riscv64.S new file mode 100644 index 00000000000..f429dc64ee6 --- /dev/null +++ b/src/runtime/cgo/gcc_riscv64.S @@ -0,0 +1,80 @@ +// Copyright 2020 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. + +/* + * void crosscall1(void (*fn)(void), void (*setg_gcc)(void *g), void *g) + * + * Calling into the gc tool chain, where all registers are caller save. + * Called from standard RISCV ELF psABI, where x8-x9, x18-x27, f8-f9 and + * f18-f27 are callee-save, so they must be saved explicitly, along with + * x1 (LR). + */ +.globl crosscall1 +crosscall1: + sd x1, -200(sp) + addi sp, sp, -200 + sd x8, 8(sp) + sd x9, 16(sp) + sd x18, 24(sp) + sd x19, 32(sp) + sd x20, 40(sp) + sd x21, 48(sp) + sd x22, 56(sp) + sd x23, 64(sp) + sd x24, 72(sp) + sd x25, 80(sp) + sd x26, 88(sp) + sd x27, 96(sp) + fsd f8, 104(sp) + fsd f9, 112(sp) + fsd f18, 120(sp) + fsd f19, 128(sp) + fsd f20, 136(sp) + fsd f21, 144(sp) + fsd f22, 152(sp) + fsd f23, 160(sp) + fsd f24, 168(sp) + fsd f25, 176(sp) + fsd f26, 184(sp) + fsd f27, 192(sp) + + // a0 = *fn, a1 = *setg_gcc, a2 = *g + mv s1, a0 + mv s0, a1 + mv a0, a2 + jalr ra, s0 // call setg_gcc (clobbers x30 aka g) + jalr ra, s1 // call fn + + ld x1, 0(sp) + ld x8, 8(sp) + ld x9, 16(sp) + ld x18, 24(sp) + ld x19, 32(sp) + ld x20, 40(sp) + ld x21, 48(sp) + ld x22, 56(sp) + ld x23, 64(sp) + ld x24, 72(sp) + ld x25, 80(sp) + ld x26, 88(sp) + ld x27, 96(sp) + fld f8, 104(sp) + fld f9, 112(sp) + fld f18, 120(sp) + fld f19, 128(sp) + fld f20, 136(sp) + fld f21, 144(sp) + fld f22, 152(sp) + fld f23, 160(sp) + fld f24, 168(sp) + fld f25, 176(sp) + fld f26, 184(sp) + fld f27, 192(sp) + addi sp, sp, 200 + + jr ra + +#ifdef __ELF__ +.section .note.GNU-stack,"",%progbits +#endif diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 9bca2793184..20cacd6043a 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -309,7 +309,7 @@ func unwindm(restore *bool) { switch GOARCH { default: throw("unwindm not implemented") - case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x", "mips", "mipsle": + case "386", "amd64", "arm", "ppc64", "ppc64le", "mips64", "mips64le", "s390x", "mips", "mipsle", "riscv64": sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + sys.MinFrameSize)) case "arm64": sched.sp = *(*uintptr)(unsafe.Pointer(sched.sp + 16)) diff --git a/src/runtime/tls_riscv64.s b/src/runtime/tls_riscv64.s index 83869804212..22b550b7611 100644 --- a/src/runtime/tls_riscv64.s +++ b/src/runtime/tls_riscv64.s @@ -9,10 +9,22 @@ // If !iscgo, this is a no-op. // -// NOTE: mcall() assumes this clobbers only R23 (REGTMP). -// FIXME: cgo +// NOTE: mcall() assumes this clobbers only X31 (REG_TMP). TEXT runtime·save_g(SB),NOSPLIT|NOFRAME,$0-0 + MOVB runtime·iscgo(SB), X31 + BEQ X0, X31, nocgo + + MOV runtime·tls_g(SB), X31 + ADD X4, X31 // add offset to thread pointer (X4) + MOV g, (X31) + +nocgo: RET TEXT runtime·load_g(SB),NOSPLIT|NOFRAME,$0-0 + MOV runtime·tls_g(SB), X31 + ADD X4, X31 // add offset to thread pointer (X4) + MOV (X31), g RET + +GLOBL runtime·tls_g(SB), TLSBSS, $8 From ecd7b7e991d802db2bb63ccf7cede83f62e4e1c9 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Tue, 3 Nov 2020 15:00:07 +0000 Subject: [PATCH 335/403] Revert "cmd/go: support cgo files in overlays" This reverts CL 267197. Reason for revert: tests failing on windows-amd64-longtest builder (https://build.golang.org/log/83afde1aac3ea49debddb8996d089a741c3b1cf1). Change-Id: I0d7c706144e34b1715316ca2ee9662c901b7f8f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/267357 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/cmd/go/internal/work/exec.go | 48 ++--------- src/cmd/go/internal/work/gc.go | 9 +- src/cmd/go/testdata/script/build_overlay.txt | 83 +------------------ .../go/testdata/script/build_trimpath_cgo.txt | 28 ------- 4 files changed, 12 insertions(+), 156 deletions(-) diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index a1a357e2acc..838b00a00d2 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -8,7 +8,6 @@ package work import ( "bytes" - "cmd/go/internal/fsys" "context" "encoding/json" "errors" @@ -2243,6 +2242,8 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s // when -trimpath is enabled. if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") { if cfg.BuildTrimpath { + // TODO(#39958): handle overlays + // Keep in sync with Action.trimpath. // The trimmed paths are a little different, but we need to trim in the // same situations. @@ -2312,8 +2313,7 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag cmdargs := []interface{}{cmd, "-o", outfile, objs, flags} dir := p.Dir - out, err := b.runOut(a, base.Cwd, b.cCompilerEnv(), cmdargs...) - + out, err := b.runOut(a, dir, b.cCompilerEnv(), cmdargs...) if len(out) > 0 { // Filter out useless linker warnings caused by bugs outside Go. // See also cmd/link/internal/ld's hostlink method. @@ -2641,8 +2641,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...) } - // Allows including _cgo_export.h, as well as the user's .h files, - // from .[ch] files in the package. + // Allows including _cgo_export.h from .[ch] files in the package. cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", objdir) // cgo @@ -2655,8 +2654,6 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cfiles = append(cfiles, f+".cgo2.c") } - hfiles := append([]string{}, p.HFiles...) - // TODO: make cgo not depend on $GOARCH? cgoflags := []string{} @@ -2701,38 +2698,7 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo cgoflags = append(cgoflags, "-exportheader="+objdir+"_cgo_install.h") } - execdir := p.Dir - - // If any of the Cgo, C, or H files are overlaid, copy them all to - // objdir to ensure that they refer to the right header files. - // TODO(#39958): Ideally, we'd always do this, but this could - // subtly break some cgo files that include .h files across directory - // boundaries, even though they shouldn't. - hasOverlay := false - cgoFileLists := [][]string{cgofiles, gccfiles, gxxfiles, mfiles, ffiles, hfiles} -OverlayLoop: - for _, fs := range cgoFileLists { - for _, f := range fs { - if _, ok := fsys.OverlayPath(mkAbs(p.Dir, f)); ok { - hasOverlay = true - break OverlayLoop - } - } - } - if hasOverlay { - execdir = objdir - for _, fs := range cgoFileLists { - for i := range fs { - opath, _ := fsys.OverlayPath(mkAbs(p.Dir, fs[i])) - fs[i] = objdir + filepath.Base(fs[i]) - if err := b.copyFile(fs[i], opath, 0666, false); err != nil { - return nil, nil, err - } - } - } - } - - if err := b.run(a, execdir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { + if err := b.run(a, p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, "-objdir", objdir, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil { return nil, nil, err } outGo = append(outGo, gofiles...) @@ -2826,7 +2792,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe return err } - linkobj := str.StringList(ofile, outObj, mkAbsFiles(p.Dir, p.SysoFiles)) + linkobj := str.StringList(ofile, outObj, p.SysoFiles) dynobj := objdir + "_cgo_.o" // we need to use -pie for Linux/ARM to get accurate imported sym @@ -2851,7 +2817,7 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = []string{"-dynlinker"} // record path to dynamic linker } - return b.run(a, base.Cwd, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + return b.run(a, p.Dir, p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) } // Run SWIG on all SWIG input files. diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go index 4ba9be78296..e79173485db 100644 --- a/src/cmd/go/internal/work/gc.go +++ b/src/cmd/go/internal/work/gc.go @@ -262,7 +262,7 @@ func (a *Action) trimpath() string { if len(objdir) > 1 && objdir[len(objdir)-1] == filepath.Separator { objdir = objdir[:len(objdir)-1] } - rewrite := "" + rewrite := objdir + "=>" rewriteDir := a.Package.Dir if cfg.BuildTrimpath { @@ -271,7 +271,7 @@ func (a *Action) trimpath() string { } else { rewriteDir = a.Package.ImportPath } - rewrite += a.Package.Dir + "=>" + rewriteDir + ";" + rewrite += ";" + a.Package.Dir + "=>" + rewriteDir } // Add rewrites for overlays. The 'from' and 'to' paths in overlays don't need to have @@ -280,14 +280,11 @@ func (a *Action) trimpath() string { if fsys.OverlayFile != "" { for _, filename := range a.Package.AllFiles() { overlayPath, ok := fsys.OverlayPath(filepath.Join(a.Package.Dir, filename)) - rewrite += filepath.Join(objdir, filename) + "=>" + filepath.Join(rewriteDir, filename) + ";" if !ok { continue } - rewrite += overlayPath + "=>" + filepath.Join(rewriteDir, filename) + ";" + rewrite += ";" + overlayPath + "=>" + filepath.Join(rewriteDir, filename) } - } else { - rewrite += objdir + "=>" } return rewrite diff --git a/src/cmd/go/testdata/script/build_overlay.txt b/src/cmd/go/testdata/script/build_overlay.txt index be473a85db9..0602e706e9e 100644 --- a/src/cmd/go/testdata/script/build_overlay.txt +++ b/src/cmd/go/testdata/script/build_overlay.txt @@ -1,11 +1,9 @@ [short] skip # Test building in overlays. -# TODO(#39958): add a test case where the destination file in the replace map +# TODO(matloob): add a test case where the destination file in the replace map # isn't a go file. Either completely exclude that case in fs.IsDirWithGoFiles # if the compiler doesn't allow it, or test that it works all the way. -# TODO(#39958): add a test that both gc and gccgo assembly files can include .h -# files. # The main package (m) is contained in an overlay. It imports m/dir2 which has one # file in an overlay and one file outside the overlay, which in turn imports m/dir, @@ -31,18 +29,6 @@ exec ./print_trimpath_two_files$GOEXE stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]main.go stdout $WORK[/\\]gopath[/\\]src[/\\]m[/\\]printpath[/\\]other.go -go build -overlay overlay.json -o main_cgo_replace$GOEXE ./cgo_hello_replace -exec ./main_cgo_replace$GOEXE -stdout '^hello cgo$' - -go build -overlay overlay.json -o main_cgo_quote$GOEXE ./cgo_hello_quote -exec ./main_cgo_quote$GOEXE -stdout '^hello cgo$' - -go build -overlay overlay.json -o main_cgo_angle$GOEXE ./cgo_hello_angle -exec ./main_cgo_angle$GOEXE -stdout '^hello cgo$' - # Run same tests but with gccgo. env GO111MODULE=off [!exec:gccgo] stop @@ -60,19 +46,6 @@ go build -compiler=gccgo -overlay overlay.json -o print_trimpath_gccgo$GOEXE -tr exec ./print_trimpath_gccgo$GOEXE stdout ^\.[/\\]printpath[/\\]main.go - -go build -compiler=gccgo -overlay overlay.json -o main_cgo_replace_gccgo$GOEXE ./cgo_hello_replace -exec ./main_cgo_replace_gccgo$GOEXE -stdout '^hello cgo$' - -go build -compiler=gccgo -overlay overlay.json -o main_cgo_quote_gccgo$GOEXE ./cgo_hello_quote -exec ./main_cgo_quote_gccgo$GOEXE -stdout '^hello cgo$' - -go build -compiler=gccgo -overlay overlay.json -o main_cgo_angle_gccgo$GOEXE ./cgo_hello_angle -exec ./main_cgo_angle_gccgo$GOEXE -stdout '^hello cgo$' - -- m/go.mod -- // TODO(matloob): how do overlays work with go.mod (especially if mod=readonly) module m @@ -98,32 +71,9 @@ the actual code is in the overlay "dir/g.go": "overlay/dir_g.go", "dir2/i.go": "overlay/dir2_i.go", "printpath/main.go": "overlay/printpath.go", - "printpath/other.go": "overlay2/printpath2.go", - "cgo_hello_replace/cgo_header.h": "overlay/cgo_head.h", - "cgo_hello_quote/cgo_hello.go": "overlay/cgo_hello_quote.go", - "cgo_hello_quote/cgo_header.h": "overlay/cgo_head.h", - "cgo_hello_angle/cgo_hello.go": "overlay/cgo_hello_angle.go", - "cgo_hello_angle/cgo_header.h": "overlay/cgo_head.h" + "printpath/other.go": "overlay2/printpath2.go" } } --- m/cgo_hello_replace/cgo_hello_replace.go -- -package main - -// #include "cgo_header.h" -import "C" - -func main() { - C.say_hello() -} --- m/cgo_hello_replace/cgo_header.h -- - // Test that this header is replaced with one that has the proper declaration. -void say_goodbye(); - --- m/cgo_hello_replace/goodbye.c -- -#include - -void say_hello() { puts("hello cgo\n"); fflush(stdout); } - -- m/overlay/f.go -- package main @@ -178,32 +128,3 @@ import "m/dir" func printMessage() { dir.PrintMessage() } --- m/overlay/cgo_hello_quote.go -- -package main - -// #include "cgo_header.h" -import "C" - -func main() { - C.say_hello() -} --- m/overlay/cgo_hello_angle.go -- -package main - -// #include -import "C" - -func main() { - C.say_hello() -} --- m/overlay/cgo_head.h -- -void say_hello(); --- m/cgo_hello_quote/hello.c -- -#include - -void say_hello() { puts("hello cgo\n"); fflush(stdout); } --- m/cgo_hello_angle/hello.c -- -#include - -void say_hello() { puts("hello cgo\n"); fflush(stdout); } - diff --git a/src/cmd/go/testdata/script/build_trimpath_cgo.txt b/src/cmd/go/testdata/script/build_trimpath_cgo.txt index 3187b4d6439..4608d9ac6bf 100644 --- a/src/cmd/go/testdata/script/build_trimpath_cgo.txt +++ b/src/cmd/go/testdata/script/build_trimpath_cgo.txt @@ -20,38 +20,10 @@ go build -trimpath -o hello.exe . go run ./list-dwarf hello.exe ! stdout gopath/src - -# Do the above, with the cgo (but not .c) sources in an overlay -# Check that the source path appears when -trimpath is not used. -mkdir $WORK/overlay -cp hello.go $WORK/overlay/hello.go -mkdir hello_overlay -cp hello.c hello_overlay/hello.c -go build -overlay overlay.json -o hello_overlay.exe ./hello_overlay -grep -q gopath[/\\]src hello_overlay.exe -! grep -q $WORK[/\\]overlay hello_overlay.exe -go run ./list-dwarf hello_overlay.exe -stdout gopath[/\\]src -! stdout $WORK[/\\]overlay - -# Check that the source path does not appear when -trimpath is used. -go build -overlay overlay.json -trimpath -o hello_overlay.exe ./hello_overlay -! grep -q gopath[/\\]src hello_overlay.exe -! grep -q $WORK[/\\]overlay hello_overlay.exe -go run ./list-dwarf hello_overlay.exe -! stdout gopath/src -! stdout $WORK[/\\]overlay - -- go.mod -- module m go 1.14 --- overlay.json -- -{ - "Replace": { - "hello_overlay/hello.go": "../../overlay/hello.go" - } -} -- hello.c -- #include From da7aa86917811a571e6634b45a457f918b8e6561 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 2 Nov 2020 21:31:06 -0800 Subject: [PATCH 336/403] cmd/go: in cgoflags, permit -DX1, prohibit -Wp,-D,opt Restrict -D and -U to ASCII C identifiers, but do permit trailing digits. When using -Wp, prohibit commas in -D values. Change-Id: Ibfc4dfdd6e6c258e131448e7682610c44eee9492 Reviewed-on: https://go-review.googlesource.com/c/go/+/267277 Trust: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/work/security.go | 8 ++++---- src/cmd/go/internal/work/security_test.go | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/internal/work/security.go b/src/cmd/go/internal/work/security.go index bcc29c8cbe1..b8df3dddd36 100644 --- a/src/cmd/go/internal/work/security.go +++ b/src/cmd/go/internal/work/security.go @@ -42,8 +42,8 @@ import ( var re = lazyregexp.New var validCompilerFlags = []*lazyregexp.Regexp{ - re(`-D([A-Za-z_].*)`), - re(`-U([A-Za-z_]*)`), + re(`-D([A-Za-z_][A-Za-z0-9_]*)(=[^@\-]*)?`), + re(`-U([A-Za-z_][A-Za-z0-9_]*)`), re(`-F([^@\-].*)`), re(`-I([^@\-].*)`), re(`-O`), @@ -51,8 +51,8 @@ var validCompilerFlags = []*lazyregexp.Regexp{ re(`-W`), re(`-W([^@,]+)`), // -Wall but not -Wa,-foo. re(`-Wa,-mbig-obj`), - re(`-Wp,-D([A-Za-z_].*)`), - re(`-Wp,-U([A-Za-z_]*)`), + re(`-Wp,-D([A-Za-z_][A-Za-z0-9_]*)(=[^@,\-]*)?`), + re(`-Wp,-U([A-Za-z_][A-Za-z0-9_]*)`), re(`-ansi`), re(`-f(no-)?asynchronous-unwind-tables`), re(`-f(no-)?blocks`), diff --git a/src/cmd/go/internal/work/security_test.go b/src/cmd/go/internal/work/security_test.go index 43a0ab1e476..4f2e0eb21ab 100644 --- a/src/cmd/go/internal/work/security_test.go +++ b/src/cmd/go/internal/work/security_test.go @@ -13,6 +13,7 @@ var goodCompilerFlags = [][]string{ {"-DFOO"}, {"-Dfoo=bar"}, {"-Ufoo"}, + {"-Ufoo1"}, {"-F/Qt"}, {"-I/"}, {"-I/etc/passwd"}, @@ -24,6 +25,8 @@ var goodCompilerFlags = [][]string{ {"-Wall"}, {"-Wp,-Dfoo=bar"}, {"-Wp,-Ufoo"}, + {"-Wp,-Dfoo1"}, + {"-Wp,-Ufoo1"}, {"-fobjc-arc"}, {"-fno-objc-arc"}, {"-fomit-frame-pointer"}, @@ -80,6 +83,8 @@ var badCompilerFlags = [][]string{ {"-O@1"}, {"-Wa,-foo"}, {"-W@foo"}, + {"-Wp,-DX,-D@X"}, + {"-Wp,-UX,-U@X"}, {"-g@gdb"}, {"-g-gdb"}, {"-march=@dawn"}, From e1b305af028544e00a22c905e68049c98c10a1cc Mon Sep 17 00:00:00 2001 From: Ben Hoyt Date: Wed, 4 Nov 2020 10:13:42 +1300 Subject: [PATCH 337/403] strconv: revert ParseFloat/ParseComplex error on incorrect bitSize This is a partial revert of https://go-review.googlesource.com/c/go/+/248219 because we found that a non-trivial amount of code erroneously calls ParseFloat(s, 10) or even ParseFloat(s, 0) and expects it to work -- before that change was merged, ParseFloat accepted a bitSize of anything other than 32 or 64 to mean 64 (and ParseComplex was similar). So revert that behavior to avoid breaking people's code, and add tests for this. I may add a vet check to flag ParseFloat(s, not_32_or_64) in a later change. See #42297 for more details. Change-Id: I4bc0156bd74f67a39d5561b6e5fde3f2d20bd622 Reviewed-on: https://go-review.googlesource.com/c/go/+/267319 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- src/strconv/atoc.go | 6 +++--- src/strconv/atoc_test.go | 21 +++++++++++++-------- src/strconv/atof.go | 3 --- src/strconv/atof_test.go | 22 ++++++++++++++-------- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/strconv/atoc.go b/src/strconv/atoc.go index 52cb5908b27..85c7bafefa4 100644 --- a/src/strconv/atoc.go +++ b/src/strconv/atoc.go @@ -40,10 +40,10 @@ func convErr(err error, s string) (syntax, range_ error) { // away from the largest floating point number of the given component's size, // ParseComplex returns err.Err = ErrRange and c = ±Inf for the respective component. func ParseComplex(s string, bitSize int) (complex128, error) { - if bitSize != 64 && bitSize != 128 { - return 0, bitSizeError(fnParseComplex, s, bitSize) + size := 64 + if bitSize == 64 { + size = 32 // complex64 uses float32 parts } - size := bitSize >> 1 orig := s diff --git a/src/strconv/atoc_test.go b/src/strconv/atoc_test.go index aecc09d247c..4c1aad09000 100644 --- a/src/strconv/atoc_test.go +++ b/src/strconv/atoc_test.go @@ -212,13 +212,18 @@ func TestParseComplex(t *testing.T) { } } -func TestParseComplexInvalidBitSize(t *testing.T) { - _, err := ParseComplex("1+2i", 100) - const want = `strconv.ParseComplex: parsing "1+2i": invalid bit size 100` - if err == nil { - t.Fatalf("got nil error, want %q", want) - } - if err.Error() != want { - t.Fatalf("got error %q, want %q", err, want) +// Issue 42297: allow ParseComplex(s, not_32_or_64) for legacy reasons +func TestParseComplexIncorrectBitSize(t *testing.T) { + const s = "1.5e308+1.0e307i" + const want = 1.5e308 + 1.0e307i + + for _, bitSize := range []int{0, 10, 100, 256} { + c, err := ParseComplex(s, bitSize) + if err != nil { + t.Fatalf("ParseComplex(%q, %d) gave error %s", s, bitSize, err) + } + if c != want { + t.Fatalf("ParseComplex(%q, %d) = %g (expected %g)", s, bitSize, c, want) + } } } diff --git a/src/strconv/atof.go b/src/strconv/atof.go index a04f5621f63..9010a66ca89 100644 --- a/src/strconv/atof.go +++ b/src/strconv/atof.go @@ -688,9 +688,6 @@ func atof64(s string) (f float64, n int, err error) { // ParseFloat recognizes the strings "NaN", and the (possibly signed) strings "Inf" and "Infinity" // as their respective special floating point values. It ignores case when matching. func ParseFloat(s string, bitSize int) (float64, error) { - if bitSize != 32 && bitSize != 64 { - return 0, bitSizeError(fnParseFloat, s, bitSize) - } f, n, err := parseFloatPrefix(s, bitSize) if err == nil && n != len(s) { return 0, syntaxError(fnParseFloat, s) diff --git a/src/strconv/atof_test.go b/src/strconv/atof_test.go index cf439035063..3c058b9be5a 100644 --- a/src/strconv/atof_test.go +++ b/src/strconv/atof_test.go @@ -634,14 +634,20 @@ func TestRoundTrip32(t *testing.T) { t.Logf("tested %d float32's", count) } -func TestParseFloatInvalidBitSize(t *testing.T) { - _, err := ParseFloat("3.14", 100) - const want = `strconv.ParseFloat: parsing "3.14": invalid bit size 100` - if err == nil { - t.Fatalf("got nil error, want %q", want) - } - if err.Error() != want { - t.Fatalf("got error %q, want %q", err, want) +// Issue 42297: a lot of code in the wild accidentally calls ParseFloat(s, 10) +// or ParseFloat(s, 0), so allow bitSize values other than 32 and 64. +func TestParseFloatIncorrectBitSize(t *testing.T) { + const s = "1.5e308" + const want = 1.5e308 + + for _, bitSize := range []int{0, 10, 100, 128} { + f, err := ParseFloat(s, bitSize) + if err != nil { + t.Fatalf("ParseFloat(%q, %d) gave error %s", s, bitSize, err) + } + if f != want { + t.Fatalf("ParseFloat(%q, %d) = %g (expected %g)", s, bitSize, f, want) + } } } From 8eb846fd37eb7bded8a1cf6932be2c59069863e5 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Wed, 4 Nov 2020 00:26:15 +1100 Subject: [PATCH 338/403] cmd/compile,cmd/dist,cmd/go: enable pie buildmode for linux/riscv64 Enable pie as a buildmode for linux/riscv64, along with associated tests. Change-Id: I3fb0234d534dbeb96aa6cee6ae872304fbe02cf4 Reviewed-on: https://go-review.googlesource.com/c/go/+/267317 Trust: Joel Sing Reviewed-by: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot --- src/cmd/compile/internal/gc/main.go | 2 +- src/cmd/dist/test.go | 2 +- src/cmd/go/go_test.go | 2 +- src/cmd/internal/sys/supported.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 8b94c7f71b6..d1097e8236d 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -130,7 +130,7 @@ func hidePanic() { // supportsDynlink reports whether or not the code generator for the given // architecture supports the -shared and -dynlink flags. func supportsDynlink(arch *sys.Arch) bool { - return arch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.I386, sys.PPC64, sys.S390X) + return arch.InFamily(sys.AMD64, sys.ARM, sys.ARM64, sys.I386, sys.PPC64, sys.RISCV64, sys.S390X) } // timing data for compiler phases diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index d12a52b1cc2..f087aba2b99 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1021,7 +1021,7 @@ func (t *tester) supportedBuildmode(mode string) bool { case "pie": switch pair { case "aix/ppc64", - "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-s390x", + "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x", "android-amd64", "android-arm", "android-arm64", "android-386": return true case "darwin-amd64", "darwin-arm64": diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 7bbadd39746..91d5884036d 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -2022,7 +2022,7 @@ func TestBuildmodePIE(t *testing.T) { platform := fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH) switch platform { - case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", + case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x", "android/amd64", "android/arm", "android/arm64", "android/386", "freebsd/amd64", "windows/386", "windows/amd64", "windows/arm": diff --git a/src/cmd/internal/sys/supported.go b/src/cmd/internal/sys/supported.go index 69d75914406..ef7c017bd4a 100644 --- a/src/cmd/internal/sys/supported.go +++ b/src/cmd/internal/sys/supported.go @@ -86,7 +86,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool { case "pie": switch platform { - case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x", + case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x", "android/amd64", "android/arm", "android/arm64", "android/386", "freebsd/amd64", "darwin/amd64", "darwin/arm64", From 5ca43acdb3e27117e6994141e518b8d55e4d32aa Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Mon, 2 Nov 2020 03:58:08 +1100 Subject: [PATCH 339/403] runtime: allow physical page aligned stacks to be allocated Add a physPageAlignedStack boolean which if set, results in over allocation by a physical page, the allocation being rounded to physical page alignment and the unused memory surrounding the allocation being freed again. OpenBSD/octeon has 16KB physical pages and requires stacks to be physical page aligned in order for them to be remapped as MAP_STACK. This change allows Go to work on this platform. Based on a suggestion from mknyszek in issue #41008. Updates #40995 Fixes #41008 Change-Id: Ia5d652292b515916db473043b41f6030094461d8 Reviewed-on: https://go-review.googlesource.com/c/go/+/266919 Trust: Joel Sing Reviewed-by: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot --- src/runtime/mheap.go | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index b8429eee948..1855330da5f 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -44,6 +44,11 @@ const ( // Must be a multiple of the pageInUse bitmap element size and // must also evenly divide pagesPerArena. pagesPerReclaimerChunk = 512 + + // physPageAlignedStacks indicates whether stack allocations must be + // physical page aligned. This is a requirement for MAP_STACK on + // OpenBSD. + physPageAlignedStacks = GOOS == "openbsd" ) // Main malloc heap. @@ -1121,9 +1126,16 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass gp := getg() base, scav := uintptr(0), uintptr(0) + // On some platforms we need to provide physical page aligned stack + // allocations. Where the page size is less than the physical page + // size, we already manage to do this by default. + needPhysPageAlign := physPageAlignedStacks && typ == spanAllocStack && pageSize < physPageSize + // If the allocation is small enough, try the page cache! + // The page cache does not support aligned allocations, so we cannot use + // it if we need to provide a physical page aligned stack allocation. pp := gp.m.p.ptr() - if pp != nil && npages < pageCachePages/4 { + if !needPhysPageAlign && pp != nil && npages < pageCachePages/4 { c := &pp.pcache // If the cache is empty, refill it. @@ -1149,6 +1161,11 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // whole job done without the heap lock. lock(&h.lock) + if needPhysPageAlign { + // Overallocate by a physical page to allow for later alignment. + npages += physPageSize / pageSize + } + if base == 0 { // Try to acquire a base address. base, scav = h.pages.alloc(npages) @@ -1168,6 +1185,23 @@ func (h *mheap) allocSpan(npages uintptr, typ spanAllocType, spanclass spanClass // one now that we have the heap lock. s = h.allocMSpanLocked() } + + if needPhysPageAlign { + allocBase, allocPages := base, npages + base = alignUp(allocBase, physPageSize) + npages -= physPageSize / pageSize + + // Return memory around the aligned allocation. + spaceBefore := base - allocBase + if spaceBefore > 0 { + h.pages.free(allocBase, spaceBefore/pageSize) + } + spaceAfter := (allocPages-npages)*pageSize - spaceBefore + if spaceAfter > 0 { + h.pages.free(base+npages*pageSize, spaceAfter/pageSize) + } + } + unlock(&h.lock) HaveSpan: From 633f9e206045176a12c301eb2c249c1c1d9a5d2e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 2 Nov 2020 12:01:33 +0100 Subject: [PATCH 340/403] internal/poll: treat copy_file_range EIO as not-handled Fixes #42334 Change-Id: Ife51df4e7d2539a04393abfdec45e3f902975fca Reviewed-on: https://go-review.googlesource.com/c/go/+/266940 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor --- src/internal/poll/copy_file_range_linux.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/internal/poll/copy_file_range_linux.go b/src/internal/poll/copy_file_range_linux.go index 09de299ff71..24bee614a68 100644 --- a/src/internal/poll/copy_file_range_linux.go +++ b/src/internal/poll/copy_file_range_linux.go @@ -41,7 +41,7 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err // use copy_file_range(2) again. atomic.StoreInt32(©FileRangeSupported, 0) return 0, false, nil - case syscall.EXDEV, syscall.EINVAL, syscall.EOPNOTSUPP, syscall.EPERM: + case syscall.EXDEV, syscall.EINVAL, syscall.EIO, syscall.EOPNOTSUPP, syscall.EPERM: // Prior to Linux 5.3, it was not possible to // copy_file_range across file systems. Similarly to // the ENOSYS case above, if we see EXDEV, we have @@ -53,6 +53,9 @@ func CopyFileRange(dst, src *FD, remain int64) (written int64, handled bool, err // file. This is another case where no data has been // transfered, so we consider it unhandled. // + // If src and dst are on CIFS, we can see EIO. + // See issue #42334. + // // If the file is on NFS, we can see EOPNOTSUPP. // See issue #40731. // From 5f0fca1475e042a6e85f81ff6db676ec18805041 Mon Sep 17 00:00:00 2001 From: Jonathan Swinney Date: Mon, 2 Nov 2020 16:36:10 +0000 Subject: [PATCH 341/403] cmd/asm: rename arm64 instructions LDANDx to LDCLRx The LDANDx instructions were misleading because they correspond to the mnemonic LDCLRx as defined in the Arm Architecture Reference Manual for Armv8. This changes the assembler to use the same mnemonic as the GNU assembler and the manual. The instruction has the form: LDCLRx Rs, (Rb), Rt: *Rb -> Rt, Rs AND NOT(*Rb) -> *Rb Change-Id: I94ae003e99e817209bba1afe960e612bf3a0b410 Reviewed-on: https://go-review.googlesource.com/c/go/+/267138 Reviewed-by: Cherry Zhang Reviewed-by: fannie zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Trust: fannie zhang --- src/cmd/asm/internal/asm/testdata/arm64.s | 64 +++++++++---------- .../asm/internal/asm/testdata/arm64error.s | 48 +++++++------- src/cmd/internal/obj/arm64/a.out.go | 32 +++++----- src/cmd/internal/obj/arm64/anames.go | 32 +++++----- src/cmd/internal/obj/arm64/asm7.go | 34 +++++----- 5 files changed, 105 insertions(+), 105 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index 5547cf634cc..91e3a0ca0a4 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -681,38 +681,38 @@ again: LDADDLH R5, (RSP), R7 // e7036578 LDADDLB R5, (R6), R7 // c7006538 LDADDLB R5, (RSP), R7 // e7036538 - LDANDAD R5, (R6), R7 // c710a5f8 - LDANDAD R5, (RSP), R7 // e713a5f8 - LDANDAW R5, (R6), R7 // c710a5b8 - LDANDAW R5, (RSP), R7 // e713a5b8 - LDANDAH R5, (R6), R7 // c710a578 - LDANDAH R5, (RSP), R7 // e713a578 - LDANDAB R5, (R6), R7 // c710a538 - LDANDAB R5, (RSP), R7 // e713a538 - LDANDALD R5, (R6), R7 // c710e5f8 - LDANDALD R5, (RSP), R7 // e713e5f8 - LDANDALW R5, (R6), R7 // c710e5b8 - LDANDALW R5, (RSP), R7 // e713e5b8 - LDANDALH R5, (R6), R7 // c710e578 - LDANDALH R5, (RSP), R7 // e713e578 - LDANDALB R5, (R6), R7 // c710e538 - LDANDALB R5, (RSP), R7 // e713e538 - LDANDD R5, (R6), R7 // c71025f8 - LDANDD R5, (RSP), R7 // e71325f8 - LDANDW R5, (R6), R7 // c71025b8 - LDANDW R5, (RSP), R7 // e71325b8 - LDANDH R5, (R6), R7 // c7102578 - LDANDH R5, (RSP), R7 // e7132578 - LDANDB R5, (R6), R7 // c7102538 - LDANDB R5, (RSP), R7 // e7132538 - LDANDLD R5, (R6), R7 // c71065f8 - LDANDLD R5, (RSP), R7 // e71365f8 - LDANDLW R5, (R6), R7 // c71065b8 - LDANDLW R5, (RSP), R7 // e71365b8 - LDANDLH R5, (R6), R7 // c7106578 - LDANDLH R5, (RSP), R7 // e7136578 - LDANDLB R5, (R6), R7 // c7106538 - LDANDLB R5, (RSP), R7 // e7136538 + LDCLRAD R5, (R6), R7 // c710a5f8 + LDCLRAD R5, (RSP), R7 // e713a5f8 + LDCLRAW R5, (R6), R7 // c710a5b8 + LDCLRAW R5, (RSP), R7 // e713a5b8 + LDCLRAH R5, (R6), R7 // c710a578 + LDCLRAH R5, (RSP), R7 // e713a578 + LDCLRAB R5, (R6), R7 // c710a538 + LDCLRAB R5, (RSP), R7 // e713a538 + LDCLRALD R5, (R6), R7 // c710e5f8 + LDCLRALD R5, (RSP), R7 // e713e5f8 + LDCLRALW R5, (R6), R7 // c710e5b8 + LDCLRALW R5, (RSP), R7 // e713e5b8 + LDCLRALH R5, (R6), R7 // c710e578 + LDCLRALH R5, (RSP), R7 // e713e578 + LDCLRALB R5, (R6), R7 // c710e538 + LDCLRALB R5, (RSP), R7 // e713e538 + LDCLRD R5, (R6), R7 // c71025f8 + LDCLRD R5, (RSP), R7 // e71325f8 + LDCLRW R5, (R6), R7 // c71025b8 + LDCLRW R5, (RSP), R7 // e71325b8 + LDCLRH R5, (R6), R7 // c7102578 + LDCLRH R5, (RSP), R7 // e7132578 + LDCLRB R5, (R6), R7 // c7102538 + LDCLRB R5, (RSP), R7 // e7132538 + LDCLRLD R5, (R6), R7 // c71065f8 + LDCLRLD R5, (RSP), R7 // e71365f8 + LDCLRLW R5, (R6), R7 // c71065b8 + LDCLRLW R5, (RSP), R7 // e71365b8 + LDCLRLH R5, (R6), R7 // c7106578 + LDCLRLH R5, (RSP), R7 // e7136578 + LDCLRLB R5, (R6), R7 // c7106538 + LDCLRLB R5, (RSP), R7 // e7136538 LDEORAD R5, (R6), R7 // c720a5f8 LDEORAD R5, (RSP), R7 // e723a5f8 LDEORAW R5, (R6), R7 // c720a5b8 diff --git a/src/cmd/asm/internal/asm/testdata/arm64error.s b/src/cmd/asm/internal/asm/testdata/arm64error.s index 99e4d62d25b..e579f20836a 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64error.s +++ b/src/cmd/asm/internal/asm/testdata/arm64error.s @@ -123,14 +123,14 @@ TEXT errors(SB),$0 LDADDLW R5, (R6), ZR // ERROR "illegal destination register" LDADDLH R5, (R6), ZR // ERROR "illegal destination register" LDADDLB R5, (R6), ZR // ERROR "illegal destination register" - LDANDD R5, (R6), ZR // ERROR "illegal destination register" - LDANDW R5, (R6), ZR // ERROR "illegal destination register" - LDANDH R5, (R6), ZR // ERROR "illegal destination register" - LDANDB R5, (R6), ZR // ERROR "illegal destination register" - LDANDLD R5, (R6), ZR // ERROR "illegal destination register" - LDANDLW R5, (R6), ZR // ERROR "illegal destination register" - LDANDLH R5, (R6), ZR // ERROR "illegal destination register" - LDANDLB R5, (R6), ZR // ERROR "illegal destination register" + LDCLRD R5, (R6), ZR // ERROR "illegal destination register" + LDCLRW R5, (R6), ZR // ERROR "illegal destination register" + LDCLRH R5, (R6), ZR // ERROR "illegal destination register" + LDCLRB R5, (R6), ZR // ERROR "illegal destination register" + LDCLRLD R5, (R6), ZR // ERROR "illegal destination register" + LDCLRLW R5, (R6), ZR // ERROR "illegal destination register" + LDCLRLH R5, (R6), ZR // ERROR "illegal destination register" + LDCLRLB R5, (R6), ZR // ERROR "illegal destination register" LDEORD R5, (R6), ZR // ERROR "illegal destination register" LDEORW R5, (R6), ZR // ERROR "illegal destination register" LDEORH R5, (R6), ZR // ERROR "illegal destination register" @@ -163,22 +163,22 @@ TEXT errors(SB),$0 LDADDLW R5, (R6), RSP // ERROR "illegal destination register" LDADDLH R5, (R6), RSP // ERROR "illegal destination register" LDADDLB R5, (R6), RSP // ERROR "illegal destination register" - LDANDAD R5, (R6), RSP // ERROR "illegal destination register" - LDANDAW R5, (R6), RSP // ERROR "illegal destination register" - LDANDAH R5, (R6), RSP // ERROR "illegal destination register" - LDANDAB R5, (R6), RSP // ERROR "illegal destination register" - LDANDALD R5, (R6), RSP // ERROR "illegal destination register" - LDANDALW R5, (R6), RSP // ERROR "illegal destination register" - LDANDALH R5, (R6), RSP // ERROR "illegal destination register" - LDANDALB R5, (R6), RSP // ERROR "illegal destination register" - LDANDD R5, (R6), RSP // ERROR "illegal destination register" - LDANDW R5, (R6), RSP // ERROR "illegal destination register" - LDANDH R5, (R6), RSP // ERROR "illegal destination register" - LDANDB R5, (R6), RSP // ERROR "illegal destination register" - LDANDLD R5, (R6), RSP // ERROR "illegal destination register" - LDANDLW R5, (R6), RSP // ERROR "illegal destination register" - LDANDLH R5, (R6), RSP // ERROR "illegal destination register" - LDANDLB R5, (R6), RSP // ERROR "illegal destination register" + LDCLRAD R5, (R6), RSP // ERROR "illegal destination register" + LDCLRAW R5, (R6), RSP // ERROR "illegal destination register" + LDCLRAH R5, (R6), RSP // ERROR "illegal destination register" + LDCLRAB R5, (R6), RSP // ERROR "illegal destination register" + LDCLRALD R5, (R6), RSP // ERROR "illegal destination register" + LDCLRALW R5, (R6), RSP // ERROR "illegal destination register" + LDCLRALH R5, (R6), RSP // ERROR "illegal destination register" + LDCLRALB R5, (R6), RSP // ERROR "illegal destination register" + LDCLRD R5, (R6), RSP // ERROR "illegal destination register" + LDCLRW R5, (R6), RSP // ERROR "illegal destination register" + LDCLRH R5, (R6), RSP // ERROR "illegal destination register" + LDCLRB R5, (R6), RSP // ERROR "illegal destination register" + LDCLRLD R5, (R6), RSP // ERROR "illegal destination register" + LDCLRLW R5, (R6), RSP // ERROR "illegal destination register" + LDCLRLH R5, (R6), RSP // ERROR "illegal destination register" + LDCLRLB R5, (R6), RSP // ERROR "illegal destination register" LDEORAD R5, (R6), RSP // ERROR "illegal destination register" LDEORAW R5, (R6), RSP // ERROR "illegal destination register" LDEORAH R5, (R6), RSP // ERROR "illegal destination register" diff --git a/src/cmd/internal/obj/arm64/a.out.go b/src/cmd/internal/obj/arm64/a.out.go index 5844b71ca73..1d1bea505cd 100644 --- a/src/cmd/internal/obj/arm64/a.out.go +++ b/src/cmd/internal/obj/arm64/a.out.go @@ -617,22 +617,6 @@ const ( ALDADDLD ALDADDLH ALDADDLW - ALDANDAB - ALDANDAD - ALDANDAH - ALDANDAW - ALDANDALB - ALDANDALD - ALDANDALH - ALDANDALW - ALDANDB - ALDANDD - ALDANDH - ALDANDW - ALDANDLB - ALDANDLD - ALDANDLH - ALDANDLW ALDAR ALDARB ALDARH @@ -643,6 +627,22 @@ const ( ALDAXRB ALDAXRH ALDAXRW + ALDCLRAB + ALDCLRAD + ALDCLRAH + ALDCLRAW + ALDCLRALB + ALDCLRALD + ALDCLRALH + ALDCLRALW + ALDCLRB + ALDCLRD + ALDCLRH + ALDCLRW + ALDCLRLB + ALDCLRLD + ALDCLRLH + ALDCLRLW ALDEORAB ALDEORAD ALDEORAH diff --git a/src/cmd/internal/obj/arm64/anames.go b/src/cmd/internal/obj/arm64/anames.go index fb216f9a946..a98f8c7ed54 100644 --- a/src/cmd/internal/obj/arm64/anames.go +++ b/src/cmd/internal/obj/arm64/anames.go @@ -111,22 +111,6 @@ var Anames = []string{ "LDADDLD", "LDADDLH", "LDADDLW", - "LDANDAB", - "LDANDAD", - "LDANDAH", - "LDANDAW", - "LDANDALB", - "LDANDALD", - "LDANDALH", - "LDANDALW", - "LDANDB", - "LDANDD", - "LDANDH", - "LDANDW", - "LDANDLB", - "LDANDLD", - "LDANDLH", - "LDANDLW", "LDAR", "LDARB", "LDARH", @@ -137,6 +121,22 @@ var Anames = []string{ "LDAXRB", "LDAXRH", "LDAXRW", + "LDCLRAB", + "LDCLRAD", + "LDCLRAH", + "LDCLRAW", + "LDCLRALB", + "LDCLRALD", + "LDCLRALH", + "LDCLRALW", + "LDCLRB", + "LDCLRD", + "LDCLRH", + "LDCLRW", + "LDCLRLB", + "LDCLRLD", + "LDCLRLH", + "LDCLRLW", "LDEORAB", "LDEORAD", "LDEORAH", diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go index 4fc62d5c7f4..1a359f1921b 100644 --- a/src/cmd/internal/obj/arm64/asm7.go +++ b/src/cmd/internal/obj/arm64/asm7.go @@ -107,22 +107,22 @@ var atomicLDADD = map[obj.As]uint32{ ALDADDLW: 2<<30 | 0x1c3<<21 | 0x00<<10, ALDADDLH: 1<<30 | 0x1c3<<21 | 0x00<<10, ALDADDLB: 0<<30 | 0x1c3<<21 | 0x00<<10, - ALDANDAD: 3<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDAW: 2<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDAH: 1<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDAB: 0<<30 | 0x1c5<<21 | 0x04<<10, - ALDANDALD: 3<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDALW: 2<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDALH: 1<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDALB: 0<<30 | 0x1c7<<21 | 0x04<<10, - ALDANDD: 3<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDW: 2<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDH: 1<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDB: 0<<30 | 0x1c1<<21 | 0x04<<10, - ALDANDLD: 3<<30 | 0x1c3<<21 | 0x04<<10, - ALDANDLW: 2<<30 | 0x1c3<<21 | 0x04<<10, - ALDANDLH: 1<<30 | 0x1c3<<21 | 0x04<<10, - ALDANDLB: 0<<30 | 0x1c3<<21 | 0x04<<10, + ALDCLRAD: 3<<30 | 0x1c5<<21 | 0x04<<10, + ALDCLRAW: 2<<30 | 0x1c5<<21 | 0x04<<10, + ALDCLRAH: 1<<30 | 0x1c5<<21 | 0x04<<10, + ALDCLRAB: 0<<30 | 0x1c5<<21 | 0x04<<10, + ALDCLRALD: 3<<30 | 0x1c7<<21 | 0x04<<10, + ALDCLRALW: 2<<30 | 0x1c7<<21 | 0x04<<10, + ALDCLRALH: 1<<30 | 0x1c7<<21 | 0x04<<10, + ALDCLRALB: 0<<30 | 0x1c7<<21 | 0x04<<10, + ALDCLRD: 3<<30 | 0x1c1<<21 | 0x04<<10, + ALDCLRW: 2<<30 | 0x1c1<<21 | 0x04<<10, + ALDCLRH: 1<<30 | 0x1c1<<21 | 0x04<<10, + ALDCLRB: 0<<30 | 0x1c1<<21 | 0x04<<10, + ALDCLRLD: 3<<30 | 0x1c3<<21 | 0x04<<10, + ALDCLRLW: 2<<30 | 0x1c3<<21 | 0x04<<10, + ALDCLRLH: 1<<30 | 0x1c3<<21 | 0x04<<10, + ALDCLRLB: 0<<30 | 0x1c3<<21 | 0x04<<10, ALDEORAD: 3<<30 | 0x1c5<<21 | 0x08<<10, ALDEORAW: 2<<30 | 0x1c5<<21 | 0x08<<10, ALDEORAH: 1<<30 | 0x1c5<<21 | 0x08<<10, @@ -4028,7 +4028,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) { o1 |= uint32(p.From.Reg&31) << 5 o1 |= uint32(p.To.Reg & 31) - case 47: // SWPx/LDADDx/LDANDx/LDEORx/LDORx/CASx Rs, (Rb), Rt + case 47: // SWPx/LDADDx/LDCLRx/LDEORx/LDORx/CASx Rs, (Rb), Rt rs := p.From.Reg rt := p.RegTo2 rb := p.To.Reg From 594b4a3bfef24ed207e058fb522ed51e65cb93bf Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Wed, 4 Nov 2020 00:29:39 +1100 Subject: [PATCH 342/403] cmd/dist: enable additional cgo tests on openbsd architectures OpenBSD gained __thread support quite some time ago. Change-Id: I7de0a5c0c4de1a7ce59e48ac939fc2daf56be8f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/267318 Trust: Joel Sing Reviewed-by: Cherry Zhang Run-TryBot: Joel Sing TryBot-Result: Go Bot --- src/cmd/dist/test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index f087aba2b99..5e3711b0c80 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1095,7 +1095,6 @@ func (t *tester) cgoTest(dt *distTest) error { pair := gohostos + "-" + goarch switch pair { case "darwin-amd64", "darwin-arm64", - "openbsd-386", "openbsd-amd64", "windows-386", "windows-amd64": // test linkmode=external, but __thread not supported, so skip testtls. if !t.extLink() { @@ -1118,7 +1117,8 @@ func (t *tester) cgoTest(dt *distTest) error { "dragonfly-amd64", "freebsd-386", "freebsd-amd64", "freebsd-arm", "linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-riscv64", "linux-s390x", - "netbsd-386", "netbsd-amd64": + "netbsd-386", "netbsd-amd64", + "openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64": cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=external") From 3a1d84b393e4192c413a45824304381625c09fbc Mon Sep 17 00:00:00 2001 From: Curtis La Graff Date: Tue, 3 Nov 2020 20:26:17 +0000 Subject: [PATCH 343/403] cmd/go/internal/modfetch/codehost: add support for new fossil info hash prefix A recent update of the Fossil SCM application changes the line prefix when the fossil info command is used. Instead of the revision hash starting with "uuid:", it has been changed to "hash:". Fossil check-in introducing this change: https://fossil-scm.org/home/info/8ad5e4690854a81a To support older and new versions, fossilParseStat will now check for either version of the prefix when attempting to find the line containing the hash of the desired revision. Fixes #42323 Change-Id: I6eff49f9989b37b295322a8569e222a1fd02f6e3 GitHub-Last-Rev: f4e6652307732fd3213684f13e42d17528271d88 GitHub-Pull-Request: golang/go#42324 Reviewed-on: https://go-review.googlesource.com/c/go/+/267080 Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Trust: Dmitri Shuralyov Trust: Bryan C. Mills Reviewed-by: Bryan C. Mills --- src/cmd/go/internal/modfetch/codehost/vcs.go | 2 +- src/cmd/go/testdata/script/mod_get_fossil.txt | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/testdata/script/mod_get_fossil.txt diff --git a/src/cmd/go/internal/modfetch/codehost/vcs.go b/src/cmd/go/internal/modfetch/codehost/vcs.go index ec97fc7e1bd..e67ee94ad87 100644 --- a/src/cmd/go/internal/modfetch/codehost/vcs.go +++ b/src/cmd/go/internal/modfetch/codehost/vcs.go @@ -568,7 +568,7 @@ func bzrParseStat(rev, out string) (*RevInfo, error) { func fossilParseStat(rev, out string) (*RevInfo, error) { for _, line := range strings.Split(out, "\n") { - if strings.HasPrefix(line, "uuid:") { + if strings.HasPrefix(line, "uuid:") || strings.HasPrefix(line, "hash:") { f := strings.Fields(line) if len(f) != 5 || len(f[1]) != 40 || f[4] != "UTC" { return nil, vcsErrorf("unexpected response from fossil info: %q", line) diff --git a/src/cmd/go/testdata/script/mod_get_fossil.txt b/src/cmd/go/testdata/script/mod_get_fossil.txt new file mode 100644 index 00000000000..3482e68da1d --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_fossil.txt @@ -0,0 +1,26 @@ +[!net] skip +[!exec:fossil] skip + +# Regression test for 'go get' to ensure repositories +# provided by fossil v2.12 and up are able to be fetched +# and parsed correctly. +# Verifies golang.org/issue/42323. + + +env GO111MODULE=on +env GOPROXY=direct +env GOSUMDB=off + +# 'go get' for the fossil repo will fail if fossil +# is unable to determine your fossil user. Easiest +# way to set it for use by 'go get' is specifying +# a any non-empty $USER; the value doesn't otherwise matter. +env USER=fossiluser + +# Attempting to get the latest version of a fossil repo. +go get vcs-test.golang.org/fossil/hello.fossil +! stderr 'unexpected response from fossil info' +grep 'vcs-test.golang.org/fossil/hello.fossil' go.mod + +-- go.mod -- +module x From e4b4e4b733624a4922741f13dcdaa493c01fe9fd Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Sun, 1 Nov 2020 15:40:37 -0500 Subject: [PATCH 344/403] race.bash: add darwin/arm64 Race detector support was added in previous CLs. Updates #38485. Change-Id: Ie9ae69406ff4770f573c2287bfbbb0421769b3ce Reviewed-on: https://go-review.googlesource.com/c/go/+/267098 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/race.bash | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/race.bash b/src/race.bash index e83c175df3b..e2b96bcffef 100755 --- a/src/race.bash +++ b/src/race.bash @@ -9,14 +9,13 @@ set -e function usage { - echo 'race detector is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64 and darwin/amd64' 1>&2 + echo 'race detector is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64, and darwin/arm64' 1>&2 exit 1 } case $(uname) in "Darwin") - # why Apple? why? - if sysctl machdep.cpu.extfeatures | grep -qv EM64T; then + if [ $(uname -m) != "x86_64" ] && [ $(uname -m) != "arm64" ]; then usage fi ;; From f532f19d94365d803e68568eb82d0dd19c81cc5b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 4 Nov 2020 06:55:59 -0500 Subject: [PATCH 345/403] os: avoid nil returns from Readdirnames, Readdir, ReadDir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The refactoring of this code while adding ReadDir stopped pre-allocating a 100-entry slice for the results. That seemed like a good idea in general, since many directories have nowhere near 100 entries, but it had the side effect of returning a nil slice for an empty directory. Some “golden” tests that are too sensitive about nil vs not inside Google broke because Readdirnames(-1) was now returning nil instead of []string{} on an empty directory. It seems likely there are other such tests in the wild, and it doesn't seem worth breaking them. This commit restores the non-nil-ness of the old result, without restoring the excessive preallocation. Fixes #42367. Change-Id: I2be72030ac703346e859a97c2d4e456fadfce9b2 Reviewed-on: https://go-review.googlesource.com/c/go/+/267637 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/os/dir.go | 16 ++++++++++++++++ src/os/os_test.go | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/os/dir.go b/src/os/dir.go index b56d9984592..1d90b970e7a 100644 --- a/src/os/dir.go +++ b/src/os/dir.go @@ -36,6 +36,12 @@ func (f *File) Readdir(n int) ([]FileInfo, error) { return nil, ErrInvalid } _, _, infos, err := f.readdir(n, readdirFileInfo) + if infos == nil { + // Readdir has historically always returned a non-nil empty slice, never nil, + // even on error (except misuse with nil receiver above). + // Keep it that way to avoid breaking overly sensitive callers. + infos = []FileInfo{} + } return infos, err } @@ -59,6 +65,12 @@ func (f *File) Readdirnames(n int) (names []string, err error) { return nil, ErrInvalid } names, _, _, err = f.readdir(n, readdirName) + if names == nil { + // Readdirnames has historically always returned a non-nil empty slice, never nil, + // even on error (except misuse with nil receiver above). + // Keep it that way to avoid breaking overly sensitive callers. + names = []string{} + } return names, err } @@ -81,6 +93,10 @@ func (f *File) ReadDir(n int) ([]DirEntry, error) { return nil, ErrInvalid } _, dirents, _, err := f.readdir(n, readdirDirEntry) + if dirents == nil { + // Match Readdir and Readdirnames: don't return nil slices. + dirents = []DirEntry{} + } return dirents, err } diff --git a/src/os/os_test.go b/src/os/os_test.go index 378ddf58dd4..a1c05788876 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -330,6 +330,9 @@ func testReaddirnames(dir string, contents []string, t *testing.T) { t.Error("could not find", m) } } + if s == nil { + t.Error("Readdirnames returned nil instead of empty slice") + } } func testReaddir(dir string, contents []string, t *testing.T) { @@ -360,6 +363,9 @@ func testReaddir(dir string, contents []string, t *testing.T) { t.Error("could not find", m) } } + if s == nil { + t.Error("Readdir returned nil instead of empty slice") + } } func testReadDir(dir string, contents []string, t *testing.T) { @@ -408,21 +414,27 @@ func testReadDir(dir string, contents []string, t *testing.T) { t.Error("could not find", m) } } + if s == nil { + t.Error("ReadDir returned nil instead of empty slice") + } } func TestReaddirnames(t *testing.T) { testReaddirnames(".", dot, t) testReaddirnames(sysdir.name, sysdir.files, t) + testReaddirnames(t.TempDir(), nil, t) } func TestReaddir(t *testing.T) { testReaddir(".", dot, t) testReaddir(sysdir.name, sysdir.files, t) + testReaddir(t.TempDir(), nil, t) } func TestReadDir(t *testing.T) { testReadDir(".", dot, t) testReadDir(sysdir.name, sysdir.files, t) + testReadDir(t.TempDir(), nil, t) } func benchmarkReaddirname(path string, b *testing.B) { From 5ed81a3d14aa4eda5de87d7fe074b4c913b58511 Mon Sep 17 00:00:00 2001 From: "Paul E. Murphy" Date: Tue, 3 Nov 2020 16:59:25 -0600 Subject: [PATCH 346/403] cmd/asm: fix rlwnm reg,reg,const,reg encoding on ppc64 The wrong value for the first reg parameter was selected. Likewise the wrong opcode was selected. This should match rlwnm (rrr type), not rlwinm (irr type). Similarly, fix the optab matching rules so clrlslwi does not match reg,reg,const,reg arguments. This is not a valid operand combination for clrlslwi. Fixes #42368 Change-Id: I4eb16d45a760b9fd3f497ef9863f82465351d39f Reviewed-on: https://go-review.googlesource.com/c/go/+/267421 Reviewed-by: Cherry Zhang Trust: Lynn Boger --- src/cmd/asm/internal/asm/testdata/ppc64.s | 2 ++ src/cmd/internal/obj/ppc64/asm9.go | 26 ++++++----------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/ppc64.s b/src/cmd/asm/internal/asm/testdata/ppc64.s index 2b1191c44b3..8f6eb14f73c 100644 --- a/src/cmd/asm/internal/asm/testdata/ppc64.s +++ b/src/cmd/asm/internal/asm/testdata/ppc64.s @@ -282,7 +282,9 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0 RLWMI $7, R3, $65535, R6 // 50663c3e RLWMICC $7, R3, $65535, R6 // 50663c3f RLWNM $3, R4, $7, R6 // 54861f7e + RLWNM R3, R4, $7, R6 // 5c861f7e RLWNMCC $3, R4, $7, R6 // 54861f7f + RLWNMCC R3, R4, $7, R6 // 5c861f7f RLDMI $0, R4, $7, R6 // 7886076c RLDMICC $0, R4, $7, R6 // 7886076d RLDIMI $0, R4, $7, R6 // 788601cc diff --git a/src/cmd/internal/obj/ppc64/asm9.go b/src/cmd/internal/obj/ppc64/asm9.go index 090fefb4d8b..775d27d8e80 100644 --- a/src/cmd/internal/obj/ppc64/asm9.go +++ b/src/cmd/internal/obj/ppc64/asm9.go @@ -174,6 +174,7 @@ var optab = []Optab{ {ASRAD, C_SCON, C_NONE, C_NONE, C_REG, 56, 4, 0}, {ARLWMI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0}, {ARLWMI, C_REG, C_REG, C_LCON, C_REG, 63, 4, 0}, + {ACLRLSLWI, C_SCON, C_REG, C_LCON, C_REG, 62, 4, 0}, {ARLDMI, C_SCON, C_REG, C_LCON, C_REG, 30, 4, 0}, {ARLDC, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0}, {ARLDCL, C_SCON, C_REG, C_LCON, C_REG, 29, 4, 0}, @@ -1911,7 +1912,6 @@ func buildop(ctxt *obj.Link) { opset(ARLWMICC, r0) opset(ARLWNM, r0) opset(ARLWNMCC, r0) - opset(ACLRLSLWI, r0) case ARLDMI: opset(ARLDMICC, r0) @@ -2010,6 +2010,7 @@ func buildop(ctxt *obj.Link) { AADDEX, ACMPEQB, AECIWX, + ACLRLSLWI, obj.ANOP, obj.ATEXT, obj.AUNDEF, @@ -3413,25 +3414,10 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) { } case 63: /* rlwmi b,s,$mask,a */ - v := c.regoff(&p.From) - switch p.As { - case ACLRLSLWI: - n := c.regoff(p.GetFrom3()) - if n > v || v >= 32 { - // Message will match operands from the ISA even though in the - // code it uses 'v' - c.ctxt.Diag("Invalid n or b for CLRLSLWI: %x %x\n%v", v, n, p) - } - // This is an extended mnemonic described in the ISA C.8.2 - // clrlslwi ra,rs,b,n -> rlwinm ra,rs,n,b-n,31-n - // It generates the rlwinm directly here. - o1 = OP_RLW(OP_RLWINM, uint32(p.To.Reg), uint32(p.Reg), uint32(n), uint32(v-n), uint32(31-n)) - default: - var mask [2]uint8 - c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) - o1 = AOP_RRR(c.opirr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(v)) - o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 - } + var mask [2]uint8 + c.maskgen(p, mask[:], uint32(c.regoff(p.GetFrom3()))) + o1 = AOP_RRR(c.oprrr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg)) + o1 |= (uint32(mask[0])&31)<<6 | (uint32(mask[1])&31)<<1 case 64: /* mtfsf fr[, $m] {,fpcsr} */ var v int32 From fd841f65368906923e287afab91857043036459d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 29 Oct 2020 12:20:53 -0400 Subject: [PATCH 347/403] path/filepath: add WalkDir WalkDir is like Walk but can use ReadDir to read directories, instead of Readdirnames + Lstat on every entry, which is usually a significant performance improvement. (The Lstat can still happen if the walk function calls d.Info.) Fixes #42027. Change-Id: Ie11024b23be2656e320d41fd81ff0d8810aa729e Reviewed-on: https://go-review.googlesource.com/c/go/+/266240 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/path/filepath/export_test.go | 2 + src/path/filepath/path.go | 213 +++++++++++++++++++++++++++---- src/path/filepath/path_test.go | 89 ++++++++----- 3 files changed, 250 insertions(+), 54 deletions(-) diff --git a/src/path/filepath/export_test.go b/src/path/filepath/export_test.go index 0cf9e3bca11..e7ad7dd01a1 100644 --- a/src/path/filepath/export_test.go +++ b/src/path/filepath/export_test.go @@ -5,3 +5,5 @@ package filepath var LstatP = &lstat + +type DirEntryFromInfo = dirEntryFromInfo diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go index dffd27db146..3f7e5c713dc 100644 --- a/src/path/filepath/path.go +++ b/src/path/filepath/path.go @@ -336,25 +336,130 @@ func Rel(basepath, targpath string) (string, error) { // as an error by any function. var SkipDir = errors.New("skip this directory") -// WalkFunc is the type of the function called for each file or directory -// visited by Walk. The path argument contains the argument to Walk as a -// prefix; that is, if Walk is called with "dir", which is a directory -// containing the file "a", the walk function will be called with argument -// "dir/a". The info argument is the fs.FileInfo for the named path. +// WalkDirFunc is the type of the function called by WalkDir to visit +// each each file or directory. // -// If there was a problem walking to the file or directory named by path, the -// incoming error will describe the problem and the function can decide how -// to handle that error (and Walk will not descend into that directory). In the -// case of an error, the info argument will be nil. If an error is returned, -// processing stops. The sole exception is when the function returns the special -// value SkipDir. If the function returns SkipDir when invoked on a directory, -// Walk skips the directory's contents entirely. If the function returns SkipDir -// when invoked on a non-directory file, Walk skips the remaining files in the -// containing directory. +// The path argument contains the argument to Walk as a prefix. +// That is, if Walk is called with root argument "dir" and finds a file +// named "a" in that directory, the walk function will be called with +// argument "dir/a". +// +// The directory and file are joined with Join, which may clean the +// directory name: if Walk is called with the root argument "x/../dir" +// and finds a file named "a" in that directory, the walk function will +// be called with argument "dir/a", not "x/../dir/a". +// +// The d argument is the fs.DirEntry for the named path. +// +// The error result returned by the function controls how WalkDir +// continues. If the function returns the special value SkipDir, WalkDir +// skips the current directory (path if d.IsDir() is true, otherwise +// path's parent directory). Otherwise, if the function returns a non-nil +// error, WalkDir stops entirely and returns that error. +// +// The err argument reports an error related to path, signaling that +// WalkDir will not walk into that directory. The function can decide how +// to handle that error; as described earlier, returning the error will +// cause WalkDir to stop walking the entire tree. +// +// WalkDir calls the function with a non-nil err argument in two cases. +// +// First, if the initial os.Lstat on the root directory fails, WalkDir +// calls the function with path set to root, d set to nil, and err set to +// the error from os.Lstat. +// +// Second, if a directory's ReadDir method fails, WalkDir calls the +// function with path set to the directory's path, d set to an +// fs.DirEntry describing the directory, and err set to the error from +// ReadDir. In this second case, the function is called twice with the +// path of the directory: the first call is before the directory read is +// attempted and has err set to nil, giving the function a chance to +// return SkipDir and avoid the ReadDir entirely. The second call is +// after a failed ReadDir and reports the error from ReadDir. +// (If ReadDir succeeds, there is no second call.) +// +// The differences between WalkDirFunc compared to WalkFunc are: +// +// - The second argument has type fs.DirEntry instead of fs.FileInfo. +// - The function is called before reading a directory, to allow SkipDir +// to bypass the directory read entirely. +// - If a directory read fails, the function is called a second time +// for that directory to report the error. +// +type WalkDirFunc func(path string, d fs.DirEntry, err error) error + +// WalkFunc is the type of the function called by Walk to visit each each +// file or directory. +// +// The path argument contains the argument to Walk as a prefix. +// That is, if Walk is called with root argument "dir" and finds a file +// named "a" in that directory, the walk function will be called with +// argument "dir/a". +// +// The directory and file are joined with Join, which may clean the +// directory name: if Walk is called with the root argument "x/../dir" +// and finds a file named "a" in that directory, the walk function will +// be called with argument "dir/a", not "x/../dir/a". +// +// The info argument is the fs.FileInfo for the named path. +// +// The error result returned by the function controls how Walk continues. +// If the function returns the special value SkipDir, Walk skips the +// current directory (path if info.IsDir() is true, otherwise path's +// parent directory). Otherwise, if the function returns a non-nil error, +// Walk stops entirely and returns that error. +// +// The err argument reports an error related to path, signaling that Walk +// will not walk into that directory. The function can decide how to +// handle that error; as described earlier, returning the error will +// cause Walk to stop walking the entire tree. +// +// Walk calls the function with a non-nil err argument in two cases. +// +// First, if an os.Lstat on the root directory or any directory or file +// in the tree fails, Walk calls the function with path set to that +// directory or file's path, info set to nil, and err set to the error +// from os.Lstat. +// +// Second, if a directory's Readdirnames method fails, Walk calls the +// function with path set to the directory's path, info, set to an +// fs.FileInfo describing the directory, and err set to the error from +// Readdirnames. type WalkFunc func(path string, info fs.FileInfo, err error) error var lstat = os.Lstat // for testing +// walkDir recursively descends path, calling walkDirFn. +func walkDir(path string, d fs.DirEntry, walkDirFn WalkDirFunc) error { + if err := walkDirFn(path, d, nil); err != nil || !d.IsDir() { + if err == SkipDir && d.IsDir() { + // Successfully skipped directory. + err = nil + } + return err + } + + dirs, err := readDir(path) + if err != nil { + // Second call, to report ReadDir error. + err = walkDirFn(path, d, err) + if err != nil { + return err + } + } + + for _, d1 := range dirs { + path1 := Join(path, d1.Name()) + if err := walkDir(path1, d1, walkDirFn); err != nil { + if err == SkipDir { + break + } + return err + } + } + return nil +} + // walk recursively descends path, calling walkFn. func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { if !info.IsDir() { @@ -393,18 +498,23 @@ func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { return nil } -// Walk walks the file tree rooted at root, calling walkFn for each file or -// directory in the tree, including root. All errors that arise visiting files -// and directories are filtered by walkFn. The files are walked in lexical -// order, which makes the output deterministic but means that for very -// large directories Walk can be inefficient. -// Walk does not follow symbolic links. -func Walk(root string, walkFn WalkFunc) error { +// WalkDir walks the file tree rooted at root, calling fn for each file or +// directory in the tree, including root. +// +// All errors that arise visiting files and directories are filtered by fn: +// see the WalkDirFunc documentation for details. +// +// The files are walked in lexical order, which makes the output deterministic +// but requires WalkDir to read an entire directory into memory before proceeding +// to walk that directory. +// +// WalkDir does not follow symbolic links. +func WalkDir(root string, fn WalkDirFunc) error { info, err := os.Lstat(root) if err != nil { - err = walkFn(root, nil, err) + err = fn(root, nil, err) } else { - err = walk(root, info, walkFn) + err = walkDir(root, &dirEntryFromInfo{info}, fn) } if err == SkipDir { return nil @@ -412,8 +522,63 @@ func Walk(root string, walkFn WalkFunc) error { return err } -// readDirNames reads the directory named by dirname and returns +type dirEntryFromInfo struct { + fs.FileInfo +} + +func (e *dirEntryFromInfo) Type() fs.FileMode { + return e.Mode().Type() +} + +func (e *dirEntryFromInfo) Info() (fs.FileInfo, error) { + return e.FileInfo, nil +} + +// Walk walks the file tree rooted at root, calling fn for each file or +// directory in the tree, including root. +// +// All errors that arise visiting files and directories are filtered by fn: +// see the WalkFunc documentation for details. +// +// The files are walked in lexical order, which makes the output deterministic +// but requires Walk to read an entire directory into memory before proceeding +// to walk that directory. +// +// Walk does not follow symbolic links. +// +// Walk is less efficient than WalkDir, introduced in Go 1.16, +// which avoids calling os.Lstat on every visited file or directory. +func Walk(root string, fn WalkFunc) error { + info, err := os.Lstat(root) + if err != nil { + err = fn(root, nil, err) + } else { + err = walk(root, info, fn) + } + if err == SkipDir { + return nil + } + return err +} + +// readDir reads the directory named by dirname and returns // a sorted list of directory entries. +func readDir(dirname string) ([]fs.DirEntry, error) { + f, err := os.Open(dirname) + if err != nil { + return nil, err + } + dirs, err := f.ReadDir(-1) + f.Close() + if err != nil { + return nil, err + } + sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() }) + return dirs, nil +} + +// readDirNames reads the directory named by dirname and returns +// a sorted list of directory entry names. func readDirNames(dirname string) ([]string, error) { f, err := os.Open(dirname) if err != nil { diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index 7dc8b60c28c..af6b69de099 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -394,8 +394,8 @@ func checkMarks(t *testing.T, report bool) { // Assumes that each node name is unique. Good enough for a test. // If clear is true, any incoming error is cleared before return. The errors // are always accumulated, though. -func mark(info fs.FileInfo, err error, errors *[]error, clear bool) error { - name := info.Name() +func mark(d fs.DirEntry, err error, errors *[]error, clear bool) error { + name := d.Name() walkTree(tree, tree.name, func(path string, n *Node) { if n.name == name { n.mark++ @@ -432,6 +432,19 @@ func chtmpdir(t *testing.T) (restore func()) { } func TestWalk(t *testing.T) { + walk := func(root string, fn filepath.WalkDirFunc) error { + return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { + return fn(path, &filepath.DirEntryFromInfo{info}, err) + }) + } + testWalk(t, walk, 1) +} + +func TestWalkDir(t *testing.T) { + testWalk(t, filepath.WalkDir, 2) +} + +func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVisit int) { if runtime.GOOS == "ios" { restore := chtmpdir(t) defer restore() @@ -455,11 +468,11 @@ func TestWalk(t *testing.T) { makeTree(t) errors := make([]error, 0, 10) clear := true - markFn := func(path string, info fs.FileInfo, err error) error { - return mark(info, err, &errors, clear) + markFn := func(path string, d fs.DirEntry, err error) error { + return mark(d, err, &errors, clear) } // Expect no errors. - err = filepath.Walk(tree.name, markFn) + err = walk(tree.name, markFn) if err != nil { t.Fatalf("no error expected, found: %s", err) } @@ -469,10 +482,17 @@ func TestWalk(t *testing.T) { checkMarks(t, true) errors = errors[0:0] - // Test permission errors. Only possible if we're not root - // and only on some file systems (AFS, FAT). To avoid errors during - // all.bash on those file systems, skip during go test -short. - if os.Getuid() > 0 && !testing.Short() { + t.Run("PermErr", func(t *testing.T) { + // Test permission errors. Only possible if we're not root + // and only on some file systems (AFS, FAT). To avoid errors during + // all.bash on those file systems, skip during go test -short. + if os.Getuid() == 0 { + t.Skip("skipping as root") + } + if testing.Short() { + t.Skip("skipping in short mode") + } + // introduce 2 errors: chmod top-level directories to 0 os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0) @@ -482,9 +502,9 @@ func TestWalk(t *testing.T) { markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself - tree.entries[1].mark-- - tree.entries[3].mark-- - err := filepath.Walk(tree.name, markFn) + tree.entries[1].mark -= errVisit + tree.entries[3].mark -= errVisit + err := walk(tree.name, markFn) if err != nil { t.Fatalf("expected no error return from Walk, got %s", err) } @@ -500,10 +520,10 @@ func TestWalk(t *testing.T) { markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself - tree.entries[1].mark-- - tree.entries[3].mark-- + tree.entries[1].mark -= errVisit + tree.entries[3].mark -= errVisit clear = false // error will stop processing - err = filepath.Walk(tree.name, markFn) + err = walk(tree.name, markFn) if err == nil { t.Fatalf("expected error return from Walk") } @@ -517,7 +537,7 @@ func TestWalk(t *testing.T) { // restore permissions os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770) - } + }) } func touch(t *testing.T, name string) { @@ -544,7 +564,7 @@ func TestWalkSkipDirOnFile(t *testing.T) { touch(t, filepath.Join(td, "dir/foo2")) sawFoo2 := false - walker := func(path string, info fs.FileInfo, err error) error { + walker := func(path string) error { if strings.HasSuffix(path, "foo2") { sawFoo2 = true } @@ -553,22 +573,31 @@ func TestWalkSkipDirOnFile(t *testing.T) { } return nil } + walkFn := func(path string, _ fs.FileInfo, _ error) error { return walker(path) } + walkDirFn := func(path string, _ fs.DirEntry, _ error) error { return walker(path) } - err = filepath.Walk(td, walker) - if err != nil { - t.Fatal(err) - } - if sawFoo2 { - t.Errorf("SkipDir on file foo1 did not block processing of foo2") + check := func(t *testing.T, walk func(root string) error, root string) { + t.Helper() + sawFoo2 = false + err = walk(root) + if err != nil { + t.Fatal(err) + } + if sawFoo2 { + t.Errorf("SkipDir on file foo1 did not block processing of foo2") + } } - err = filepath.Walk(filepath.Join(td, "dir"), walker) - if err != nil { - t.Fatal(err) - } - if sawFoo2 { - t.Errorf("SkipDir on file foo1 did not block processing of foo2") - } + t.Run("Walk", func(t *testing.T) { + Walk := func(root string) error { return filepath.Walk(td, walkFn) } + check(t, Walk, td) + check(t, Walk, filepath.Join(td, "dir")) + }) + t.Run("WalkDir", func(t *testing.T) { + WalkDir := func(root string) error { return filepath.WalkDir(td, walkDirFn) } + check(t, WalkDir, td) + check(t, WalkDir, filepath.Join(td, "dir")) + }) } func TestWalkFileError(t *testing.T) { From 63fd764502e08d067293a93d6d1a566951255ce5 Mon Sep 17 00:00:00 2001 From: Derek Parker Date: Wed, 28 Oct 2020 20:54:27 +0000 Subject: [PATCH 348/403] cmd/internal/obj: add prologue_end DWARF stmt for ppc64 This patch adds a prologue_end statement to the DWARF information for the ppc64 arch. Prologue end is used by the Delve debugger in order to determine where to set a breakpoint to avoid the stacksplit prologue. Updates #36612 Change-Id: Ifb16c1476fe716a0bf493c5486d1d88ebe8d0253 GitHub-Last-Rev: 77a217206d529df8bf8d4ef10a5347b6ae524612 GitHub-Pull-Request: golang/go#42261 Reviewed-on: https://go-review.googlesource.com/c/go/+/266019 Run-TryBot: David Chase TryBot-Result: Go Bot Reviewed-by: Cherry Zhang Reviewed-by: Alessandro Arzilli Trust: Dmitri Shuralyov --- src/cmd/internal/obj/ppc64/obj9.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index 3ab19de602a..fddf552156c 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -32,6 +32,7 @@ package ppc64 import ( "cmd/internal/obj" "cmd/internal/objabi" + "cmd/internal/src" "cmd/internal/sys" ) @@ -672,6 +673,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { // save the link register and update the stack, since that code is // called directly from C/C++ and can't clobber REGTMP (R31). if autosize != 0 && c.cursym.Name != "runtime.racecallbackthunk" { + var prologueEnd *obj.Prog // Save the link register and update the SP. MOVDU is used unless // the frame size is too large. The link register must be saved // even for non-empty leaf functions so that traceback works. @@ -685,6 +687,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.To.Type = obj.TYPE_REG q.To.Reg = REGTMP + prologueEnd = q + q = obj.Appendp(q, c.newprog) q.As = AMOVDU q.Pos = p.Pos @@ -720,6 +724,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.To.Offset = int64(-autosize) q.To.Reg = REGSP + prologueEnd = q + q = obj.Appendp(q, c.newprog) q.As = AADD q.Pos = p.Pos @@ -730,8 +736,8 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { q.Spadj = +autosize q = c.ctxt.EndUnsafePoint(q, c.newprog, -1) - } + prologueEnd.Pos = prologueEnd.Pos.WithXlogue(src.PosPrologueEnd) } else if c.cursym.Func().Text.Mark&LEAF == 0 { // A very few functions that do not return to their caller // (e.g. gogo) are not identified as leaves but still have From c018eec1f3ab3af28dae0bdf588e25d5e2ba3418 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 29 Oct 2020 10:57:38 -0400 Subject: [PATCH 349/403] cmd/go: add GOVCS setting to control version control usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The go command runs commands like git and hg to download modules. In the past, we have had problems with security bugs in version control systems becoming security bugs in “go get”. The original modules draft design removed use of these commands entirely, saying: > We want to move away from invoking version control tools such as bzr, > fossil, git, hg, and svn to download source code. These fragment the > ecosystem: packages developed using Bazaar or Fossil, for example, are > effectively unavailable to users who cannot or choose not to install > these tools. The version control tools have also been a source of > exciting security problems. It would be good to move them outside the > security perimeter. The removal of these commands was not possible in the end: being able to fetch directly from Git repos is too important, especially for closed source. But the security exposure has not gone away. We remain vulnerable to problems in VCS systems, especially the less scrutinized ones. This change adds a GOVCS setting to let users control which version control systems are allowed by default. It also changes the default allowed version control systems to git and hg for public code and any version control system for private code (import path or module path matched by the GOPRIVATE setting). See the changes in alldocs.go for detailed documentation. See #41730 for proposal and discussion. Fixes #41730. Change-Id: I1999ddf7445b36a7572965be5897c7a1ff7f4265 Reviewed-on: https://go-review.googlesource.com/c/go/+/266420 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 177 +++++++++++++++++++------- src/cmd/go/internal/cfg/cfg.go | 1 + src/cmd/go/internal/envcmd/env.go | 1 + src/cmd/go/internal/help/helpdoc.go | 2 +- src/cmd/go/internal/modfetch/fetch.go | 13 +- src/cmd/go/internal/modget/get.go | 76 +++++++++++ src/cmd/go/internal/modload/help.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 144 +++++++++++++++++++++ src/cmd/go/internal/vcs/vcs_test.go | 104 +++++++++++++++ src/cmd/go/main.go | 3 +- src/cmd/go/testdata/script/govcs.txt | 174 +++++++++++++++++++++++++ src/internal/cfg/cfg.go | 1 + 12 files changed, 642 insertions(+), 56 deletions(-) create mode 100644 src/cmd/go/testdata/script/govcs.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 23d44ddc708..ded07e38b4a 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -49,10 +49,11 @@ // modules modules, module versions, and more // module-get module-aware go get // module-auth module authentication using go.sum -// module-private module configuration for non-public modules // packages package lists and patterns +// private configuration for downloading non-public code // testflag testing flags // testfunc testing functions +// vcs controlling version control with GOVCS // // Use "go help " for more information about that topic. // @@ -1799,7 +1800,7 @@ // Comma-separated list of glob patterns (in the syntax of Go's path.Match) // of module path prefixes that should always be fetched directly // or that should not be compared against the checksum database. -// See 'go help module-private'. +// See 'go help private'. // GOROOT // The root of the go tree. // GOSUMDB @@ -2869,7 +2870,7 @@ // followed by a pipe character, indicating it is safe to fall back on any error. // // The GOPRIVATE and GONOPROXY environment variables allow bypassing -// the proxy for selected modules. See 'go help module-private' for details. +// the proxy for selected modules. See 'go help private' for details. // // No matter the source of the modules, the go command checks downloads against // known checksums, to detect unexpected changes in the content of any specific @@ -2989,52 +2990,7 @@ // accepted, at the cost of giving up the security guarantee of verified repeatable // downloads for all modules. A better way to bypass the checksum database // for specific modules is to use the GOPRIVATE or GONOSUMDB environment -// variables. See 'go help module-private' for details. -// -// The 'go env -w' command (see 'go help env') can be used to set these variables -// for future go command invocations. -// -// -// Module configuration for non-public modules -// -// The go command defaults to downloading modules from the public Go module -// mirror at proxy.golang.org. It also defaults to validating downloaded modules, -// regardless of source, against the public Go checksum database at sum.golang.org. -// These defaults work well for publicly available source code. -// -// The GOPRIVATE environment variable controls which modules the go command -// considers to be private (not available publicly) and should therefore not use the -// proxy or checksum database. The variable is a comma-separated list of -// glob patterns (in the syntax of Go's path.Match) of module path prefixes. -// For example, -// -// GOPRIVATE=*.corp.example.com,rsc.io/private -// -// causes the go command to treat as private any module with a path prefix -// matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, -// and rsc.io/private/quux. -// -// The GOPRIVATE environment variable may be used by other tools as well to -// identify non-public modules. For example, an editor could use GOPRIVATE -// to decide whether to hyperlink a package import to a godoc.org page. -// -// For fine-grained control over module download and validation, the GONOPROXY -// and GONOSUMDB environment variables accept the same kind of glob list -// and override GOPRIVATE for the specific decision of whether to use the proxy -// and checksum database, respectively. -// -// For example, if a company ran a module proxy serving private modules, -// users would configure go using: -// -// GOPRIVATE=*.corp.example.com -// GOPROXY=proxy.example.com -// GONOPROXY=none -// -// This would tell the go command and other tools that modules beginning with -// a corp.example.com subdomain are private but that the company proxy should -// be used for downloading both public and private modules, because -// GONOPROXY has been set to a pattern that won't match any modules, -// overriding GOPRIVATE. +// variables. See 'go help private' for details. // // The 'go env -w' command (see 'go help env') can be used to set these variables // for future go command invocations. @@ -3124,6 +3080,56 @@ // by the go tool, as are directories named "testdata". // // +// Configuration for downloading non-public code +// +// The go command defaults to downloading modules from the public Go module +// mirror at proxy.golang.org. It also defaults to validating downloaded modules, +// regardless of source, against the public Go checksum database at sum.golang.org. +// These defaults work well for publicly available source code. +// +// The GOPRIVATE environment variable controls which modules the go command +// considers to be private (not available publicly) and should therefore not use the +// proxy or checksum database. The variable is a comma-separated list of +// glob patterns (in the syntax of Go's path.Match) of module path prefixes. +// For example, +// +// GOPRIVATE=*.corp.example.com,rsc.io/private +// +// causes the go command to treat as private any module with a path prefix +// matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, +// and rsc.io/private/quux. +// +// The GOPRIVATE environment variable may be used by other tools as well to +// identify non-public modules. For example, an editor could use GOPRIVATE +// to decide whether to hyperlink a package import to a godoc.org page. +// +// For fine-grained control over module download and validation, the GONOPROXY +// and GONOSUMDB environment variables accept the same kind of glob list +// and override GOPRIVATE for the specific decision of whether to use the proxy +// and checksum database, respectively. +// +// For example, if a company ran a module proxy serving private modules, +// users would configure go using: +// +// GOPRIVATE=*.corp.example.com +// GOPROXY=proxy.example.com +// GONOPROXY=none +// +// This would tell the go command and other tools that modules beginning with +// a corp.example.com subdomain are private but that the company proxy should +// be used for downloading both public and private modules, because +// GONOPROXY has been set to a pattern that won't match any modules, +// overriding GOPRIVATE. +// +// The GOPRIVATE variable is also used to define the "public" and "private" +// patterns for the GOVCS variable; see 'go help vcs'. For that usage, +// GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths +// instead of module paths. +// +// The 'go env -w' command (see 'go help env') can be used to set these variables +// for future go command invocations. +// +// // Testing flags // // The 'go test' command takes both flags that apply to 'go test' itself @@ -3416,4 +3422,77 @@ // See the documentation of the testing package for more information. // // +// Controlling version control with GOVCS +// +// The 'go get' command can run version control commands like git +// to download imported code. This functionality is critical to the decentralized +// Go package ecosystem, in which code can be imported from any server, +// but it is also a potential security problem, if a malicious server finds a +// way to cause the invoked version control command to run unintended code. +// +// To balance the functionality and security concerns, the 'go get' command +// by default will only use git and hg to download code from public servers. +// But it will use any known version control system (bzr, fossil, git, hg, svn) +// to download code from private servers, defined as those hosting packages +// matching the GOPRIVATE variable (see 'go help private'). The rationale behind +// allowing only Git and Mercurial is that these two systems have had the most +// attention to issues of being run as clients of untrusted servers. In contrast, +// Bazaar, Fossil, and Subversion have primarily been used in trusted, +// authenticated environments and are not as well scrutinized as attack surfaces. +// +// The version control command restrictions only apply when using direct version +// control access to download code. When downloading modules from a proxy, +// 'go get' uses the proxy protocol instead, which is always permitted. +// By default, the 'go get' command uses the Go module mirror (proxy.golang.org) +// for public packages and only falls back to version control for private +// packages or when the mirror refuses to serve a public package (typically for +// legal reasons). Therefore, clients can still access public code served from +// Bazaar, Fossil, or Subversion repositories by default, because those downloads +// use the Go module mirror, which takes on the security risk of running the +// version control commands, using a custom sandbox. +// +// The GOVCS variable can be used to change the allowed version control systems +// for specific packages (identified by a module or import path). +// The GOVCS variable applies both when using modules and when using GOPATH. +// When using modules, the patterns match against the module path. +// When using GOPATH, the patterns match against the import path +// corresponding to the root of the version control repository. +// +// The general form of the GOVCS setting is a comma-separated list of +// pattern:vcslist rules. The pattern is a glob pattern that must match +// one or more leading elements of the module or import path. The vcslist +// is a pipe-separated list of allowed version control commands, or "all" +// to allow use of any known command, or "off" to allow nothing. +// The earliest matching pattern in the list applies, even if later patterns +// might also match. +// +// For example, consider: +// +// GOVCS=github.com:git,evil.com:off,*:git|hg +// +// With this setting, code with an module or import path beginning with +// github.com/ can only use git; paths on evil.com cannot use any version +// control command, and all other paths (* matches everything) can use +// only git or hg. +// +// The special patterns "public" and "private" match public and private +// module or import paths. A path is private if it matches the GOPRIVATE +// variable; otherwise it is public. +// +// If no rules in the GOVCS variable match a particular module or import path, +// the 'go get' command applies its default rule, which can now be summarized +// in GOVCS notation as 'public:git|hg,private:all'. +// +// To allow unfettered use of any version control system for any package, use: +// +// GOVCS=*:all +// +// To disable all use of version control, use: +// +// GOVCS=*:off +// +// The 'go env -w' command (see 'go help env') can be used to set the GOVCS +// variable for future go command invocations. +// +// package main diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 67d581f6e6d..9bc48132ae2 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -268,6 +268,7 @@ var ( GONOPROXY = envOr("GONOPROXY", GOPRIVATE) GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE) GOINSECURE = Getenv("GOINSECURE") + GOVCS = Getenv("GOVCS") ) var SumdbDir = gopathDir("pkg/sumdb") diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 557e4189213..d65ace879db 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -87,6 +87,7 @@ func MkEnv() []cfg.EnvVar { {Name: "GOSUMDB", Value: cfg.GOSUMDB}, {Name: "GOTMPDIR", Value: cfg.Getenv("GOTMPDIR")}, {Name: "GOTOOLDIR", Value: base.ToolDir}, + {Name: "GOVCS", Value: cfg.GOVCS}, } if work.GccgoBin != "" { diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 8dfabbaa4a0..50cf911407e 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -526,7 +526,7 @@ General-purpose environment variables: Comma-separated list of glob patterns (in the syntax of Go's path.Match) of module path prefixes that should always be fetched directly or that should not be compared against the checksum database. - See 'go help module-private'. + See 'go help private'. GOROOT The root of the go tree. GOSUMDB diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index 25e9fb62c13..a3e2cd1f9d6 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -848,16 +848,16 @@ the checksum database is not consulted, and all unrecognized modules are accepted, at the cost of giving up the security guarantee of verified repeatable downloads for all modules. A better way to bypass the checksum database for specific modules is to use the GOPRIVATE or GONOSUMDB environment -variables. See 'go help module-private' for details. +variables. See 'go help private' for details. The 'go env -w' command (see 'go help env') can be used to set these variables for future go command invocations. `, } -var HelpModulePrivate = &base.Command{ - UsageLine: "module-private", - Short: "module configuration for non-public modules", +var HelpPrivate = &base.Command{ + UsageLine: "private", + Short: "configuration for downloading non-public code", Long: ` The go command defaults to downloading modules from the public Go module mirror at proxy.golang.org. It also defaults to validating downloaded modules, @@ -898,6 +898,11 @@ be used for downloading both public and private modules, because GONOPROXY has been set to a pattern that won't match any modules, overriding GOPRIVATE. +The GOPRIVATE variable is also used to define the "public" and "private" +patterns for the GOVCS variable; see 'go help vcs'. For that usage, +GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths +instead of module paths. + The 'go env -w' command (see 'go help env') can be used to set these variables for future go command invocations. `, diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 171c070ab34..f99441c2b9c 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -176,6 +176,82 @@ Usage: ` + CmdGet.UsageLine + ` ` + CmdGet.Long, } +var HelpVCS = &base.Command{ + UsageLine: "vcs", + Short: "controlling version control with GOVCS", + Long: ` +The 'go get' command can run version control commands like git +to download imported code. This functionality is critical to the decentralized +Go package ecosystem, in which code can be imported from any server, +but it is also a potential security problem, if a malicious server finds a +way to cause the invoked version control command to run unintended code. + +To balance the functionality and security concerns, the 'go get' command +by default will only use git and hg to download code from public servers. +But it will use any known version control system (bzr, fossil, git, hg, svn) +to download code from private servers, defined as those hosting packages +matching the GOPRIVATE variable (see 'go help private'). The rationale behind +allowing only Git and Mercurial is that these two systems have had the most +attention to issues of being run as clients of untrusted servers. In contrast, +Bazaar, Fossil, and Subversion have primarily been used in trusted, +authenticated environments and are not as well scrutinized as attack surfaces. + +The version control command restrictions only apply when using direct version +control access to download code. When downloading modules from a proxy, +'go get' uses the proxy protocol instead, which is always permitted. +By default, the 'go get' command uses the Go module mirror (proxy.golang.org) +for public packages and only falls back to version control for private +packages or when the mirror refuses to serve a public package (typically for +legal reasons). Therefore, clients can still access public code served from +Bazaar, Fossil, or Subversion repositories by default, because those downloads +use the Go module mirror, which takes on the security risk of running the +version control commands, using a custom sandbox. + +The GOVCS variable can be used to change the allowed version control systems +for specific packages (identified by a module or import path). +The GOVCS variable applies both when using modules and when using GOPATH. +When using modules, the patterns match against the module path. +When using GOPATH, the patterns match against the import path +corresponding to the root of the version control repository. + +The general form of the GOVCS setting is a comma-separated list of +pattern:vcslist rules. The pattern is a glob pattern that must match +one or more leading elements of the module or import path. The vcslist +is a pipe-separated list of allowed version control commands, or "all" +to allow use of any known command, or "off" to allow nothing. +The earliest matching pattern in the list applies, even if later patterns +might also match. + +For example, consider: + + GOVCS=github.com:git,evil.com:off,*:git|hg + +With this setting, code with an module or import path beginning with +github.com/ can only use git; paths on evil.com cannot use any version +control command, and all other paths (* matches everything) can use +only git or hg. + +The special patterns "public" and "private" match public and private +module or import paths. A path is private if it matches the GOPRIVATE +variable; otherwise it is public. + +If no rules in the GOVCS variable match a particular module or import path, +the 'go get' command applies its default rule, which can now be summarized +in GOVCS notation as 'public:git|hg,private:all'. + +To allow unfettered use of any version control system for any package, use: + + GOVCS=*:all + +To disable all use of version control, use: + + GOVCS=*:off + +The 'go env -w' command (see 'go help env') can be used to set the GOVCS +variable for future go command invocations. +`, +} + var ( getD = CmdGet.Flag.Bool("d", false, "") getF = CmdGet.Flag.Bool("f", false, "") diff --git a/src/cmd/go/internal/modload/help.go b/src/cmd/go/internal/modload/help.go index 56920c28b99..c09dfe965d2 100644 --- a/src/cmd/go/internal/modload/help.go +++ b/src/cmd/go/internal/modload/help.go @@ -365,7 +365,7 @@ list if the error is a 404 or 410 HTTP response or if the current proxy is followed by a pipe character, indicating it is safe to fall back on any error. The GOPRIVATE and GONOPROXY environment variables allow bypassing -the proxy for selected modules. See 'go help module-private' for details. +the proxy for selected modules. See 'go help private' for details. No matter the source of the modules, the go command checks downloads against known checksums, to detect unexpected changes in the content of any specific diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 7812afd4888..3bdb1d4ef94 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -22,7 +22,10 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" + "cmd/go/internal/search" "cmd/go/internal/web" + + "golang.org/x/mod/module" ) // A vcsCmd describes how to use a version control system @@ -591,12 +594,146 @@ func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) { } if vcsRet != nil { + if err := checkGOVCS(vcsRet, rootRet); err != nil { + return nil, "", err + } return vcsRet, rootRet, nil } return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) } +// A govcsRule is a single GOVCS rule like private:hg|svn. +type govcsRule struct { + pattern string + allowed []string +} + +// A govcsConfig is a full GOVCS configuration. +type govcsConfig []govcsRule + +func parseGOVCS(s string) (govcsConfig, error) { + s = strings.TrimSpace(s) + if s == "" { + return nil, nil + } + var cfg govcsConfig + have := make(map[string]string) + for _, item := range strings.Split(s, ",") { + item = strings.TrimSpace(item) + if item == "" { + return nil, fmt.Errorf("empty entry in GOVCS") + } + i := strings.Index(item, ":") + if i < 0 { + return nil, fmt.Errorf("malformed entry in GOVCS (missing colon): %q", item) + } + pattern, list := strings.TrimSpace(item[:i]), strings.TrimSpace(item[i+1:]) + if pattern == "" { + return nil, fmt.Errorf("empty pattern in GOVCS: %q", item) + } + if list == "" { + return nil, fmt.Errorf("empty VCS list in GOVCS: %q", item) + } + if search.IsRelativePath(pattern) { + return nil, fmt.Errorf("relative pattern not allowed in GOVCS: %q", pattern) + } + if old := have[pattern]; old != "" { + return nil, fmt.Errorf("unreachable pattern in GOVCS: %q after %q", item, old) + } + have[pattern] = item + allowed := strings.Split(list, "|") + for i, a := range allowed { + a = strings.TrimSpace(a) + if a == "" { + return nil, fmt.Errorf("empty VCS name in GOVCS: %q", item) + } + allowed[i] = a + } + cfg = append(cfg, govcsRule{pattern, allowed}) + } + return cfg, nil +} + +func (c *govcsConfig) allow(path string, private bool, vcs string) bool { + for _, rule := range *c { + match := false + switch rule.pattern { + case "private": + match = private + case "public": + match = !private + default: + // Note: rule.pattern is known to be comma-free, + // so MatchPrefixPatterns is only matching a single pattern for us. + match = module.MatchPrefixPatterns(rule.pattern, path) + } + if !match { + continue + } + for _, allow := range rule.allowed { + if allow == vcs || allow == "all" { + return true + } + } + return false + } + + // By default, nothing is allowed. + return false +} + +var ( + govcs govcsConfig + govcsErr error + govcsOnce sync.Once +) + +// defaultGOVCS is the default setting for GOVCS. +// Setting GOVCS adds entries ahead of these but does not remove them. +// (They are appended to the parsed GOVCS setting.) +// +// The rationale behind allowing only Git and Mercurial is that +// these two systems have had the most attention to issues +// of being run as clients of untrusted servers. In contrast, +// Bazaar, Fossil, and Subversion have primarily been used +// in trusted, authenticated environments and are not as well +// scrutinized as attack surfaces. +// +// See golang.org/issue/41730 for details. +var defaultGOVCS = govcsConfig{ + {"private", []string{"all"}}, + {"public", []string{"git", "hg"}}, +} + +func checkGOVCS(vcs *Cmd, root string) error { + if vcs.Cmd == "mod" { + // Direct module (proxy protocol) fetches don't + // involve an external version control system + // and are always allowed. + return nil + } + + govcsOnce.Do(func() { + govcs, govcsErr = parseGOVCS(os.Getenv("GOVCS")) + govcs = append(govcs, defaultGOVCS...) + }) + if govcsErr != nil { + return govcsErr + } + + private := module.MatchPrefixPatterns(cfg.GOPRIVATE, root) + if !govcs.allow(root, private, vcs.Cmd) { + what := "public" + if private { + what = "private" + } + return fmt.Errorf("GOVCS disallows using %s for %s %s", vcs.Cmd, what, root) + } + + return nil +} + // CheckNested checks for an incorrectly-nested VCS-inside-VCS // situation for dir, checking parents up until srcRoot. func CheckNested(vcs *Cmd, dir, srcRoot string) error { @@ -733,6 +870,9 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths if vcs == nil { return nil, fmt.Errorf("unknown version control system %q", match["vcs"]) } + if err := checkGOVCS(vcs, match["root"]); err != nil { + return nil, err + } var repoURL string if !srv.schemelessRepo { repoURL = match["repo"] @@ -857,6 +997,10 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se } } + if err := checkGOVCS(vcs, mmi.Prefix); err != nil { + return nil, err + } + rr := &RepoRoot{ Repo: mmi.RepoRoot, Root: mmi.Prefix, diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index 5b874204f1e..72d74a01e30 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -11,11 +11,20 @@ import ( "os" "path" "path/filepath" + "strings" "testing" "cmd/go/internal/web" ) +func init() { + // GOVCS defaults to public:git|hg,private:all, + // which breaks many tests here - they can't use non-git, non-hg VCS at all! + // Change to fully permissive. + // The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt. + os.Setenv("GOVCS", "*:all") +} + // Test that RepoRootForImportPath determines the correct RepoRoot for a given importPath. // TODO(cmang): Add tests for SVN and BZR. func TestRepoRootForImportPath(t *testing.T) { @@ -473,3 +482,98 @@ func TestValidateRepoRoot(t *testing.T) { } } } + +var govcsTests = []struct { + govcs string + path string + vcs string + ok bool +}{ + {"private:all", "is-public.com/foo", "zzz", false}, + {"private:all", "is-private.com/foo", "zzz", true}, + {"public:all", "is-public.com/foo", "zzz", true}, + {"public:all", "is-private.com/foo", "zzz", false}, + {"public:all,private:none", "is-public.com/foo", "zzz", true}, + {"public:all,private:none", "is-private.com/foo", "zzz", false}, + {"*:all", "is-public.com/foo", "zzz", true}, + {"golang.org:git", "golang.org/x/text", "zzz", false}, + {"golang.org:git", "golang.org/x/text", "git", true}, + {"golang.org:zzz", "golang.org/x/text", "zzz", true}, + {"golang.org:zzz", "golang.org/x/text", "git", false}, + {"golang.org:zzz", "golang.org/x/text", "zzz", true}, + {"golang.org:zzz", "golang.org/x/text", "git", false}, + {"golang.org:git|hg", "golang.org/x/text", "hg", true}, + {"golang.org:git|hg", "golang.org/x/text", "git", true}, + {"golang.org:git|hg", "golang.org/x/text", "zzz", false}, + {"golang.org:all", "golang.org/x/text", "hg", true}, + {"golang.org:all", "golang.org/x/text", "git", true}, + {"golang.org:all", "golang.org/x/text", "zzz", true}, + {"other.xyz/p:none,golang.org/x:git", "other.xyz/p/x", "git", false}, + {"other.xyz/p:none,golang.org/x:git", "unexpected.com", "git", false}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/x/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/x/text", "git", true}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/x/text", "zzz", true}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/x/text", "git", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "hg", true}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "git", true}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "hg", true}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "git", true}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "zzz", true}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/y/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/y/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "hg", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "hg", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "zzz", false}, +} + +func TestGOVCS(t *testing.T) { + for _, tt := range govcsTests { + cfg, err := parseGOVCS(tt.govcs) + if err != nil { + t.Errorf("parseGOVCS(%q): %v", tt.govcs, err) + continue + } + private := strings.HasPrefix(tt.path, "is-private") + ok := cfg.allow(tt.path, private, tt.vcs) + if ok != tt.ok { + t.Errorf("parseGOVCS(%q).allow(%q, %v, %q) = %v, want %v", + tt.govcs, tt.path, private, tt.vcs, ok, tt.ok) + } + } +} + +var govcsErrors = []struct { + s string + err string +}{ + {`,`, `empty entry in GOVCS`}, + {`,x`, `empty entry in GOVCS`}, + {`x,`, `malformed entry in GOVCS (missing colon): "x"`}, + {`x:y,`, `empty entry in GOVCS`}, + {`x`, `malformed entry in GOVCS (missing colon): "x"`}, + {`x:`, `empty VCS list in GOVCS: "x:"`}, + {`x:|`, `empty VCS name in GOVCS: "x:|"`}, + {`x:y|`, `empty VCS name in GOVCS: "x:y|"`}, + {`x:|y`, `empty VCS name in GOVCS: "x:|y"`}, + {`x:y,z:`, `empty VCS list in GOVCS: "z:"`}, + {`x:y,z:|`, `empty VCS name in GOVCS: "z:|"`}, + {`x:y,z:|w`, `empty VCS name in GOVCS: "z:|w"`}, + {`x:y,z:w|`, `empty VCS name in GOVCS: "z:w|"`}, + {`x:y,z:w||v`, `empty VCS name in GOVCS: "z:w||v"`}, + {`x:y,x:z`, `unreachable pattern in GOVCS: "x:z" after "x:y"`}, +} + +func TestGOVCSErrors(t *testing.T) { + for _, tt := range govcsErrors { + _, err := parseGOVCS(tt.s) + if err == nil || !strings.Contains(err.Error(), tt.err) { + t.Errorf("parseGOVCS(%s): err=%v, want %v", tt.s, err, tt.err) + } + } +} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 37bb7d6d270..9cc44da84db 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -75,10 +75,11 @@ func init() { modload.HelpModules, modget.HelpModuleGet, modfetch.HelpModuleAuth, - modfetch.HelpModulePrivate, help.HelpPackages, + modfetch.HelpPrivate, test.HelpTestflag, test.HelpTestfunc, + modget.HelpVCS, } } diff --git a/src/cmd/go/testdata/script/govcs.txt b/src/cmd/go/testdata/script/govcs.txt new file mode 100644 index 00000000000..cc10a369155 --- /dev/null +++ b/src/cmd/go/testdata/script/govcs.txt @@ -0,0 +1,174 @@ +env GO111MODULE=on +env proxy=$GOPROXY +env GOPROXY=direct + +# GOVCS stops go get +env GOVCS='*:none' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' +env GOPRIVATE='github.com/google' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' + +# public pattern works +env GOPRIVATE='github.com/google' +env GOVCS='public:all,private:none' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' + +# private pattern works +env GOPRIVATE='hubgit.com/google' +env GOVCS='private:all,public:none' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' + +# other patterns work (for more patterns, see TestGOVCS) +env GOPRIVATE= +env GOVCS='github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' +env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' + +# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) +env GOVCS='git' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"' + +env GOVCS=github.com:hg,github.com:git +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"' + +# bad GOVCS patterns do not stop commands that do not need to check VCS +go list +env GOPROXY=$proxy +go get -d rsc.io/quote # ok because used proxy +env GOPROXY=direct + +# svn is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.svn/hello +stderr 'go get rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn' + +# fossil is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.fossil/hello +stderr 'go get rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil' + +# bzr is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.bzr/hello +stderr 'go get rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr' + +# git is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:git] [!short] go get rsc.io/sampler + +# hg is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello + +# git can be disallowed +env GOVCS=public:hg +! go get rsc.io/nonexist.git/hello +stderr 'go get rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git' + +# hg can be disallowed +env GOVCS=public:git +! go get rsc.io/nonexist.hg/hello +stderr 'go get rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg' + +# Repeat in GOPATH mode. Error texts slightly different. + +env GO111MODULE=off + +# GOVCS stops go get +env GOVCS='*:none' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' +env GOPRIVATE='github.com/google' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' + +# public pattern works +env GOPRIVATE='github.com/google' +env GOVCS='public:all,private:none' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' + +# private pattern works +env GOPRIVATE='hubgit.com/google' +env GOVCS='private:all,public:none' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' + +# other patterns work (for more patterns, see TestGOVCS) +env GOPRIVATE= +env GOVCS='github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' +env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' + +# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) +env GOVCS='git' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"' + +env GOVCS=github.com:hg,github.com:git +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"' + +# bad GOVCS patterns do not stop commands that do not need to check VCS +go list + +# svn is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.svn/hello +stderr 'package rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn' + +# fossil is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.fossil/hello +stderr 'package rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil' + +# bzr is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.bzr/hello +stderr 'package rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr' + +# git is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:git] [!short] go get rsc.io/sampler + +# hg is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello + +# git can be disallowed +env GOVCS=public:hg +! go get rsc.io/nonexist.git/hello +stderr 'package rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git' + +# hg can be disallowed +env GOVCS=public:git +! go get rsc.io/nonexist.hg/hello +stderr 'package rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg' + +-- go.mod -- +module m + +-- p.go -- +package p diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go index bdbe9df3e75..553021374d5 100644 --- a/src/internal/cfg/cfg.go +++ b/src/internal/cfg/cfg.go @@ -58,6 +58,7 @@ const KnownEnv = ` GOSUMDB GOTMPDIR GOTOOLDIR + GOVCS GOWASM GO_EXTLINK_ENABLED PKG_CONFIG From 1e3b535b6eb7f13eb6d903f7998c384a36e9bba8 Mon Sep 17 00:00:00 2001 From: Johan Knutzen Date: Wed, 21 Oct 2020 18:45:03 +0000 Subject: [PATCH 350/403] syscall: expose bInheritHandles of CreateProcess Certain use cases require this parameter to be false. This includes spawning a child process in a different windows session than session 0. Docs regarding the behavior of this parameter to CreateProcess: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa Fixes #42098 Change-Id: If998f57d6f2962824aacbee75e1b508b255ab293 GitHub-Last-Rev: 584eb13e36a3ef7e0cd959295e92fb129f21d1f8 GitHub-Pull-Request: golang/go#41957 Reviewed-on: https://go-review.googlesource.com/c/go/+/261917 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Tobias Klauser Trust: Alex Brainman --- doc/go1.16.html | 8 ++++++++ src/syscall/exec_windows.go | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 5d293078861..5ae85e6c293 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -378,6 +378,14 @@ Do not send CLs removing the interior tags from such phrases. +

syscall
+
+

+ SysProcAttr on Windows has a new NoInheritHandles field that disables inheriting handles when creating a new process. +

+
+
+
strconv

diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go index 4a1d74ba3f3..46cbd7567dd 100644 --- a/src/syscall/exec_windows.go +++ b/src/syscall/exec_windows.go @@ -241,6 +241,7 @@ type SysProcAttr struct { Token Token // if set, runs new process in the security context represented by the token ProcessAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process ThreadAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process + NoInheritHandles bool // if set, each inheritable handle in the calling process is not inherited by the new process } var zeroProcAttr ProcAttr @@ -341,9 +342,9 @@ func StartProcess(argv0 string, argv []string, attr *ProcAttr) (pid int, handle flags := sys.CreationFlags | CREATE_UNICODE_ENVIRONMENT if sys.Token != 0 { - err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, true, flags, createEnvBlock(attr.Env), dirp, si, pi) + err = CreateProcessAsUser(sys.Token, argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, si, pi) } else { - err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, true, flags, createEnvBlock(attr.Env), dirp, si, pi) + err = CreateProcess(argv0p, argvp, sys.ProcessAttributes, sys.ThreadAttributes, !sys.NoInheritHandles, flags, createEnvBlock(attr.Env), dirp, si, pi) } if err != nil { return 0, 0, err From 3ef8562c9c2c7f6897572b05b70ac936a99fd043 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Tue, 26 May 2020 14:14:08 -0700 Subject: [PATCH 351/403] net/mail: avoid ParseDate confusion if day name includes "T" Fixes the check for RFC 5322 "obsolete time zone" to ensure that we correctly extract the entire date from the "T" of the implied time zone. Obsolete Time zones come in the form: * GMT * PST * MDT etc, as per Section 4.3 of RFC 5322, https://tools.ietf.org/html/rfc5322#section-4.3. The prior check from CL 117596 erronenously used strings.Index which selects the first "T", and that meant that dates containing days "Tue" or "Thu" could not be parsed. We also now deal with "T" in the CFWS "Comment Folding White Space". Thus we'll now accept dates: * Thu, 20 Nov 1997 09:55:06 MDT * Thu, 20 Nov 1997 09:55:06 MDT (MDT) * Fri, 21 Nov 1997 09:55:06 MDT (This comment) * Fri, 21 Nov 1997 09:55:06 MDT (MDT Fixes #39260 Change-Id: I6d59d99bc4f05a82582c826b5c5a080a25fd999b Reviewed-on: https://go-review.googlesource.com/c/go/+/235200 Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Emmanuel Odeke --- src/net/mail/message.go | 24 +++++++++++++++++----- src/net/mail/message_test.go | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/net/mail/message.go b/src/net/mail/message.go index 09fb794005a..47bbf6ca977 100644 --- a/src/net/mail/message.go +++ b/src/net/mail/message.go @@ -112,11 +112,25 @@ func ParseDate(date string) (time.Time, error) { if ind := strings.IndexAny(p.s, "+-"); ind != -1 && len(p.s) >= ind+5 { date = p.s[:ind+5] p.s = p.s[ind+5:] - } else if ind := strings.Index(p.s, "T"); ind != -1 && len(p.s) >= ind+1 { - // The last letter T of the obsolete time zone is checked when no standard time zone is found. - // If T is misplaced, the date to parse is garbage. - date = p.s[:ind+1] - p.s = p.s[ind+1:] + } else { + ind := strings.Index(p.s, "T") + if ind == 0 { + // In this case we have the following date formats: + // * Thu, 20 Nov 1997 09:55:06 MDT + // * Thu, 20 Nov 1997 09:55:06 MDT (MDT) + // * Thu, 20 Nov 1997 09:55:06 MDT (This comment) + ind = strings.Index(p.s[1:], "T") + if ind != -1 { + ind++ + } + } + + if ind != -1 && len(p.s) >= ind+5 { + // The last letter T of the obsolete time zone is checked when no standard time zone is found. + // If T is misplaced, the date to parse is garbage. + date = p.s[:ind+1] + p.s = p.s[ind+1:] + } } if !p.skipCFWS() { return time.Time{}, errors.New("mail: misformatted parenthetical comment") diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go index 188d0bf7663..0daa3d6c632 100644 --- a/src/net/mail/message_test.go +++ b/src/net/mail/message_test.go @@ -102,6 +102,18 @@ func TestDateParsing(t *testing.T) { "Fri, 21 Nov 1997 09:55:06 -0600 (MDT)", time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)), }, + { + "Thu, 20 Nov 1997 09:55:06 -0600 (MDT)", + time.Date(1997, 11, 20, 9, 55, 6, 0, time.FixedZone("", -6*60*60)), + }, + { + "Thu, 20 Nov 1997 09:55:06 MDT (MDT)", + time.Date(1997, 11, 20, 9, 55, 6, 0, time.FixedZone("MDT", 0)), + }, + { + "Fri, 21 Nov 1997 09:55:06 +1300 (TOT)", + time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", +13*60*60)), + }, } for _, test := range tests { hdr := Header{ @@ -243,6 +255,33 @@ func TestDateParsingCFWS(t *testing.T) { time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("", -6*60*60)), false, }, + // Ensure that the presence of "T" in the date + // doesn't trip out ParseDate, as per issue 39260. + { + "Tue, 26 May 2020 14:04:40 GMT", + time.Date(2020, 05, 26, 14, 04, 40, 0, time.UTC), + true, + }, + { + "Tue, 26 May 2020 14:04:40 UT", + time.Date(2020, 05, 26, 14, 04, 40, 0, time.UTC), + false, + }, + { + "Thu, 21 May 2020 14:04:40 UT", + time.Date(2020, 05, 21, 14, 04, 40, 0, time.UTC), + false, + }, + { + "Thu, 21 May 2020 14:04:40 UTC", + time.Date(2020, 05, 21, 14, 04, 40, 0, time.UTC), + true, + }, + { + "Fri, 21 Nov 1997 09:55:06 MDT (MDT)", + time.Date(1997, 11, 21, 9, 55, 6, 0, time.FixedZone("MDT", 0)), + true, + }, } for _, test := range tests { hdr := Header{ From 3510a1e32cbc86b73db143aefcc00aadc44c27bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=B6hrmann?= Date: Thu, 5 Nov 2020 05:59:34 +0100 Subject: [PATCH 352/403] internal/cpu: fix and cleanup ARM64 cpu feature fields and options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove all cpu features from the ARM64 struct that are not initialized to reduce cache lines used and to avoid those features being accidentially used without actual detection if they are present. Add missing option to mask the CPUID feature. Change-Id: I94bf90c0655de1af2218ac72117ac6c52adfc289 Reviewed-on: https://go-review.googlesource.com/c/go/+/267658 Run-TryBot: Martin Möhrmann TryBot-Result: Go Bot Reviewed-by: Tobias Klauser Trust: Martin Möhrmann --- src/internal/cpu/cpu.go | 17 ----------------- src/internal/cpu/cpu_arm64.go | 1 + 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index 0ceedcd7d22..dab5d068ef3 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -57,30 +57,13 @@ var ARM struct { // The struct is padded to avoid false sharing. var ARM64 struct { _ CacheLinePad - HasFP bool - HasASIMD bool - HasEVTSTRM bool HasAES bool HasPMULL bool HasSHA1 bool HasSHA2 bool HasCRC32 bool HasATOMICS bool - HasFPHP bool - HasASIMDHP bool HasCPUID bool - HasASIMDRDM bool - HasJSCVT bool - HasFCMA bool - HasLRCPC bool - HasDCPOP bool - HasSHA3 bool - HasSM3 bool - HasSM4 bool - HasASIMDDP bool - HasSHA512 bool - HasSVE bool - HasASIMDFHM bool IsNeoverseN1 bool IsZeus bool _ CacheLinePad diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index 8fde39f03e1..4e9ea8ca961 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -29,6 +29,7 @@ func doinit() { {Name: "sha2", Feature: &ARM64.HasSHA2}, {Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "atomics", Feature: &ARM64.HasATOMICS}, + {Name: "cpuid", Feature: &ARM64.HasCPUID}, {Name: "isNeoverseN1", Feature: &ARM64.IsNeoverseN1}, {Name: "isZeus", Feature: &ARM64.IsZeus}, } From 05568315f2ae8fb86112e63966b46c2dcc8ab6e2 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 3 Nov 2020 17:54:24 -0500 Subject: [PATCH 353/403] go/types: simplify error messages for untyped value assignability CL 242083 corrected an inaccurate error message related to the assignability of untyped constant values. Previously the error message was of the form "cannot convert ... to ...", which is misleading when there is no explicit conversion in the syntax. The new error message corrected this to "cannot use ... as ... in ...", but also appended an inner error message that can be quite verbose. For example: cannot use "123" (untyped string constant) as int value in assignment: cannot convert "123" (untyped string constant) to int" This might be more accurate, but is a regression in readability. Correct this by only including the inner error message in the rare cases where it is helpful: if the constant value overflows or is truncated. For golang/go#22070 Change-Id: I8b8ee6ef713f64facc319894be09398b0b5ea500 Reviewed-on: https://go-review.googlesource.com/c/go/+/267717 Run-TryBot: Robert Findley Reviewed-by: Robert Griesemer Trust: Robert Griesemer Trust: Robert Findley TryBot-Result: Go Bot --- src/go/types/assignments.go | 19 +++++++++++++------ src/go/types/errorcodes.go | 5 ++++- src/go/types/testdata/builtins.src | 4 ++-- src/go/types/testdata/decls1.src | 2 ++ src/go/types/testdata/decls2b.src | 8 ++++---- src/go/types/testdata/expr3.src | 14 +++++++------- src/go/types/testdata/issues.src | 4 ++-- src/go/types/testdata/stmt0.src | 12 ++++++------ 8 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index c099d11c25a..d895c6f099a 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -45,14 +45,21 @@ func (check *Checker) assignment(x *operand, T Type, context string) { target = Default(x.typ) } if err := check.canConvertUntyped(x, target); err != nil { - var internalErr Error - msg := err.Error() + msg := check.sprintf("cannot use %s as %s value in %s", x, target, context) code := _IncompatibleAssign - if errors.As(err, &internalErr) { - msg = internalErr.Msg - code = internalErr.go116code + var ierr Error + if errors.As(err, &ierr) { + // Preserve these inner errors, as they are informative. + switch ierr.go116code { + case _TruncatedFloat: + msg += " (truncated)" + code = ierr.go116code + case _NumericOverflow: + msg += " (overflows)" + code = ierr.go116code + } } - check.errorf(x.pos(), code, "cannot use %s as %s value in %s: %v", x, target, context, msg) + check.error(x.pos(), code, msg) x.mode = invalid return } diff --git a/src/go/types/errorcodes.go b/src/go/types/errorcodes.go index ba6e2f908bd..e4c8311d62e 100644 --- a/src/go/types/errorcodes.go +++ b/src/go/types/errorcodes.go @@ -135,8 +135,11 @@ const ( // _InvalidConstVal occurs when a const value cannot be converted to its // target type. // + // TODO(findleyr): this error code and example are not very clear. Consider + // removing it. + // // Example: - // var x string = 1 + // const _ = 1 << "hello" _InvalidConstVal // _InvalidConstType occurs when the underlying type in a const declaration diff --git a/src/go/types/testdata/builtins.src b/src/go/types/testdata/builtins.src index ecdba51553e..98830eb08c6 100644 --- a/src/go/types/testdata/builtins.src +++ b/src/go/types/testdata/builtins.src @@ -35,9 +35,9 @@ func append1() { type S []byte type T string var t T - _ = append(s, "foo" /* ERROR cannot convert */ ) + _ = append(s, "foo" /* ERROR cannot use .* in argument to append */ ) _ = append(s, "foo"...) - _ = append(S(s), "foo" /* ERROR cannot convert */ ) + _ = append(S(s), "foo" /* ERROR cannot use .* in argument to append */ ) _ = append(S(s), "foo"...) _ = append(s, t /* ERROR cannot use t */ ) _ = append(s, t...) diff --git a/src/go/types/testdata/decls1.src b/src/go/types/testdata/decls1.src index e6beb783589..f4d2eaba911 100644 --- a/src/go/types/testdata/decls1.src +++ b/src/go/types/testdata/decls1.src @@ -96,6 +96,8 @@ var ( v11 = xx/yy*yy - xx v12 = true && false v13 = nil /* ERROR "use of untyped nil" */ + v14 string = 257 // ERROR cannot use 257 .* as string value in variable declaration$ + v15 int8 = 257 // ERROR cannot use 257 .* as int8 value in variable declaration .*overflows ) // Multiple assignment expressions diff --git a/src/go/types/testdata/decls2b.src b/src/go/types/testdata/decls2b.src index 8e82c6dcde1..5c55750a103 100644 --- a/src/go/types/testdata/decls2b.src +++ b/src/go/types/testdata/decls2b.src @@ -40,17 +40,17 @@ func f_double /* ERROR "redeclared" */ () {} // Verify by checking that errors are reported. func (T /* ERROR "undeclared" */ ) _() {} func (T1) _(undeclared /* ERROR "undeclared" */ ) {} -func (T1) _() int { return "foo" /* ERROR "cannot convert" */ } +func (T1) _() int { return "foo" /* ERROR "cannot use .* in return statement" */ } // Methods with undeclared receiver type can still be checked. // Verify by checking that errors are reported. func (Foo /* ERROR "undeclared" */ ) m() {} func (Foo /* ERROR "undeclared" */ ) m(undeclared /* ERROR "undeclared" */ ) {} -func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot convert" */ } +func (Foo /* ERROR "undeclared" */ ) m() int { return "foo" /* ERROR "cannot use .* in return statement" */ } func (Foo /* ERROR "undeclared" */ ) _() {} func (Foo /* ERROR "undeclared" */ ) _(undeclared /* ERROR "undeclared" */ ) {} -func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot convert" */ } +func (Foo /* ERROR "undeclared" */ ) _() int { return "foo" /* ERROR "cannot use .* in return statement" */ } // Receiver declarations are regular parameter lists; // receiver types may use parentheses, and the list @@ -72,4 +72,4 @@ var ( _ = (*T7).m4 _ = (*T7).m5 _ = (*T7).m6 -) \ No newline at end of file +) diff --git a/src/go/types/testdata/expr3.src b/src/go/types/testdata/expr3.src index 4ecb1987bb4..6f2201c3656 100644 --- a/src/go/types/testdata/expr3.src +++ b/src/go/types/testdata/expr3.src @@ -94,7 +94,7 @@ func indexes() { _ = &s /* ERROR "cannot take address" */ [:10] var m map[string]int - _ = m[0 /* ERROR "cannot convert" */ ] + _ = m[0 /* ERROR "cannot use .* in map index" */ ] _ = m /* ERROR "cannot slice" */ ["foo" : "bar"] _ = m["foo"] // ok is of type bool @@ -184,7 +184,7 @@ func struct_literals() { _ = T1{aa /* ERROR "unknown field" */ : 0} _ = T1{1 /* ERROR "invalid field name" */ : 0} _ = T1{a: 0, s: "foo", u: 0, a /* ERROR "duplicate field" */: 10} - _ = T1{a: "foo" /* ERROR "cannot convert" */ } + _ = T1{a: "foo" /* ERROR "cannot use .* in struct literal" */ } _ = T1{c /* ERROR "unknown field" */ : 0} _ = T1{T0: { /* ERROR "missing type" */ }} // struct literal element type may not be elided _ = T1{T0: T0{}} @@ -195,7 +195,7 @@ func struct_literals() { _ = T0{1, b /* ERROR "mixture" */ : 2, 3} _ = T0{1, 2} /* ERROR "too few values" */ _ = T0{1, 2, 3, 4 /* ERROR "too many values" */ } - _ = T0{1, "foo" /* ERROR "cannot convert" */, 3.4 /* ERROR "truncated" */} + _ = T0{1, "foo" /* ERROR "cannot use .* in struct literal" */, 3.4 /* ERROR "cannot use .*\(truncated\)" */} // invalid type type P *struct{ @@ -235,7 +235,7 @@ func array_literals() { _ = A1{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4} _ = A1{2.0} _ = A1{2.1 /* ERROR "truncated" */ } - _ = A1{"foo" /* ERROR "cannot convert" */ } + _ = A1{"foo" /* ERROR "cannot use .* in array or slice literal" */ } // indices must be integer constants i := 1 @@ -301,7 +301,7 @@ func slice_literals() { _ = S0{5: 5, 6, 7, 4: 4, 1 /* ERROR "overflows" */ <<100: 4} _ = S0{2.0} _ = S0{2.1 /* ERROR "truncated" */ } - _ = S0{"foo" /* ERROR "cannot convert" */ } + _ = S0{"foo" /* ERROR "cannot use .* in array or slice literal" */ } // indices must be resolved correctly const index1 = 1 @@ -354,8 +354,8 @@ func map_literals() { _ = M0{} _ = M0{1 /* ERROR "missing key" */ } - _ = M0{1 /* ERROR "cannot convert" */ : 2} - _ = M0{"foo": "bar" /* ERROR "cannot convert" */ } + _ = M0{1 /* ERROR "cannot use .* in map literal" */ : 2} + _ = M0{"foo": "bar" /* ERROR "cannot use .* in map literal" */ } _ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 } _ = map[interface{}]int{2: 1, 2 /* ERROR "duplicate key" */ : 1} diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src index 4944f6f6187..e0c5d7a37cf 100644 --- a/src/go/types/testdata/issues.src +++ b/src/go/types/testdata/issues.src @@ -354,10 +354,10 @@ func issue26234c() { func issue35895() { // T is defined in this package, don't qualify its name with the package name. - var _ T = 0 // ERROR cannot convert 0 \(untyped int constant\) to T + var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T // There is only one package with name syntax imported, only use the (global) package name in error messages. - var _ *syn.File = 0 // ERROR cannot convert 0 \(untyped int constant\) to \*syntax.File + var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File // Because both t1 and t2 have the same global package name (template), // qualify packages with full path name in this case. diff --git a/src/go/types/testdata/stmt0.src b/src/go/types/testdata/stmt0.src index 446997ac098..13777292a94 100644 --- a/src/go/types/testdata/stmt0.src +++ b/src/go/types/testdata/stmt0.src @@ -182,7 +182,7 @@ func sends() { var x int x <- /* ERROR "cannot send" */ x rch <- /* ERROR "cannot send" */ x - ch <- "foo" /* ERROR "cannot convert" */ + ch <- "foo" /* ERROR "cannot use .* in send" */ ch <- x } @@ -381,13 +381,13 @@ func returns0() { func returns1(x float64) (int, *float64) { return 0, &x return /* ERROR wrong number of return values */ - return "foo" /* ERROR "cannot convert" */, x /* ERROR "cannot use .* in return statement" */ + return "foo" /* ERROR "cannot .* in return statement" */, x /* ERROR "cannot use .* in return statement" */ return /* ERROR wrong number of return values */ 0, &x, 1 } func returns2() (a, b int) { return - return 1, "foo" /* ERROR cannot convert */ + return 1, "foo" /* ERROR cannot use .* in return statement */ return /* ERROR wrong number of return values */ 1, 2, 3 { type a int @@ -609,7 +609,7 @@ func switches2() { // untyped constants are converted to default types switch 1<<63-1 { } - switch 1 /* ERROR "overflows int" */ << 63 { + switch 1 /* ERROR "cannot use .* as int value.*\(overflows\)" */ << 63 { } var x int switch 1.0 { @@ -631,9 +631,9 @@ func switches2() { } func issue11667() { - switch 9223372036854775808 /* ERROR "overflows int" */ { + switch 9223372036854775808 /* ERROR "cannot use .* as int value.*\(overflows\)" */ { } - switch 9223372036854775808 /* ERROR "overflows int" */ { + switch 9223372036854775808 /* ERROR "cannot use .* as int value.*\(overflows\)" */ { case 9223372036854775808: } var x int From 74ec40fc8acffb81f17ccbaa498b15f694c25e4d Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 5 Nov 2020 01:05:04 +0000 Subject: [PATCH 354/403] path/filepath: revert "add WalkDir" This reverts CL 266240. Reason for revert: tests aren't passing on windows-amd64-longtest. Change-Id: If323c6254a42aff0418e2c0a9531f3d4c829a242 Reviewed-on: https://go-review.googlesource.com/c/go/+/267798 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/path/filepath/export_test.go | 2 - src/path/filepath/path.go | 211 ++++--------------------------- src/path/filepath/path_test.go | 89 +++++-------- 3 files changed, 53 insertions(+), 249 deletions(-) diff --git a/src/path/filepath/export_test.go b/src/path/filepath/export_test.go index e7ad7dd01a1..0cf9e3bca11 100644 --- a/src/path/filepath/export_test.go +++ b/src/path/filepath/export_test.go @@ -5,5 +5,3 @@ package filepath var LstatP = &lstat - -type DirEntryFromInfo = dirEntryFromInfo diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go index 3f7e5c713dc..dffd27db146 100644 --- a/src/path/filepath/path.go +++ b/src/path/filepath/path.go @@ -336,130 +336,25 @@ func Rel(basepath, targpath string) (string, error) { // as an error by any function. var SkipDir = errors.New("skip this directory") -// WalkDirFunc is the type of the function called by WalkDir to visit -// each each file or directory. +// WalkFunc is the type of the function called for each file or directory +// visited by Walk. The path argument contains the argument to Walk as a +// prefix; that is, if Walk is called with "dir", which is a directory +// containing the file "a", the walk function will be called with argument +// "dir/a". The info argument is the fs.FileInfo for the named path. // -// The path argument contains the argument to Walk as a prefix. -// That is, if Walk is called with root argument "dir" and finds a file -// named "a" in that directory, the walk function will be called with -// argument "dir/a". -// -// The directory and file are joined with Join, which may clean the -// directory name: if Walk is called with the root argument "x/../dir" -// and finds a file named "a" in that directory, the walk function will -// be called with argument "dir/a", not "x/../dir/a". -// -// The d argument is the fs.DirEntry for the named path. -// -// The error result returned by the function controls how WalkDir -// continues. If the function returns the special value SkipDir, WalkDir -// skips the current directory (path if d.IsDir() is true, otherwise -// path's parent directory). Otherwise, if the function returns a non-nil -// error, WalkDir stops entirely and returns that error. -// -// The err argument reports an error related to path, signaling that -// WalkDir will not walk into that directory. The function can decide how -// to handle that error; as described earlier, returning the error will -// cause WalkDir to stop walking the entire tree. -// -// WalkDir calls the function with a non-nil err argument in two cases. -// -// First, if the initial os.Lstat on the root directory fails, WalkDir -// calls the function with path set to root, d set to nil, and err set to -// the error from os.Lstat. -// -// Second, if a directory's ReadDir method fails, WalkDir calls the -// function with path set to the directory's path, d set to an -// fs.DirEntry describing the directory, and err set to the error from -// ReadDir. In this second case, the function is called twice with the -// path of the directory: the first call is before the directory read is -// attempted and has err set to nil, giving the function a chance to -// return SkipDir and avoid the ReadDir entirely. The second call is -// after a failed ReadDir and reports the error from ReadDir. -// (If ReadDir succeeds, there is no second call.) -// -// The differences between WalkDirFunc compared to WalkFunc are: -// -// - The second argument has type fs.DirEntry instead of fs.FileInfo. -// - The function is called before reading a directory, to allow SkipDir -// to bypass the directory read entirely. -// - If a directory read fails, the function is called a second time -// for that directory to report the error. -// -type WalkDirFunc func(path string, d fs.DirEntry, err error) error - -// WalkFunc is the type of the function called by Walk to visit each each -// file or directory. -// -// The path argument contains the argument to Walk as a prefix. -// That is, if Walk is called with root argument "dir" and finds a file -// named "a" in that directory, the walk function will be called with -// argument "dir/a". -// -// The directory and file are joined with Join, which may clean the -// directory name: if Walk is called with the root argument "x/../dir" -// and finds a file named "a" in that directory, the walk function will -// be called with argument "dir/a", not "x/../dir/a". -// -// The info argument is the fs.FileInfo for the named path. -// -// The error result returned by the function controls how Walk continues. -// If the function returns the special value SkipDir, Walk skips the -// current directory (path if info.IsDir() is true, otherwise path's -// parent directory). Otherwise, if the function returns a non-nil error, -// Walk stops entirely and returns that error. -// -// The err argument reports an error related to path, signaling that Walk -// will not walk into that directory. The function can decide how to -// handle that error; as described earlier, returning the error will -// cause Walk to stop walking the entire tree. -// -// Walk calls the function with a non-nil err argument in two cases. -// -// First, if an os.Lstat on the root directory or any directory or file -// in the tree fails, Walk calls the function with path set to that -// directory or file's path, info set to nil, and err set to the error -// from os.Lstat. -// -// Second, if a directory's Readdirnames method fails, Walk calls the -// function with path set to the directory's path, info, set to an -// fs.FileInfo describing the directory, and err set to the error from -// Readdirnames. +// If there was a problem walking to the file or directory named by path, the +// incoming error will describe the problem and the function can decide how +// to handle that error (and Walk will not descend into that directory). In the +// case of an error, the info argument will be nil. If an error is returned, +// processing stops. The sole exception is when the function returns the special +// value SkipDir. If the function returns SkipDir when invoked on a directory, +// Walk skips the directory's contents entirely. If the function returns SkipDir +// when invoked on a non-directory file, Walk skips the remaining files in the +// containing directory. type WalkFunc func(path string, info fs.FileInfo, err error) error var lstat = os.Lstat // for testing -// walkDir recursively descends path, calling walkDirFn. -func walkDir(path string, d fs.DirEntry, walkDirFn WalkDirFunc) error { - if err := walkDirFn(path, d, nil); err != nil || !d.IsDir() { - if err == SkipDir && d.IsDir() { - // Successfully skipped directory. - err = nil - } - return err - } - - dirs, err := readDir(path) - if err != nil { - // Second call, to report ReadDir error. - err = walkDirFn(path, d, err) - if err != nil { - return err - } - } - - for _, d1 := range dirs { - path1 := Join(path, d1.Name()) - if err := walkDir(path1, d1, walkDirFn); err != nil { - if err == SkipDir { - break - } - return err - } - } - return nil -} - // walk recursively descends path, calling walkFn. func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { if !info.IsDir() { @@ -498,62 +393,18 @@ func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { return nil } -// WalkDir walks the file tree rooted at root, calling fn for each file or -// directory in the tree, including root. -// -// All errors that arise visiting files and directories are filtered by fn: -// see the WalkDirFunc documentation for details. -// -// The files are walked in lexical order, which makes the output deterministic -// but requires WalkDir to read an entire directory into memory before proceeding -// to walk that directory. -// -// WalkDir does not follow symbolic links. -func WalkDir(root string, fn WalkDirFunc) error { - info, err := os.Lstat(root) - if err != nil { - err = fn(root, nil, err) - } else { - err = walkDir(root, &dirEntryFromInfo{info}, fn) - } - if err == SkipDir { - return nil - } - return err -} - -type dirEntryFromInfo struct { - fs.FileInfo -} - -func (e *dirEntryFromInfo) Type() fs.FileMode { - return e.Mode().Type() -} - -func (e *dirEntryFromInfo) Info() (fs.FileInfo, error) { - return e.FileInfo, nil -} - -// Walk walks the file tree rooted at root, calling fn for each file or -// directory in the tree, including root. -// -// All errors that arise visiting files and directories are filtered by fn: -// see the WalkFunc documentation for details. -// -// The files are walked in lexical order, which makes the output deterministic -// but requires Walk to read an entire directory into memory before proceeding -// to walk that directory. -// +// Walk walks the file tree rooted at root, calling walkFn for each file or +// directory in the tree, including root. All errors that arise visiting files +// and directories are filtered by walkFn. The files are walked in lexical +// order, which makes the output deterministic but means that for very +// large directories Walk can be inefficient. // Walk does not follow symbolic links. -// -// Walk is less efficient than WalkDir, introduced in Go 1.16, -// which avoids calling os.Lstat on every visited file or directory. -func Walk(root string, fn WalkFunc) error { +func Walk(root string, walkFn WalkFunc) error { info, err := os.Lstat(root) if err != nil { - err = fn(root, nil, err) + err = walkFn(root, nil, err) } else { - err = walk(root, info, fn) + err = walk(root, info, walkFn) } if err == SkipDir { return nil @@ -561,24 +412,8 @@ func Walk(root string, fn WalkFunc) error { return err } -// readDir reads the directory named by dirname and returns -// a sorted list of directory entries. -func readDir(dirname string) ([]fs.DirEntry, error) { - f, err := os.Open(dirname) - if err != nil { - return nil, err - } - dirs, err := f.ReadDir(-1) - f.Close() - if err != nil { - return nil, err - } - sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() }) - return dirs, nil -} - // readDirNames reads the directory named by dirname and returns -// a sorted list of directory entry names. +// a sorted list of directory entries. func readDirNames(dirname string) ([]string, error) { f, err := os.Open(dirname) if err != nil { diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index af6b69de099..7dc8b60c28c 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -394,8 +394,8 @@ func checkMarks(t *testing.T, report bool) { // Assumes that each node name is unique. Good enough for a test. // If clear is true, any incoming error is cleared before return. The errors // are always accumulated, though. -func mark(d fs.DirEntry, err error, errors *[]error, clear bool) error { - name := d.Name() +func mark(info fs.FileInfo, err error, errors *[]error, clear bool) error { + name := info.Name() walkTree(tree, tree.name, func(path string, n *Node) { if n.name == name { n.mark++ @@ -432,19 +432,6 @@ func chtmpdir(t *testing.T) (restore func()) { } func TestWalk(t *testing.T) { - walk := func(root string, fn filepath.WalkDirFunc) error { - return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { - return fn(path, &filepath.DirEntryFromInfo{info}, err) - }) - } - testWalk(t, walk, 1) -} - -func TestWalkDir(t *testing.T) { - testWalk(t, filepath.WalkDir, 2) -} - -func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVisit int) { if runtime.GOOS == "ios" { restore := chtmpdir(t) defer restore() @@ -468,11 +455,11 @@ func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVi makeTree(t) errors := make([]error, 0, 10) clear := true - markFn := func(path string, d fs.DirEntry, err error) error { - return mark(d, err, &errors, clear) + markFn := func(path string, info fs.FileInfo, err error) error { + return mark(info, err, &errors, clear) } // Expect no errors. - err = walk(tree.name, markFn) + err = filepath.Walk(tree.name, markFn) if err != nil { t.Fatalf("no error expected, found: %s", err) } @@ -482,17 +469,10 @@ func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVi checkMarks(t, true) errors = errors[0:0] - t.Run("PermErr", func(t *testing.T) { - // Test permission errors. Only possible if we're not root - // and only on some file systems (AFS, FAT). To avoid errors during - // all.bash on those file systems, skip during go test -short. - if os.Getuid() == 0 { - t.Skip("skipping as root") - } - if testing.Short() { - t.Skip("skipping in short mode") - } - + // Test permission errors. Only possible if we're not root + // and only on some file systems (AFS, FAT). To avoid errors during + // all.bash on those file systems, skip during go test -short. + if os.Getuid() > 0 && !testing.Short() { // introduce 2 errors: chmod top-level directories to 0 os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0) @@ -502,9 +482,9 @@ func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVi markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself - tree.entries[1].mark -= errVisit - tree.entries[3].mark -= errVisit - err := walk(tree.name, markFn) + tree.entries[1].mark-- + tree.entries[3].mark-- + err := filepath.Walk(tree.name, markFn) if err != nil { t.Fatalf("expected no error return from Walk, got %s", err) } @@ -520,10 +500,10 @@ func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVi markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself - tree.entries[1].mark -= errVisit - tree.entries[3].mark -= errVisit + tree.entries[1].mark-- + tree.entries[3].mark-- clear = false // error will stop processing - err = walk(tree.name, markFn) + err = filepath.Walk(tree.name, markFn) if err == nil { t.Fatalf("expected error return from Walk") } @@ -537,7 +517,7 @@ func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVi // restore permissions os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770) - }) + } } func touch(t *testing.T, name string) { @@ -564,7 +544,7 @@ func TestWalkSkipDirOnFile(t *testing.T) { touch(t, filepath.Join(td, "dir/foo2")) sawFoo2 := false - walker := func(path string) error { + walker := func(path string, info fs.FileInfo, err error) error { if strings.HasSuffix(path, "foo2") { sawFoo2 = true } @@ -573,31 +553,22 @@ func TestWalkSkipDirOnFile(t *testing.T) { } return nil } - walkFn := func(path string, _ fs.FileInfo, _ error) error { return walker(path) } - walkDirFn := func(path string, _ fs.DirEntry, _ error) error { return walker(path) } - check := func(t *testing.T, walk func(root string) error, root string) { - t.Helper() - sawFoo2 = false - err = walk(root) - if err != nil { - t.Fatal(err) - } - if sawFoo2 { - t.Errorf("SkipDir on file foo1 did not block processing of foo2") - } + err = filepath.Walk(td, walker) + if err != nil { + t.Fatal(err) + } + if sawFoo2 { + t.Errorf("SkipDir on file foo1 did not block processing of foo2") } - t.Run("Walk", func(t *testing.T) { - Walk := func(root string) error { return filepath.Walk(td, walkFn) } - check(t, Walk, td) - check(t, Walk, filepath.Join(td, "dir")) - }) - t.Run("WalkDir", func(t *testing.T) { - WalkDir := func(root string) error { return filepath.WalkDir(td, walkDirFn) } - check(t, WalkDir, td) - check(t, WalkDir, filepath.Join(td, "dir")) - }) + err = filepath.Walk(filepath.Join(td, "dir"), walker) + if err != nil { + t.Fatal(err) + } + if sawFoo2 { + t.Errorf("SkipDir on file foo1 did not block processing of foo2") + } } func TestWalkFileError(t *testing.T) { From 34c09695db93218217703362135c6fede35535e0 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 5 Nov 2020 10:08:11 -0500 Subject: [PATCH 355/403] cmd/go: revert "add GOVCS setting to control version control usage" This reverts CL 266420. Reason for revert: tests aren't passing on linux-{386,amd64}-longtest. Change-Id: Icec47cded795a51ef7569dfb2d93d9211b4fb578 Reviewed-on: https://go-review.googlesource.com/c/go/+/267799 Trust: Dmitri Shuralyov Reviewed-by: Bryan C. Mills --- src/cmd/go/alldocs.go | 177 +++++++------------------- src/cmd/go/internal/cfg/cfg.go | 1 - src/cmd/go/internal/envcmd/env.go | 1 - src/cmd/go/internal/help/helpdoc.go | 2 +- src/cmd/go/internal/modfetch/fetch.go | 13 +- src/cmd/go/internal/modget/get.go | 76 ----------- src/cmd/go/internal/modload/help.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 144 --------------------- src/cmd/go/internal/vcs/vcs_test.go | 104 --------------- src/cmd/go/main.go | 3 +- src/cmd/go/testdata/script/govcs.txt | 174 ------------------------- src/internal/cfg/cfg.go | 1 - 12 files changed, 56 insertions(+), 642 deletions(-) delete mode 100644 src/cmd/go/testdata/script/govcs.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index ded07e38b4a..23d44ddc708 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -49,11 +49,10 @@ // modules modules, module versions, and more // module-get module-aware go get // module-auth module authentication using go.sum +// module-private module configuration for non-public modules // packages package lists and patterns -// private configuration for downloading non-public code // testflag testing flags // testfunc testing functions -// vcs controlling version control with GOVCS // // Use "go help " for more information about that topic. // @@ -1800,7 +1799,7 @@ // Comma-separated list of glob patterns (in the syntax of Go's path.Match) // of module path prefixes that should always be fetched directly // or that should not be compared against the checksum database. -// See 'go help private'. +// See 'go help module-private'. // GOROOT // The root of the go tree. // GOSUMDB @@ -2870,7 +2869,7 @@ // followed by a pipe character, indicating it is safe to fall back on any error. // // The GOPRIVATE and GONOPROXY environment variables allow bypassing -// the proxy for selected modules. See 'go help private' for details. +// the proxy for selected modules. See 'go help module-private' for details. // // No matter the source of the modules, the go command checks downloads against // known checksums, to detect unexpected changes in the content of any specific @@ -2990,7 +2989,52 @@ // accepted, at the cost of giving up the security guarantee of verified repeatable // downloads for all modules. A better way to bypass the checksum database // for specific modules is to use the GOPRIVATE or GONOSUMDB environment -// variables. See 'go help private' for details. +// variables. See 'go help module-private' for details. +// +// The 'go env -w' command (see 'go help env') can be used to set these variables +// for future go command invocations. +// +// +// Module configuration for non-public modules +// +// The go command defaults to downloading modules from the public Go module +// mirror at proxy.golang.org. It also defaults to validating downloaded modules, +// regardless of source, against the public Go checksum database at sum.golang.org. +// These defaults work well for publicly available source code. +// +// The GOPRIVATE environment variable controls which modules the go command +// considers to be private (not available publicly) and should therefore not use the +// proxy or checksum database. The variable is a comma-separated list of +// glob patterns (in the syntax of Go's path.Match) of module path prefixes. +// For example, +// +// GOPRIVATE=*.corp.example.com,rsc.io/private +// +// causes the go command to treat as private any module with a path prefix +// matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, +// and rsc.io/private/quux. +// +// The GOPRIVATE environment variable may be used by other tools as well to +// identify non-public modules. For example, an editor could use GOPRIVATE +// to decide whether to hyperlink a package import to a godoc.org page. +// +// For fine-grained control over module download and validation, the GONOPROXY +// and GONOSUMDB environment variables accept the same kind of glob list +// and override GOPRIVATE for the specific decision of whether to use the proxy +// and checksum database, respectively. +// +// For example, if a company ran a module proxy serving private modules, +// users would configure go using: +// +// GOPRIVATE=*.corp.example.com +// GOPROXY=proxy.example.com +// GONOPROXY=none +// +// This would tell the go command and other tools that modules beginning with +// a corp.example.com subdomain are private but that the company proxy should +// be used for downloading both public and private modules, because +// GONOPROXY has been set to a pattern that won't match any modules, +// overriding GOPRIVATE. // // The 'go env -w' command (see 'go help env') can be used to set these variables // for future go command invocations. @@ -3080,56 +3124,6 @@ // by the go tool, as are directories named "testdata". // // -// Configuration for downloading non-public code -// -// The go command defaults to downloading modules from the public Go module -// mirror at proxy.golang.org. It also defaults to validating downloaded modules, -// regardless of source, against the public Go checksum database at sum.golang.org. -// These defaults work well for publicly available source code. -// -// The GOPRIVATE environment variable controls which modules the go command -// considers to be private (not available publicly) and should therefore not use the -// proxy or checksum database. The variable is a comma-separated list of -// glob patterns (in the syntax of Go's path.Match) of module path prefixes. -// For example, -// -// GOPRIVATE=*.corp.example.com,rsc.io/private -// -// causes the go command to treat as private any module with a path prefix -// matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, -// and rsc.io/private/quux. -// -// The GOPRIVATE environment variable may be used by other tools as well to -// identify non-public modules. For example, an editor could use GOPRIVATE -// to decide whether to hyperlink a package import to a godoc.org page. -// -// For fine-grained control over module download and validation, the GONOPROXY -// and GONOSUMDB environment variables accept the same kind of glob list -// and override GOPRIVATE for the specific decision of whether to use the proxy -// and checksum database, respectively. -// -// For example, if a company ran a module proxy serving private modules, -// users would configure go using: -// -// GOPRIVATE=*.corp.example.com -// GOPROXY=proxy.example.com -// GONOPROXY=none -// -// This would tell the go command and other tools that modules beginning with -// a corp.example.com subdomain are private but that the company proxy should -// be used for downloading both public and private modules, because -// GONOPROXY has been set to a pattern that won't match any modules, -// overriding GOPRIVATE. -// -// The GOPRIVATE variable is also used to define the "public" and "private" -// patterns for the GOVCS variable; see 'go help vcs'. For that usage, -// GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths -// instead of module paths. -// -// The 'go env -w' command (see 'go help env') can be used to set these variables -// for future go command invocations. -// -// // Testing flags // // The 'go test' command takes both flags that apply to 'go test' itself @@ -3422,77 +3416,4 @@ // See the documentation of the testing package for more information. // // -// Controlling version control with GOVCS -// -// The 'go get' command can run version control commands like git -// to download imported code. This functionality is critical to the decentralized -// Go package ecosystem, in which code can be imported from any server, -// but it is also a potential security problem, if a malicious server finds a -// way to cause the invoked version control command to run unintended code. -// -// To balance the functionality and security concerns, the 'go get' command -// by default will only use git and hg to download code from public servers. -// But it will use any known version control system (bzr, fossil, git, hg, svn) -// to download code from private servers, defined as those hosting packages -// matching the GOPRIVATE variable (see 'go help private'). The rationale behind -// allowing only Git and Mercurial is that these two systems have had the most -// attention to issues of being run as clients of untrusted servers. In contrast, -// Bazaar, Fossil, and Subversion have primarily been used in trusted, -// authenticated environments and are not as well scrutinized as attack surfaces. -// -// The version control command restrictions only apply when using direct version -// control access to download code. When downloading modules from a proxy, -// 'go get' uses the proxy protocol instead, which is always permitted. -// By default, the 'go get' command uses the Go module mirror (proxy.golang.org) -// for public packages and only falls back to version control for private -// packages or when the mirror refuses to serve a public package (typically for -// legal reasons). Therefore, clients can still access public code served from -// Bazaar, Fossil, or Subversion repositories by default, because those downloads -// use the Go module mirror, which takes on the security risk of running the -// version control commands, using a custom sandbox. -// -// The GOVCS variable can be used to change the allowed version control systems -// for specific packages (identified by a module or import path). -// The GOVCS variable applies both when using modules and when using GOPATH. -// When using modules, the patterns match against the module path. -// When using GOPATH, the patterns match against the import path -// corresponding to the root of the version control repository. -// -// The general form of the GOVCS setting is a comma-separated list of -// pattern:vcslist rules. The pattern is a glob pattern that must match -// one or more leading elements of the module or import path. The vcslist -// is a pipe-separated list of allowed version control commands, or "all" -// to allow use of any known command, or "off" to allow nothing. -// The earliest matching pattern in the list applies, even if later patterns -// might also match. -// -// For example, consider: -// -// GOVCS=github.com:git,evil.com:off,*:git|hg -// -// With this setting, code with an module or import path beginning with -// github.com/ can only use git; paths on evil.com cannot use any version -// control command, and all other paths (* matches everything) can use -// only git or hg. -// -// The special patterns "public" and "private" match public and private -// module or import paths. A path is private if it matches the GOPRIVATE -// variable; otherwise it is public. -// -// If no rules in the GOVCS variable match a particular module or import path, -// the 'go get' command applies its default rule, which can now be summarized -// in GOVCS notation as 'public:git|hg,private:all'. -// -// To allow unfettered use of any version control system for any package, use: -// -// GOVCS=*:all -// -// To disable all use of version control, use: -// -// GOVCS=*:off -// -// The 'go env -w' command (see 'go help env') can be used to set the GOVCS -// variable for future go command invocations. -// -// package main diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 9bc48132ae2..67d581f6e6d 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -268,7 +268,6 @@ var ( GONOPROXY = envOr("GONOPROXY", GOPRIVATE) GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE) GOINSECURE = Getenv("GOINSECURE") - GOVCS = Getenv("GOVCS") ) var SumdbDir = gopathDir("pkg/sumdb") diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index d65ace879db..557e4189213 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -87,7 +87,6 @@ func MkEnv() []cfg.EnvVar { {Name: "GOSUMDB", Value: cfg.GOSUMDB}, {Name: "GOTMPDIR", Value: cfg.Getenv("GOTMPDIR")}, {Name: "GOTOOLDIR", Value: base.ToolDir}, - {Name: "GOVCS", Value: cfg.GOVCS}, } if work.GccgoBin != "" { diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 50cf911407e..8dfabbaa4a0 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -526,7 +526,7 @@ General-purpose environment variables: Comma-separated list of glob patterns (in the syntax of Go's path.Match) of module path prefixes that should always be fetched directly or that should not be compared against the checksum database. - See 'go help private'. + See 'go help module-private'. GOROOT The root of the go tree. GOSUMDB diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index a3e2cd1f9d6..25e9fb62c13 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -848,16 +848,16 @@ the checksum database is not consulted, and all unrecognized modules are accepted, at the cost of giving up the security guarantee of verified repeatable downloads for all modules. A better way to bypass the checksum database for specific modules is to use the GOPRIVATE or GONOSUMDB environment -variables. See 'go help private' for details. +variables. See 'go help module-private' for details. The 'go env -w' command (see 'go help env') can be used to set these variables for future go command invocations. `, } -var HelpPrivate = &base.Command{ - UsageLine: "private", - Short: "configuration for downloading non-public code", +var HelpModulePrivate = &base.Command{ + UsageLine: "module-private", + Short: "module configuration for non-public modules", Long: ` The go command defaults to downloading modules from the public Go module mirror at proxy.golang.org. It also defaults to validating downloaded modules, @@ -898,11 +898,6 @@ be used for downloading both public and private modules, because GONOPROXY has been set to a pattern that won't match any modules, overriding GOPRIVATE. -The GOPRIVATE variable is also used to define the "public" and "private" -patterns for the GOVCS variable; see 'go help vcs'. For that usage, -GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths -instead of module paths. - The 'go env -w' command (see 'go help env') can be used to set these variables for future go command invocations. `, diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index f99441c2b9c..171c070ab34 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -176,82 +176,6 @@ Usage: ` + CmdGet.UsageLine + ` ` + CmdGet.Long, } -var HelpVCS = &base.Command{ - UsageLine: "vcs", - Short: "controlling version control with GOVCS", - Long: ` -The 'go get' command can run version control commands like git -to download imported code. This functionality is critical to the decentralized -Go package ecosystem, in which code can be imported from any server, -but it is also a potential security problem, if a malicious server finds a -way to cause the invoked version control command to run unintended code. - -To balance the functionality and security concerns, the 'go get' command -by default will only use git and hg to download code from public servers. -But it will use any known version control system (bzr, fossil, git, hg, svn) -to download code from private servers, defined as those hosting packages -matching the GOPRIVATE variable (see 'go help private'). The rationale behind -allowing only Git and Mercurial is that these two systems have had the most -attention to issues of being run as clients of untrusted servers. In contrast, -Bazaar, Fossil, and Subversion have primarily been used in trusted, -authenticated environments and are not as well scrutinized as attack surfaces. - -The version control command restrictions only apply when using direct version -control access to download code. When downloading modules from a proxy, -'go get' uses the proxy protocol instead, which is always permitted. -By default, the 'go get' command uses the Go module mirror (proxy.golang.org) -for public packages and only falls back to version control for private -packages or when the mirror refuses to serve a public package (typically for -legal reasons). Therefore, clients can still access public code served from -Bazaar, Fossil, or Subversion repositories by default, because those downloads -use the Go module mirror, which takes on the security risk of running the -version control commands, using a custom sandbox. - -The GOVCS variable can be used to change the allowed version control systems -for specific packages (identified by a module or import path). -The GOVCS variable applies both when using modules and when using GOPATH. -When using modules, the patterns match against the module path. -When using GOPATH, the patterns match against the import path -corresponding to the root of the version control repository. - -The general form of the GOVCS setting is a comma-separated list of -pattern:vcslist rules. The pattern is a glob pattern that must match -one or more leading elements of the module or import path. The vcslist -is a pipe-separated list of allowed version control commands, or "all" -to allow use of any known command, or "off" to allow nothing. -The earliest matching pattern in the list applies, even if later patterns -might also match. - -For example, consider: - - GOVCS=github.com:git,evil.com:off,*:git|hg - -With this setting, code with an module or import path beginning with -github.com/ can only use git; paths on evil.com cannot use any version -control command, and all other paths (* matches everything) can use -only git or hg. - -The special patterns "public" and "private" match public and private -module or import paths. A path is private if it matches the GOPRIVATE -variable; otherwise it is public. - -If no rules in the GOVCS variable match a particular module or import path, -the 'go get' command applies its default rule, which can now be summarized -in GOVCS notation as 'public:git|hg,private:all'. - -To allow unfettered use of any version control system for any package, use: - - GOVCS=*:all - -To disable all use of version control, use: - - GOVCS=*:off - -The 'go env -w' command (see 'go help env') can be used to set the GOVCS -variable for future go command invocations. -`, -} - var ( getD = CmdGet.Flag.Bool("d", false, "") getF = CmdGet.Flag.Bool("f", false, "") diff --git a/src/cmd/go/internal/modload/help.go b/src/cmd/go/internal/modload/help.go index c09dfe965d2..56920c28b99 100644 --- a/src/cmd/go/internal/modload/help.go +++ b/src/cmd/go/internal/modload/help.go @@ -365,7 +365,7 @@ list if the error is a 404 or 410 HTTP response or if the current proxy is followed by a pipe character, indicating it is safe to fall back on any error. The GOPRIVATE and GONOPROXY environment variables allow bypassing -the proxy for selected modules. See 'go help private' for details. +the proxy for selected modules. See 'go help module-private' for details. No matter the source of the modules, the go command checks downloads against known checksums, to detect unexpected changes in the content of any specific diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 3bdb1d4ef94..7812afd4888 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -22,10 +22,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" - "cmd/go/internal/search" "cmd/go/internal/web" - - "golang.org/x/mod/module" ) // A vcsCmd describes how to use a version control system @@ -594,146 +591,12 @@ func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) { } if vcsRet != nil { - if err := checkGOVCS(vcsRet, rootRet); err != nil { - return nil, "", err - } return vcsRet, rootRet, nil } return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) } -// A govcsRule is a single GOVCS rule like private:hg|svn. -type govcsRule struct { - pattern string - allowed []string -} - -// A govcsConfig is a full GOVCS configuration. -type govcsConfig []govcsRule - -func parseGOVCS(s string) (govcsConfig, error) { - s = strings.TrimSpace(s) - if s == "" { - return nil, nil - } - var cfg govcsConfig - have := make(map[string]string) - for _, item := range strings.Split(s, ",") { - item = strings.TrimSpace(item) - if item == "" { - return nil, fmt.Errorf("empty entry in GOVCS") - } - i := strings.Index(item, ":") - if i < 0 { - return nil, fmt.Errorf("malformed entry in GOVCS (missing colon): %q", item) - } - pattern, list := strings.TrimSpace(item[:i]), strings.TrimSpace(item[i+1:]) - if pattern == "" { - return nil, fmt.Errorf("empty pattern in GOVCS: %q", item) - } - if list == "" { - return nil, fmt.Errorf("empty VCS list in GOVCS: %q", item) - } - if search.IsRelativePath(pattern) { - return nil, fmt.Errorf("relative pattern not allowed in GOVCS: %q", pattern) - } - if old := have[pattern]; old != "" { - return nil, fmt.Errorf("unreachable pattern in GOVCS: %q after %q", item, old) - } - have[pattern] = item - allowed := strings.Split(list, "|") - for i, a := range allowed { - a = strings.TrimSpace(a) - if a == "" { - return nil, fmt.Errorf("empty VCS name in GOVCS: %q", item) - } - allowed[i] = a - } - cfg = append(cfg, govcsRule{pattern, allowed}) - } - return cfg, nil -} - -func (c *govcsConfig) allow(path string, private bool, vcs string) bool { - for _, rule := range *c { - match := false - switch rule.pattern { - case "private": - match = private - case "public": - match = !private - default: - // Note: rule.pattern is known to be comma-free, - // so MatchPrefixPatterns is only matching a single pattern for us. - match = module.MatchPrefixPatterns(rule.pattern, path) - } - if !match { - continue - } - for _, allow := range rule.allowed { - if allow == vcs || allow == "all" { - return true - } - } - return false - } - - // By default, nothing is allowed. - return false -} - -var ( - govcs govcsConfig - govcsErr error - govcsOnce sync.Once -) - -// defaultGOVCS is the default setting for GOVCS. -// Setting GOVCS adds entries ahead of these but does not remove them. -// (They are appended to the parsed GOVCS setting.) -// -// The rationale behind allowing only Git and Mercurial is that -// these two systems have had the most attention to issues -// of being run as clients of untrusted servers. In contrast, -// Bazaar, Fossil, and Subversion have primarily been used -// in trusted, authenticated environments and are not as well -// scrutinized as attack surfaces. -// -// See golang.org/issue/41730 for details. -var defaultGOVCS = govcsConfig{ - {"private", []string{"all"}}, - {"public", []string{"git", "hg"}}, -} - -func checkGOVCS(vcs *Cmd, root string) error { - if vcs.Cmd == "mod" { - // Direct module (proxy protocol) fetches don't - // involve an external version control system - // and are always allowed. - return nil - } - - govcsOnce.Do(func() { - govcs, govcsErr = parseGOVCS(os.Getenv("GOVCS")) - govcs = append(govcs, defaultGOVCS...) - }) - if govcsErr != nil { - return govcsErr - } - - private := module.MatchPrefixPatterns(cfg.GOPRIVATE, root) - if !govcs.allow(root, private, vcs.Cmd) { - what := "public" - if private { - what = "private" - } - return fmt.Errorf("GOVCS disallows using %s for %s %s", vcs.Cmd, what, root) - } - - return nil -} - // CheckNested checks for an incorrectly-nested VCS-inside-VCS // situation for dir, checking parents up until srcRoot. func CheckNested(vcs *Cmd, dir, srcRoot string) error { @@ -870,9 +733,6 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths if vcs == nil { return nil, fmt.Errorf("unknown version control system %q", match["vcs"]) } - if err := checkGOVCS(vcs, match["root"]); err != nil { - return nil, err - } var repoURL string if !srv.schemelessRepo { repoURL = match["repo"] @@ -997,10 +857,6 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se } } - if err := checkGOVCS(vcs, mmi.Prefix); err != nil { - return nil, err - } - rr := &RepoRoot{ Repo: mmi.RepoRoot, Root: mmi.Prefix, diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index 72d74a01e30..5b874204f1e 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -11,20 +11,11 @@ import ( "os" "path" "path/filepath" - "strings" "testing" "cmd/go/internal/web" ) -func init() { - // GOVCS defaults to public:git|hg,private:all, - // which breaks many tests here - they can't use non-git, non-hg VCS at all! - // Change to fully permissive. - // The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt. - os.Setenv("GOVCS", "*:all") -} - // Test that RepoRootForImportPath determines the correct RepoRoot for a given importPath. // TODO(cmang): Add tests for SVN and BZR. func TestRepoRootForImportPath(t *testing.T) { @@ -482,98 +473,3 @@ func TestValidateRepoRoot(t *testing.T) { } } } - -var govcsTests = []struct { - govcs string - path string - vcs string - ok bool -}{ - {"private:all", "is-public.com/foo", "zzz", false}, - {"private:all", "is-private.com/foo", "zzz", true}, - {"public:all", "is-public.com/foo", "zzz", true}, - {"public:all", "is-private.com/foo", "zzz", false}, - {"public:all,private:none", "is-public.com/foo", "zzz", true}, - {"public:all,private:none", "is-private.com/foo", "zzz", false}, - {"*:all", "is-public.com/foo", "zzz", true}, - {"golang.org:git", "golang.org/x/text", "zzz", false}, - {"golang.org:git", "golang.org/x/text", "git", true}, - {"golang.org:zzz", "golang.org/x/text", "zzz", true}, - {"golang.org:zzz", "golang.org/x/text", "git", false}, - {"golang.org:zzz", "golang.org/x/text", "zzz", true}, - {"golang.org:zzz", "golang.org/x/text", "git", false}, - {"golang.org:git|hg", "golang.org/x/text", "hg", true}, - {"golang.org:git|hg", "golang.org/x/text", "git", true}, - {"golang.org:git|hg", "golang.org/x/text", "zzz", false}, - {"golang.org:all", "golang.org/x/text", "hg", true}, - {"golang.org:all", "golang.org/x/text", "git", true}, - {"golang.org:all", "golang.org/x/text", "zzz", true}, - {"other.xyz/p:none,golang.org/x:git", "other.xyz/p/x", "git", false}, - {"other.xyz/p:none,golang.org/x:git", "unexpected.com", "git", false}, - {"other.xyz/p:none,golang.org/x:git", "golang.org/x/text", "zzz", false}, - {"other.xyz/p:none,golang.org/x:git", "golang.org/x/text", "git", true}, - {"other.xyz/p:none,golang.org/x:zzz", "golang.org/x/text", "zzz", true}, - {"other.xyz/p:none,golang.org/x:zzz", "golang.org/x/text", "git", false}, - {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "hg", true}, - {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "git", true}, - {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "zzz", false}, - {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "hg", true}, - {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "git", true}, - {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "zzz", true}, - {"other.xyz/p:none,golang.org/x:git", "golang.org/y/text", "zzz", false}, - {"other.xyz/p:none,golang.org/x:git", "golang.org/y/text", "git", false}, - {"other.xyz/p:none,golang.org/x:zzz", "golang.org/y/text", "zzz", false}, - {"other.xyz/p:none,golang.org/x:zzz", "golang.org/y/text", "git", false}, - {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "hg", false}, - {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "git", false}, - {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "zzz", false}, - {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "hg", false}, - {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "git", false}, - {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "zzz", false}, -} - -func TestGOVCS(t *testing.T) { - for _, tt := range govcsTests { - cfg, err := parseGOVCS(tt.govcs) - if err != nil { - t.Errorf("parseGOVCS(%q): %v", tt.govcs, err) - continue - } - private := strings.HasPrefix(tt.path, "is-private") - ok := cfg.allow(tt.path, private, tt.vcs) - if ok != tt.ok { - t.Errorf("parseGOVCS(%q).allow(%q, %v, %q) = %v, want %v", - tt.govcs, tt.path, private, tt.vcs, ok, tt.ok) - } - } -} - -var govcsErrors = []struct { - s string - err string -}{ - {`,`, `empty entry in GOVCS`}, - {`,x`, `empty entry in GOVCS`}, - {`x,`, `malformed entry in GOVCS (missing colon): "x"`}, - {`x:y,`, `empty entry in GOVCS`}, - {`x`, `malformed entry in GOVCS (missing colon): "x"`}, - {`x:`, `empty VCS list in GOVCS: "x:"`}, - {`x:|`, `empty VCS name in GOVCS: "x:|"`}, - {`x:y|`, `empty VCS name in GOVCS: "x:y|"`}, - {`x:|y`, `empty VCS name in GOVCS: "x:|y"`}, - {`x:y,z:`, `empty VCS list in GOVCS: "z:"`}, - {`x:y,z:|`, `empty VCS name in GOVCS: "z:|"`}, - {`x:y,z:|w`, `empty VCS name in GOVCS: "z:|w"`}, - {`x:y,z:w|`, `empty VCS name in GOVCS: "z:w|"`}, - {`x:y,z:w||v`, `empty VCS name in GOVCS: "z:w||v"`}, - {`x:y,x:z`, `unreachable pattern in GOVCS: "x:z" after "x:y"`}, -} - -func TestGOVCSErrors(t *testing.T) { - for _, tt := range govcsErrors { - _, err := parseGOVCS(tt.s) - if err == nil || !strings.Contains(err.Error(), tt.err) { - t.Errorf("parseGOVCS(%s): err=%v, want %v", tt.s, err, tt.err) - } - } -} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 9cc44da84db..37bb7d6d270 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -75,11 +75,10 @@ func init() { modload.HelpModules, modget.HelpModuleGet, modfetch.HelpModuleAuth, + modfetch.HelpModulePrivate, help.HelpPackages, - modfetch.HelpPrivate, test.HelpTestflag, test.HelpTestfunc, - modget.HelpVCS, } } diff --git a/src/cmd/go/testdata/script/govcs.txt b/src/cmd/go/testdata/script/govcs.txt deleted file mode 100644 index cc10a369155..00000000000 --- a/src/cmd/go/testdata/script/govcs.txt +++ /dev/null @@ -1,174 +0,0 @@ -env GO111MODULE=on -env proxy=$GOPROXY -env GOPROXY=direct - -# GOVCS stops go get -env GOVCS='*:none' -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' -env GOPRIVATE='github.com/google' -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' - -# public pattern works -env GOPRIVATE='github.com/google' -env GOVCS='public:all,private:none' -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' - -# private pattern works -env GOPRIVATE='hubgit.com/google' -env GOVCS='private:all,public:none' -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' - -# other patterns work (for more patterns, see TestGOVCS) -env GOPRIVATE= -env GOVCS='github.com:svn|hg' -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' -env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' - -# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) -env GOVCS='git' -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"' - -env GOVCS=github.com:hg,github.com:git -! go get github.com/google/go-cmp -stderr 'go get github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"' - -# bad GOVCS patterns do not stop commands that do not need to check VCS -go list -env GOPROXY=$proxy -go get -d rsc.io/quote # ok because used proxy -env GOPROXY=direct - -# svn is disallowed by default -env GOPRIVATE= -env GOVCS= -! go get rsc.io/nonexist.svn/hello -stderr 'go get rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn' - -# fossil is disallowed by default -env GOPRIVATE= -env GOVCS= -! go get rsc.io/nonexist.fossil/hello -stderr 'go get rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil' - -# bzr is disallowed by default -env GOPRIVATE= -env GOVCS= -! go get rsc.io/nonexist.bzr/hello -stderr 'go get rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr' - -# git is OK by default -env GOVCS= -env GONOSUMDB='*' -[net] [exec:git] [!short] go get rsc.io/sampler - -# hg is OK by default -env GOVCS= -env GONOSUMDB='*' -[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello - -# git can be disallowed -env GOVCS=public:hg -! go get rsc.io/nonexist.git/hello -stderr 'go get rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git' - -# hg can be disallowed -env GOVCS=public:git -! go get rsc.io/nonexist.hg/hello -stderr 'go get rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg' - -# Repeat in GOPATH mode. Error texts slightly different. - -env GO111MODULE=off - -# GOVCS stops go get -env GOVCS='*:none' -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' -env GOPRIVATE='github.com/google' -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' - -# public pattern works -env GOPRIVATE='github.com/google' -env GOVCS='public:all,private:none' -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' - -# private pattern works -env GOPRIVATE='hubgit.com/google' -env GOVCS='private:all,public:none' -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' - -# other patterns work (for more patterns, see TestGOVCS) -env GOPRIVATE= -env GOVCS='github.com:svn|hg' -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' -env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' - -# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) -env GOVCS='git' -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"' - -env GOVCS=github.com:hg,github.com:git -! go get github.com/google/go-cmp -stderr 'package github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"' - -# bad GOVCS patterns do not stop commands that do not need to check VCS -go list - -# svn is disallowed by default -env GOPRIVATE= -env GOVCS= -! go get rsc.io/nonexist.svn/hello -stderr 'package rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn' - -# fossil is disallowed by default -env GOPRIVATE= -env GOVCS= -! go get rsc.io/nonexist.fossil/hello -stderr 'package rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil' - -# bzr is disallowed by default -env GOPRIVATE= -env GOVCS= -! go get rsc.io/nonexist.bzr/hello -stderr 'package rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr' - -# git is OK by default -env GOVCS= -env GONOSUMDB='*' -[net] [exec:git] [!short] go get rsc.io/sampler - -# hg is OK by default -env GOVCS= -env GONOSUMDB='*' -[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello - -# git can be disallowed -env GOVCS=public:hg -! go get rsc.io/nonexist.git/hello -stderr 'package rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git' - -# hg can be disallowed -env GOVCS=public:git -! go get rsc.io/nonexist.hg/hello -stderr 'package rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg' - --- go.mod -- -module m - --- p.go -- -package p diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go index 553021374d5..bdbe9df3e75 100644 --- a/src/internal/cfg/cfg.go +++ b/src/internal/cfg/cfg.go @@ -58,7 +58,6 @@ const KnownEnv = ` GOSUMDB GOTMPDIR GOTOOLDIR - GOVCS GOWASM GO_EXTLINK_ENABLED PKG_CONFIG From 8ab8125fbd70e439f677c37832a678e6ce1067d7 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 4 Nov 2020 11:52:43 -0800 Subject: [PATCH 356/403] os: remove unused variable in unix implementation of File.readdir Change-Id: I0dd8a325bce6ed12d1ec1dc206ded62398925aef Reviewed-on: https://go-review.googlesource.com/c/go/+/267758 Run-TryBot: Brad Fitzpatrick Reviewed-by: Emmanuel Odeke Reviewed-by: Ian Lance Taylor TryBot-Result: Go Bot Trust: Brad Fitzpatrick Trust: Emmanuel Odeke --- src/os/dir_unix.go | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go index 3e5a6983501..0e1eab1c965 100644 --- a/src/os/dir_unix.go +++ b/src/os/dir_unix.go @@ -36,9 +36,16 @@ func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEn } d := f.dirinfo - size := n - if size <= 0 { - size = 100 + // Change the meaning of n for the implementation below. + // + // The n above was for the public interface of "if n <= 0, + // Readdir returns all the FileInfo from the directory in a + // single slice". + // + // But below, we use only negative to mean looping until the + // end and positive to mean bounded, with positive + // terminating at 0. + if n == 0 { n = -1 } @@ -88,7 +95,9 @@ func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEn if string(name) == "." || string(name) == ".." { continue } - n-- + if n > 0 { // see 'n == 0' comment above + n-- + } if mode == readdirName { names = append(names, string(name)) } else if mode == readdirDirEntry { From db8142fb8631df3ee56983cbc13db997c16f2f6f Mon Sep 17 00:00:00 2001 From: Vee Zhang Date: Thu, 5 Nov 2020 08:27:55 +0000 Subject: [PATCH 357/403] runtime: fix file references in hiter's comments The file "cmd/internal/gc/range.go" does not exist, but should be "cmd/compile/internal/gc/range.go". Change-Id: I26e5560b9d0b7eea8502c6b375e45fc87aed1276 GitHub-Last-Rev: 5f19dca7e9dab942a54257c5da05bce780744b19 GitHub-Pull-Request: golang/go#42391 Reviewed-on: https://go-review.googlesource.com/c/go/+/267837 Reviewed-by: Ian Lance Taylor Trust: Emmanuel Odeke --- src/runtime/map.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/map.go b/src/runtime/map.go index 5ac3a9958bd..0beff57a1a5 100644 --- a/src/runtime/map.go +++ b/src/runtime/map.go @@ -162,8 +162,8 @@ type bmap struct { // If you modify hiter, also change cmd/compile/internal/gc/reflect.go to indicate // the layout of this structure. type hiter struct { - key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/internal/gc/range.go). - elem unsafe.Pointer // Must be in second position (see cmd/internal/gc/range.go). + key unsafe.Pointer // Must be in first position. Write nil to indicate iteration end (see cmd/compile/internal/gc/range.go). + elem unsafe.Pointer // Must be in second position (see cmd/compile/internal/gc/range.go). t *maptype h *hmap buckets unsafe.Pointer // bucket ptr at hash_iter initialization time From 40f0359d52e04ed124a8f81e1ef8ac86957dd983 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 3 Jun 2020 11:03:22 -0700 Subject: [PATCH 358/403] runtime: avoid a bit of unneeded work when MemProfileRate==1 Change-Id: I1dc355bcaeb0e5fb06a7fddc4cf5db596d22e0b3 Reviewed-on: https://go-review.googlesource.com/c/go/+/236148 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Trust: Emmanuel Odeke Reviewed-by: Austin Clements --- src/runtime/malloc.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 551acd07969..f20ded5bf71 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -1221,6 +1221,13 @@ func profilealloc(mp *m, x unsafe.Pointer, size uintptr) { // distribution (exp(MemProfileRate)), so the best return value is a random // number taken from an exponential distribution whose mean is MemProfileRate. func nextSample() uintptr { + if MemProfileRate == 1 { + // Callers assign our return value to + // mcache.next_sample, but next_sample is not used + // when the rate is 1. So avoid the math below and + // just return something. + return 0 + } if GOOS == "plan9" { // Plan 9 doesn't support floating point in note handler. if g := getg(); g == g.m.gsignal { From 04b5b4f740a34a95a10253a0e34779bb259ec9c4 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 30 Oct 2020 12:24:51 -0400 Subject: [PATCH 359/403] cmd/go/internal/modload: return a module-only result from QueryPattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows a single QueryPattern call to resolve a path that could be either a package or a module. It is important to be able to make a single QueryPattern call — rather than a QueryPattern followed by a Query for the specific module path — to provide appropriate fallback behavior: if the proxy returns package results but does not contain a module result, we don't want to fall back to the next proxy to look for the (probably-nonexistent) module. For #37438 Change-Id: I419b8bb3ab4565f443bb5cee9a8b206f453b9801 Reviewed-on: https://go-review.googlesource.com/c/go/+/266657 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modget/get.go | 19 ++-- src/cmd/go/internal/modload/import.go | 2 +- src/cmd/go/internal/modload/query.go | 86 +++++++++++++------ src/cmd/go/internal/work/build.go | 2 +- .../script/mod_get_downgrade_missing.txt | 16 +++- 5 files changed, 81 insertions(+), 44 deletions(-) diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 171c070ab34..6d83af710fe 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -912,22 +912,15 @@ func getQuery(ctx context.Context, path, vers string, prevM module.Version, forc // If it turns out to only exist as a module, we can detect the resulting // PackageNotInModuleError and avoid a second round-trip through (potentially) // all of the configured proxies. - results, err := modload.QueryPattern(ctx, path, vers, modload.Selected, allowed) + results, modOnly, err := modload.QueryPattern(ctx, path, vers, modload.Selected, allowed) if err != nil { - // If the path doesn't contain a wildcard, check whether it was actually a - // module path instead. If so, return that. - if !strings.Contains(path, "...") { - var modErr *modload.PackageNotInModuleError - if errors.As(err, &modErr) && modErr.Mod.Path == path { - if modErr.Mod.Version != vers { - logOncef("go: %s %s => %s", path, vers, modErr.Mod.Version) - } - return modErr.Mod, nil - } - } - return module.Version{}, err } + if len(results) == 0 { + // The path doesn't contain a wildcard, but was actually a + // module path instead. Return that. + return modOnly.Mod, nil + } m := results[0].Mod if m.Path != path { diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index e9593470203..193edfdd208 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -383,7 +383,7 @@ func queryImport(ctx context.Context, path string) (module.Version, error) { // and return m, dir, ImpportMissingError. fmt.Fprintf(os.Stderr, "go: finding module for package %s\n", path) - candidates, err := QueryPattern(ctx, path, "latest", Selected, CheckAllowed) + candidates, err := QueryPackages(ctx, path, "latest", Selected, CheckAllowed) if err != nil { if errors.Is(err, fs.ErrNotExist) { // Return "cannot find module providing package […]" instead of whatever diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 3927051015a..2e9d72a6bfe 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -504,20 +504,39 @@ type QueryResult struct { Packages []string } +// QueryPackages is like QueryPattern, but requires that the pattern match at +// least one package and omits the non-package result (if any). +func QueryPackages(ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) ([]QueryResult, error) { + pkgMods, modOnly, err := QueryPattern(ctx, pattern, query, current, allowed) + + if len(pkgMods) == 0 && err == nil { + return nil, &PackageNotInModuleError{ + Mod: modOnly.Mod, + Replacement: Replacement(modOnly.Mod), + Query: query, + Pattern: pattern, + } + } + + return pkgMods, err +} + // QueryPattern looks up the module(s) containing at least one package matching // the given pattern at the given version. The results are sorted by module path -// length in descending order. +// length in descending order. If any proxy provides a non-empty set of candidate +// modules, no further proxies are tried. // -// QueryPattern queries modules with package paths up to the first "..." -// in the pattern. For the pattern "example.com/a/b.../c", QueryPattern would -// consider prefixes of "example.com/a". If multiple modules have versions -// that match the query and packages that match the pattern, QueryPattern -// picks the one with the longest module path. +// For wildcard patterns, QueryPattern looks in modules with package paths up to +// the first "..." in the pattern. For the pattern "example.com/a/b.../c", +// QueryPattern would consider prefixes of "example.com/a". // // If any matching package is in the main module, QueryPattern considers only // the main module and only the version "latest", without checking for other // possible modules. -func QueryPattern(ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) ([]QueryResult, error) { +// +// QueryPattern always returns at least one QueryResult (which may be only +// modOnly) or a non-nil error. +func QueryPattern(ctx context.Context, pattern, query string, current func(string) string, allowed AllowedFunc) (pkgMods []QueryResult, modOnly *QueryResult, err error) { ctx, span := trace.StartSpan(ctx, "modload.QueryPattern "+pattern+" "+query) defer span.Done() @@ -531,6 +550,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin } var match func(mod module.Version, root string, isLocal bool) *search.Match + matchPattern := search.MatchPattern(pattern) if i := strings.Index(pattern, "..."); i >= 0 { base = pathpkg.Dir(pattern[:i+3]) @@ -558,20 +578,29 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if HasModRoot() { m := match(Target, modRoot, true) if len(m.Pkgs) > 0 { - if query != "latest" { - return nil, fmt.Errorf("can't query specific version for package %s in the main module (%s)", pattern, Target.Path) + if query != "latest" && query != "upgrade" && query != "patch" { + return nil, nil, fmt.Errorf("can't query version %q for package %s in the main module (%s)", query, pattern, Target.Path) } if err := allowed(ctx, Target); err != nil { - return nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed: %w", pattern, Target.Path, err) + return nil, nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed: %w", pattern, Target.Path, err) } return []QueryResult{{ Mod: Target, Rev: &modfetch.RevInfo{Version: Target.Version}, Packages: m.Pkgs, - }}, nil + }}, nil, nil } if err := firstError(m); err != nil { - return nil, err + return nil, nil, err + } + + if query != "latest" && query != "upgrade" && query != "patch" && matchPattern(Target.Path) { + if err := allowed(ctx, Target); err == nil { + modOnly = &QueryResult{ + Mod: Target, + Rev: &modfetch.RevInfo{Version: Target.Version}, + } + } } } @@ -580,14 +609,17 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin candidateModules = modulePrefixesExcludingTarget(base) ) if len(candidateModules) == 0 { - return nil, &PackageNotInModuleError{ - Mod: Target, - Query: query, - Pattern: pattern, + if modOnly == nil { + return nil, nil, &PackageNotInModuleError{ + Mod: Target, + Query: query, + Pattern: pattern, + } } + return nil, modOnly, nil } - err := modfetch.TryProxies(func(proxy string) error { + err = modfetch.TryProxies(func(proxy string) error { queryModule := func(ctx context.Context, path string) (r QueryResult, err error) { ctx, span := trace.StartSpan(ctx, "modload.QueryPattern.queryModule ["+proxy+"] "+path) defer span.Done() @@ -606,7 +638,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin } m := match(r.Mod, root, isLocal) r.Packages = m.Pkgs - if len(r.Packages) == 0 { + if len(r.Packages) == 0 && !matchPattern(path) { if err := firstError(m); err != nil { return r, err } @@ -620,12 +652,19 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return r, nil } - var err error - results, err = queryPrefixModules(ctx, candidateModules, queryModule) + allResults, err := queryPrefixModules(ctx, candidateModules, queryModule) + results = allResults[:0] + for _, r := range allResults { + if len(r.Packages) == 0 { + modOnly = &r + } else { + results = append(results, r) + } + } return err }) - return results, err + return results[:len(results):len(results)], modOnly, err } // modulePrefixesExcludingTarget returns all prefixes of path that may plausibly @@ -651,11 +690,6 @@ func modulePrefixesExcludingTarget(path string) []string { return prefixes } -type prefixResult struct { - QueryResult - err error -} - func queryPrefixModules(ctx context.Context, candidateModules []string, queryModule func(ctx context.Context, path string) (QueryResult, error)) (found []QueryResult, err error) { ctx, span := trace.StartSpan(ctx, "modload.queryPrefixModules") defer span.Done() diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 3531612dc61..181bb3b8744 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -741,7 +741,7 @@ func installOutsideModule(ctx context.Context, args []string) { // Don't check for retractions if a specific revision is requested. allowed = nil } - qrs, err := modload.QueryPattern(ctx, patterns[0], version, modload.Selected, allowed) + qrs, err := modload.QueryPackages(ctx, patterns[0], version, modload.Selected, allowed) if err != nil { base.Fatalf("go install %s: %v", args[0], err) } diff --git a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt index 49e17e6507d..543f9f8111d 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt @@ -3,14 +3,24 @@ cp go.mod go.mod.orig # getting a specific version of a module along with a pattern # not yet present in that module should report the version mismatch # rather than a "matched no packages" warning. + ! go get example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... stderr '^go get: conflicting versions for module example\.net/pkgadded: v1\.1\.0 and v1\.2\.0$' ! stderr 'matched no packages' cmp go.mod.orig go.mod -! go get example.net/pkgadded/...@v1.0.0 -stderr '^go get example\.net/pkgadded/\.\.\.@v1\.0\.0: module example\.net/pkgadded@v1\.0\.0 found, but does not contain packages matching example\.net/pkgadded/\.\.\.$' -cmp go.mod.orig go.mod + +# A wildcard pattern should match a package in a module with that path. + +go get example.net/pkgadded/...@v1.0.0 +go list -m all +stdout '^example.net/pkgadded v1.0.0' +cp go.mod.orig go.mod + + +# If we need to resolve a transitive dependency of a package, +# and another argument constrains away the version that provides that +# package, then 'go get' should fail with a useful error message. ! go get example.net/pkgadded@v1.0.0 . stderr -count=1 '^go: found example.net/pkgadded/subpkg in example.net/pkgadded v1\.2\.0$' # TODO: We shouldn't even try v1.2.0. From 0c861724a05009a75eaa2a3f187101bd13a583b5 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 30 Oct 2020 14:42:56 -0400 Subject: [PATCH 360/403] cmd/go/internal/modload: add structured errors for queries matching the main module For #37438 Change-Id: I7df80ae0917b0b4ecad98947da39ddf8554b07c7 Reviewed-on: https://go-review.googlesource.com/c/go/+/266717 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/query.go | 46 ++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 2e9d72a6bfe..99cbac1aa79 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -109,8 +109,8 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed } if path == Target.Path { - if query != "latest" { - return nil, fmt.Errorf("can't query specific version (%q) for the main module (%s)", query, path) + if query != "latest" && query != "upgrade" && query != "patch" { + return nil, &QueryMatchesMainModuleError{Pattern: path, Query: query} } if err := allowed(ctx, Target); err != nil { return nil, fmt.Errorf("internal error: main module version is not allowed: %w", err) @@ -579,7 +579,11 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin m := match(Target, modRoot, true) if len(m.Pkgs) > 0 { if query != "latest" && query != "upgrade" && query != "patch" { - return nil, nil, fmt.Errorf("can't query version %q for package %s in the main module (%s)", query, pattern, Target.Path) + return nil, nil, &QueryMatchesPackagesInMainModuleError{ + Pattern: pattern, + Query: query, + Packages: m.Pkgs, + } } if err := allowed(ctx, Target); err != nil { return nil, nil, fmt.Errorf("internal error: package %s is in the main module (%s), but version is not allowed: %w", pattern, Target.Path, err) @@ -1023,3 +1027,39 @@ func (rr *replacementRepo) replacementStat(v string) (*modfetch.RevInfo, error) } return rev, nil } + +// A QueryMatchesMainModuleError indicates that a query requests +// a version of the main module that cannot be satisfied. +// (The main module's version cannot be changed.) +type QueryMatchesMainModuleError struct { + Pattern string + Query string +} + +func (e *QueryMatchesMainModuleError) Error() string { + if e.Pattern == Target.Path { + return fmt.Sprintf("can't request version %q of the main module (%s)", e.Query, e.Pattern) + } + + return fmt.Sprintf("can't request version %q of pattern %q that includes the main module (%s)", e.Query, e.Pattern, Target.Path) +} + +// A QueryMatchesPackagesInMainModuleError indicates that a query cannot be +// satisfied because it matches one or more packages found in the main module. +type QueryMatchesPackagesInMainModuleError struct { + Pattern string + Query string + Packages []string +} + +func (e *QueryMatchesPackagesInMainModuleError) Error() string { + if len(e.Packages) > 1 { + return fmt.Sprintf("pattern %s matches %d packages in the main module, so can't request version %s", e.Pattern, len(e.Packages), e.Query) + } + + if search.IsMetaPackage(e.Pattern) || strings.Contains(e.Pattern, "...") { + return fmt.Sprintf("pattern %s matches package %s in the main module, so can't request version %s", e.Pattern, e.Packages[0], e.Query) + } + + return fmt.Sprintf("package %s is in the main module, so can't request version %s", e.Packages[0], e.Query) +} From 4a3339223c82b6d184d2fd990b996ed0b365653c Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 30 Oct 2020 21:47:32 -0400 Subject: [PATCH 361/403] cmd/go/internal/mvs: test a downgrade where the target explicitly requires itself Also clean up the test assertions, and add a check for assertions missing function invocations (there was one). For #37438 Change-Id: Iafbfeae2c25217eac894181e01480b25b7cffbd4 Reviewed-on: https://go-review.googlesource.com/c/go/+/266859 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Michael Matloob --- src/cmd/go/internal/mvs/mvs.go | 3 ++- src/cmd/go/internal/mvs/mvs_test.go | 36 +++++++++++++++++------------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/cmd/go/internal/mvs/mvs.go b/src/cmd/go/internal/mvs/mvs.go index 3524a7a90ee..fe6d14e9dcb 100644 --- a/src/cmd/go/internal/mvs/mvs.go +++ b/src/cmd/go/internal/mvs/mvs.go @@ -342,7 +342,8 @@ func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]mod } // Downgrade returns a build list for the target module -// in which the given additional modules are downgraded. +// in which the given additional modules are downgraded, +// potentially overriding the requirements of the target. // // The versions to be downgraded may be unreachable from reqs.Latest and // reqs.Previous, but the methods of reqs must otherwise handle such versions diff --git a/src/cmd/go/internal/mvs/mvs_test.go b/src/cmd/go/internal/mvs/mvs_test.go index f6f07b200ea..af1bb216a7f 100644 --- a/src/cmd/go/internal/mvs/mvs_test.go +++ b/src/cmd/go/internal/mvs/mvs_test.go @@ -54,7 +54,7 @@ build A: A B C D2 E2 name: cross1V A: B2 C D2 E1 -B1: +B1: B2: D1 C: D2 D1: E2 @@ -63,7 +63,7 @@ build A: A B2 C D2 E2 name: cross1U A: B1 C -B1: +B1: B2: D1 C: D2 D1: E2 @@ -72,7 +72,7 @@ build A: A B1 C D2 E1 upgrade A B2: A B2 C D2 E2 name: cross1R -A: B C +A: B C B: D2 C: D1 D1: E2 @@ -165,7 +165,7 @@ M: A1 B1 A1: X1 B1: X2 X1: I1 -X2: +X2: build M: M A1 B1 I1 X2 # Upgrade from B1 to B2 should not drop the transitive dep on D. @@ -229,28 +229,31 @@ E1: F1: downgrade A F1: A B1 E1 -name: down3 -A: +name: downcycle +A: A B2 +B2: A +B1: +downgrade A B1: A B1 # golang.org/issue/25542. name: noprev1 A: B4 C2 -B2.hidden: -C2: +B2.hidden: +C2: downgrade A B2.hidden: A B2.hidden C2 name: noprev2 A: B4 C2 -B2.hidden: -B1: -C2: +B2.hidden: +B1: +C2: downgrade A B2.hidden: A B2.hidden C2 name: noprev3 A: B4 C2 -B3: -B2.hidden: -C2: +B3: +B2.hidden: +C2: downgrade A B2.hidden: A B2.hidden C2 # Cycles involving the target. @@ -315,7 +318,7 @@ M: A1 B1 A1: X1 B1: X2 X1: I1 -X2: +X2: req M: A1 B1 name: reqnone @@ -338,6 +341,9 @@ func Test(t *testing.T) { for _, fn := range fns { fn(t) } + if len(fns) == 0 { + t.Errorf("no functions tested") + } }) } } From a19a4dcb987d010b5ed0cecc4b377382f42a6ecc Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 30 Oct 2020 22:13:51 -0400 Subject: [PATCH 362/403] cmd/go/internal/mvs: in Upgrade, pass upgrades to buildList as upgrades This has no impact on the resulting build list, but provides clearer diagnostics if reqs.Required returns an error for one of the upgraded modules. For #37438 Change-Id: I5cd8f72a9b7b9a0b185e1a728f46fefbd2f09b4a Reviewed-on: https://go-review.googlesource.com/c/go/+/266897 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Michael Matloob --- src/cmd/go/internal/mvs/mvs.go | 51 ++++++++++++++++++++--------- src/cmd/go/internal/mvs/mvs_test.go | 4 +-- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/cmd/go/internal/mvs/mvs.go b/src/cmd/go/internal/mvs/mvs.go index fe6d14e9dcb..b630b610f10 100644 --- a/src/cmd/go/internal/mvs/mvs.go +++ b/src/cmd/go/internal/mvs/mvs.go @@ -108,19 +108,21 @@ func buildList(target module.Version, reqs Reqs, upgrade func(module.Version) (m node := &modGraphNode{m: m} mu.Lock() modGraph[m] = node - if v, ok := min[m.Path]; !ok || reqs.Max(v, m.Version) != v { - min[m.Path] = m.Version + if m.Version != "none" { + if v, ok := min[m.Path]; !ok || reqs.Max(v, m.Version) != v { + min[m.Path] = m.Version + } } mu.Unlock() - required, err := reqs.Required(m) - if err != nil { - setErr(node, err) - return - } - node.required = required - for _, r := range node.required { - if r.Version != "none" { + if m.Version != "none" { + required, err := reqs.Required(m) + if err != nil { + setErr(node, err) + return + } + node.required = required + for _, r := range node.required { work.Add(r) } } @@ -333,12 +335,31 @@ func Upgrade(target module.Version, reqs Reqs, upgrade ...module.Version) ([]mod if err != nil { return nil, err } - // TODO: Maybe if an error is given, - // rerun with BuildList(upgrade[0], reqs) etc - // to find which ones are the buggy ones. + + pathInList := make(map[string]bool, len(list)) + for _, m := range list { + pathInList[m.Path] = true + } list = append([]module.Version(nil), list...) - list = append(list, upgrade...) - return BuildList(target, &override{target, list, reqs}) + + upgradeTo := make(map[string]string, len(upgrade)) + for _, u := range upgrade { + if !pathInList[u.Path] { + list = append(list, module.Version{Path: u.Path, Version: "none"}) + } + if prev, dup := upgradeTo[u.Path]; dup { + upgradeTo[u.Path] = reqs.Max(prev, u.Version) + } else { + upgradeTo[u.Path] = u.Version + } + } + + return buildList(target, &override{target, list, reqs}, func(m module.Version) (module.Version, error) { + if v, ok := upgradeTo[m.Path]; ok { + return module.Version{Path: m.Path, Version: v}, nil + } + return m, nil + }) } // Downgrade returns a build list for the target module diff --git a/src/cmd/go/internal/mvs/mvs_test.go b/src/cmd/go/internal/mvs/mvs_test.go index af1bb216a7f..721cd9635c8 100644 --- a/src/cmd/go/internal/mvs/mvs_test.go +++ b/src/cmd/go/internal/mvs/mvs_test.go @@ -491,9 +491,9 @@ func (r reqsMap) Max(v1, v2 string) string { } func (r reqsMap) Upgrade(m module.Version) (module.Version, error) { - var u module.Version + u := module.Version{Version: "none"} for k := range r { - if k.Path == m.Path && u.Version < k.Version && !strings.HasSuffix(k.Version, ".hidden") { + if k.Path == m.Path && r.Max(u.Version, k.Version) == k.Version && !strings.HasSuffix(k.Version, ".hidden") { u = k } } From 67bf1c9979180da6dba7dd523df7d7917fe04048 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 30 Oct 2020 21:00:41 -0400 Subject: [PATCH 363/403] cmd/go/internal/modload: fix (*mvsReqs).Max when the second argument is the empty string As far as I can tell, this bug had gone unnoticed because everything that uses Max so far happened to only ever present the empty string as the first argument. For #37438 Change-Id: Ie8c42313157d2c2c17e4058c53b5bb026b95a1c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/266860 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Michael Matloob --- src/cmd/go/internal/modload/mvs.go | 2 +- src/cmd/go/internal/modload/mvs_test.go | 33 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/cmd/go/internal/modload/mvs_test.go diff --git a/src/cmd/go/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go index 94373bc5f39..045cbead3b2 100644 --- a/src/cmd/go/internal/modload/mvs.go +++ b/src/cmd/go/internal/modload/mvs.go @@ -58,7 +58,7 @@ func (r *mvsReqs) Required(mod module.Version) ([]module.Version, error) { // be chosen over other versions of the same module in the module dependency // graph. func (*mvsReqs) Max(v1, v2 string) string { - if v1 != "" && semver.Compare(v1, v2) == -1 { + if v1 != "" && (v2 == "" || semver.Compare(v1, v2) == -1) { return v2 } return v1 diff --git a/src/cmd/go/internal/modload/mvs_test.go b/src/cmd/go/internal/modload/mvs_test.go new file mode 100644 index 00000000000..0cb376ec3c0 --- /dev/null +++ b/src/cmd/go/internal/modload/mvs_test.go @@ -0,0 +1,33 @@ +// Copyright 2020 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 modload_test + +import ( + "testing" + + "cmd/go/internal/modload" +) + +func TestReqsMax(t *testing.T) { + type testCase struct { + a, b, want string + } + reqs := modload.Reqs() + for _, tc := range []testCase{ + {a: "v0.1.0", b: "v0.2.0", want: "v0.2.0"}, + {a: "v0.2.0", b: "v0.1.0", want: "v0.2.0"}, + {a: "", b: "v0.1.0", want: ""}, // "" is Target.Version + {a: "v0.1.0", b: "", want: ""}, + {a: "none", b: "v0.1.0", want: "v0.1.0"}, + {a: "v0.1.0", b: "none", want: "v0.1.0"}, + {a: "none", b: "", want: ""}, + {a: "", b: "none", want: ""}, + } { + max := reqs.Max(tc.a, tc.b) + if max != tc.want { + t.Errorf("Reqs().Max(%q, %q) = %q; want %q", tc.a, tc.b, max, tc.want) + } + } +} From 06538fa723fc358462c5d7ae385b5b64ac76827b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 18 Sep 2020 12:10:58 -0400 Subject: [PATCH 364/403] cmd/go/internal/modget: resolve paths at the requested versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, we resolved each argument to 'go get' to a package path or module path based on what was in the build list at existing versions, even if the argument specified a different version explicitly. That resulted in bugs like #37438, in which we variously resolved the wrong version or guessed the wrong argument type for what is unambiguously a package argument at the requested version. We were also using a two-step upgrade/downgrade algorithm, which could not only upgrade more that is strictly necessary, but could also unintentionally upgrade *above* the requested versions during the downgrade step. This change instead uses an iterative approach, with an explicit disambiguation step for the (rare) cases where an argument could match the same package path in multiple modules. We use a hook in the package loader to halt package loading as soon as an incorrect version is found — preventing over-resolving — and verify that the result after applying downgrades successfully obtained the requested versions of all modules. Making 'go get' be correct and usable is especially important now that we are defaulting to read-only mode (#40728), for which we are recommending 'go get' more heavily. While I'm in here refactoring, I'm also reworking the API boundary between the modget and modload packages. Previously, the modget package edited the build list directly, and the modload package accepted the edited build list without validation. For lazy loading (#36460), the modload package will need to maintain additional metadata about the requirement graph, so it needs tighter control over the changes to the build list. As of this change, modget no longer invokes MVS directly, but instead goes through the modload package. The resulting API gives clearer reasons in case of updates, which we can use to emit more useful errors. Fixes #37438 Updates #36460 Updates #40728 Change-Id: I596f0020f3795870dec258147e6fc26a3292c93a Reviewed-on: https://go-review.googlesource.com/c/go/+/263267 Trust: Bryan C. Mills Trust: Jay Conrod Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Russ Cox --- doc/go1.16.html | 10 + src/cmd/go/alldocs.go | 6 +- src/cmd/go/internal/modget/get.go | 1914 +++++++++++------ src/cmd/go/internal/modget/mvs.go | 202 -- src/cmd/go/internal/modget/query.go | 353 +++ src/cmd/go/internal/modload/buildlist.go | 157 +- src/cmd/go/internal/modload/import.go | 4 +- src/cmd/go/internal/modload/load.go | 17 +- src/cmd/go/internal/modload/mvs.go | 8 + src/cmd/go/internal/modload/query.go | 54 +- src/cmd/go/internal/modload/search.go | 45 +- src/cmd/go/testdata/script/get_update_all.txt | 2 + src/cmd/go/testdata/script/mod_bad_domain.txt | 2 +- src/cmd/go/testdata/script/mod_dot.txt | 2 +- src/cmd/go/testdata/script/mod_download.txt | 6 +- .../testdata/script/mod_get_ambiguous_arg.txt | 51 +- .../script/mod_get_ambiguous_import.txt | 2 +- .../testdata/script/mod_get_ambiguous_pkg.txt | 46 +- .../go/testdata/script/mod_get_downgrade.txt | 3 +- .../script/mod_get_downgrade_missing.txt | 6 +- src/cmd/go/testdata/script/mod_get_extra.txt | 69 + .../go/testdata/script/mod_get_issue37438.txt | 37 + src/cmd/go/testdata/script/mod_get_main.txt | 26 +- src/cmd/go/testdata/script/mod_get_moved.txt | 4 +- .../go/testdata/script/mod_get_newcycle.txt | 3 +- src/cmd/go/testdata/script/mod_get_patch.txt | 130 ++ .../go/testdata/script/mod_get_patchbound.txt | 84 + .../go/testdata/script/mod_get_patchcycle.txt | 64 + .../go/testdata/script/mod_get_patchmod.txt | 60 +- .../go/testdata/script/mod_get_patterns.txt | 12 +- .../go/testdata/script/mod_get_replaced.txt | 2 +- src/cmd/go/testdata/script/mod_get_split.txt | 157 ++ src/cmd/go/testdata/script/mod_get_wild.txt | 95 + .../testdata/script/mod_invalid_version.txt | 2 +- .../go/testdata/script/mod_load_badchain.txt | 5 +- src/cmd/go/testdata/script/mod_outside.txt | 4 +- .../go/testdata/script/mod_query_empty.txt | 4 +- .../go/testdata/script/mod_query_exclude.txt | 2 +- .../script/mod_retract_pseudo_base.txt | 2 +- src/cmd/go/testdata/script/mod_sumdb.txt | 2 +- .../testdata/script/mod_sumdb_file_path.txt | 2 +- .../go/testdata/script/mod_upgrade_patch.txt | 21 +- 42 files changed, 2668 insertions(+), 1009 deletions(-) delete mode 100644 src/cmd/go/internal/modget/mvs.go create mode 100644 src/cmd/go/internal/modget/query.go create mode 100644 src/cmd/go/testdata/script/mod_get_extra.txt create mode 100644 src/cmd/go/testdata/script/mod_get_issue37438.txt create mode 100644 src/cmd/go/testdata/script/mod_get_patch.txt create mode 100644 src/cmd/go/testdata/script/mod_get_patchbound.txt create mode 100644 src/cmd/go/testdata/script/mod_get_patchcycle.txt create mode 100644 src/cmd/go/testdata/script/mod_get_split.txt create mode 100644 src/cmd/go/testdata/script/mod_get_wild.txt diff --git a/doc/go1.16.html b/doc/go1.16.html index 5ae85e6c293..99e8e3c980d 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -110,6 +110,16 @@ Do not send CLs removing the interior tags from such phrases. See go help environment for details.

+

go get

+ +

+ go get example.com/mod@patch now + requires that some version of example.com/mod already be + required by the main module. + (However, go get -u=patch continues + to patch even newly-added dependencies.) +

+

The all pattern

diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 23d44ddc708..ada85b13241 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -617,15 +617,15 @@ // dependency should be removed entirely, downgrading or removing modules // depending on it as needed. // -// The version suffix @latest explicitly requests the latest minor release of the +// The version suffix @latest explicitly requests the latest minor release ofthe // module named by the given path. The suffix @upgrade is like @latest but // will not downgrade a module if it is already required at a revision or // pre-release version newer than the latest released version. The suffix // @patch requests the latest patch release: the latest released version // with the same major and minor version numbers as the currently required // version. Like @upgrade, @patch will not downgrade a module already required -// at a newer version. If the path is not already required, @upgrade and @patch -// are equivalent to @latest. +// at a newer version. If the path is not already required, @upgrade is +// equivalent to @latest, and @patch is disallowed. // // Although get defaults to using the latest version of the module containing // a named package, it does not use the latest version of that module's diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 6d83af710fe..bb59191c734 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -5,12 +5,32 @@ // Package modget implements the module-aware ``go get'' command. package modget +// The arguments to 'go get' are patterns with optional version queries, with +// the version queries defaulting to "upgrade". +// +// The patterns are normally interpreted as package patterns. However, if a +// pattern cannot match a package, it is instead interpreted as a *module* +// pattern. For version queries such as "upgrade" and "patch" that depend on the +// selected version of a module (or of the module containing a package), +// whether a pattern denotes a package or module may change as updates are +// applied (see the example in mod_get_patchmod.txt). +// +// There are a few other ambiguous cases to resolve, too. A package can exist in +// two different modules at the same version: for example, the package +// example.com/foo might be found in module example.com and also in module +// example.com/foo, and those modules may have independent v0.1.0 tags — so the +// input 'example.com/foo@v0.1.0' could syntactically refer to the variant of +// the package loaded from either module! (See mod_get_ambiguous_pkg.txt.) +// If the argument is ambiguous, the user can often disambiguate by specifying +// explicit versions for *all* of the potential module paths involved. + import ( "context" "errors" "fmt" "os" "path/filepath" + "reflect" "runtime" "sort" "strings" @@ -21,12 +41,11 @@ import ( "cmd/go/internal/imports" "cmd/go/internal/load" "cmd/go/internal/modload" - "cmd/go/internal/mvs" + "cmd/go/internal/par" "cmd/go/internal/search" "cmd/go/internal/work" "golang.org/x/mod/module" - "golang.org/x/mod/semver" ) var CmdGet = &base.Command{ @@ -70,15 +89,15 @@ downgrades the dependency. The version suffix @none indicates that the dependency should be removed entirely, downgrading or removing modules depending on it as needed. -The version suffix @latest explicitly requests the latest minor release of the +The version suffix @latest explicitly requests the latest minor release ofthe module named by the given path. The suffix @upgrade is like @latest but will not downgrade a module if it is already required at a revision or pre-release version newer than the latest released version. The suffix @patch requests the latest patch release: the latest released version with the same major and minor version numbers as the currently required version. Like @upgrade, @patch will not downgrade a module already required -at a newer version. If the path is not already required, @upgrade and @patch -are equivalent to @latest. +at a newer version. If the path is not already required, @upgrade is +equivalent to @latest, and @patch is disallowed. Although get defaults to using the latest version of the module containing a named package, it does not use the latest version of that module's @@ -188,18 +207,24 @@ var ( ) // upgradeFlag is a custom flag.Value for -u. -type upgradeFlag string +type upgradeFlag struct { + rawVersion string + version string +} func (*upgradeFlag) IsBoolFlag() bool { return true } // allow -u func (v *upgradeFlag) Set(s string) error { if s == "false" { - s = "" + v.version = "" + v.rawVersion = "" + } else if s == "true" { + v.version = "upgrade" + v.rawVersion = "" + } else { + v.version = s + v.rawVersion = s } - if s == "true" { - s = "upgrade" - } - *v = upgradeFlag(s) return nil } @@ -212,64 +237,12 @@ func init() { CmdGet.Flag.Var(&getU, "u", "") } -// A getArg holds a parsed positional argument for go get (path@vers). -type getArg struct { - // raw is the original argument, to be printed in error messages. - raw string - - // path is the part of the argument before "@" (or the whole argument - // if there is no "@"). path specifies the modules or packages to get. - path string - - // vers is the part of the argument after "@" or an implied - // "upgrade" or "patch" if there is no "@". vers specifies the - // module version to get. - vers string -} - -func (arg getArg) String() string { return arg.raw } - -// querySpec describes a query for a specific module. path may be a -// module path, package path, or package pattern. vers is a version -// query string from a command line argument. -type querySpec struct { - // path is a module path, package path, or package pattern that - // specifies which module to query. - path string - - // vers specifies what version of the module to get. - vers string - - // forceModulePath is true if path should be interpreted as a module path. - // If forceModulePath is true, prevM must be set. - forceModulePath bool - - // prevM is the previous version of the module. prevM is needed - // to determine the minor version number if vers is "patch". It's also - // used to avoid downgrades from prerelease versions newer than - // "latest" and "patch". If prevM is set, forceModulePath must be true. - prevM module.Version -} - -// query holds the state for a query made for a specific module. -// After a query is performed, we know the actual module path and -// version and whether any packages were matched by the query path. -type query struct { - querySpec - - // arg is the command line argument that matched the specified module. - arg string - - // m is the module path and version found by the query. - m module.Version -} - func runGet(ctx context.Context, cmd *base.Command, args []string) { - switch getU { + switch getU.version { case "", "upgrade", "patch": // ok default: - base.Fatalf("go get: unknown upgrade flag -u=%s", getU) + base.Fatalf("go get: unknown upgrade flag -u=%s", getU.rawVersion) } if *getF { fmt.Fprintf(os.Stderr, "go get: -f flag is a no-op when using modules\n") @@ -294,311 +267,105 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // 'go get' is expected to do this, unlike other commands. modload.AllowMissingModuleImports() - getArgs := parseArgs(args) + modload.LoadModFile(ctx) // Initializes modload.Target. - buildList := modload.LoadAllModules(ctx) - buildList = buildList[:len(buildList):len(buildList)] // copy on append - selectedVersion := make(map[string]string) - for _, m := range buildList { - selectedVersion[m.Path] = m.Version - } - queries := classifyArgs(ctx, selectedVersion, getArgs) + queries := parseArgs(ctx, args) - // Query modules referenced by command line arguments at requested versions. - // We need to do this before loading packages since patterns that refer to - // packages in unknown modules can't be expanded. This also avoids looking - // up new modules while loading packages, only to downgrade later. - queryCache := make(map[querySpec]*query) - byPath := runQueries(ctx, queryCache, queries, nil) + r := newResolver(ctx, queries) + r.performLocalQueries(ctx) + r.performPathQueries(ctx) - // Add missing modules to the build list. - // We call SetBuildList here and elsewhere, since newUpgrader, - // LoadPackages, and other functions read the global build list. - for _, q := range queries { - if _, ok := selectedVersion[q.m.Path]; !ok && q.m.Version != "none" { - buildList = append(buildList, q.m) - } - } - selectedVersion = nil // out of date now; rebuilt later when needed - modload.SetBuildList(buildList) + for { + r.performWildcardQueries(ctx) + r.performPatternAllQueries(ctx) - // Upgrade modules specifically named on the command line. This is our only - // chance to upgrade modules without root packages (modOnly below). - // This also skips loading packages at an old version, only to upgrade - // and reload at a new version. - upgrade := make(map[string]*query) - for path, q := range byPath { - if q.path == q.m.Path && q.m.Version != "none" { - upgrade[path] = q - } - } - buildList, err := mvs.UpgradeAll(modload.Target, newUpgrader(upgrade, nil)) - if err != nil { - base.Fatalf("go get: %v", err) - } - modload.SetBuildList(buildList) - base.ExitIfErrors() - prevBuildList := buildList - - // Build a set of module paths that we don't plan to load packages from. - // This includes explicitly requested modules that don't have a root package - // and modules with a target version of "none". - var wg sync.WaitGroup - var modOnlyMu sync.Mutex - modOnly := make(map[string]*query) - for _, q := range queries { - if q.m.Version == "none" { - modOnlyMu.Lock() - modOnly[q.m.Path] = q - modOnlyMu.Unlock() + if changed := r.resolveCandidates(ctx, queries, nil); changed { + // 'go get' arguments can be (and often are) package patterns rather than + // (just) modules. A package can be provided by any module with a prefix + // of its import path, and a wildcard can even match packages in modules + // with totally different paths. Because of these effects, and because any + // change to the selected version of a module can bring in entirely new + // module paths as dependencies, we need to reissue queries whenever we + // change the build list. + // + // The result of any version query for a given module — even "upgrade" or + // "patch" — is always relative to the build list at the start of + // the 'go get' command, not an intermediate state, and is therefore + // dederministic and therefore cachable, and the constraints on the + // selected version of each module can only narrow as we iterate. + // + // "all" is functionally very similar to a wildcard pattern. The set of + // packages imported by the main module does not change, and the query + // result for the module containing each such package also does not change + // (it is always relative to the initial build list, before applying + // queries). So the only way that the result of an "all" query can change + // is if some matching package moves from one module in the build list + // to another, which should not happen very often. continue } - if q.path == q.m.Path { - wg.Add(1) - go func(q *query) { - if hasPkg, err := modload.ModuleHasRootPackage(ctx, q.m); err != nil { - base.Errorf("go get: %v", err) - } else if !hasPkg { - modOnlyMu.Lock() - modOnly[q.m.Path] = q - modOnlyMu.Unlock() - } - wg.Done() - }(q) - } - } - wg.Wait() - base.ExitIfErrors() - // Build a list of arguments that may refer to packages. + // When we load imports, we detect the following conditions: + // + // - missing transitive depencies that need to be resolved from outside the + // current build list (note that these may add new matches for existing + // pattern queries!) + // + // - transitive dependencies that didn't match any other query, + // but need to be upgraded due to the -u flag + // + // - ambiguous import errors. + // TODO(#27899): Try to resolve ambiguous import errors automatically. + upgrades := r.findAndUpgradeImports(ctx, queries) + if changed := r.resolveCandidates(ctx, nil, upgrades); changed { + continue + } + + r.findMissingWildcards(ctx) + if changed := r.resolveCandidates(ctx, r.wildcardQueries, nil); changed { + continue + } + + break + } + + r.checkWildcardVersions(ctx) + var pkgPatterns []string - var pkgGets []getArg - for _, arg := range getArgs { - if modOnly[arg.path] == nil && arg.vers != "none" { - pkgPatterns = append(pkgPatterns, arg.path) - pkgGets = append(pkgGets, arg) + for _, q := range queries { + if q.matchesPackages { + pkgPatterns = append(pkgPatterns, q.pattern) } } - - // Load packages and upgrade the modules that provide them. We do this until - // we reach a fixed point, since modules providing packages may change as we - // change versions. This must terminate because the module graph is finite, - // and the load and upgrade operations may only add and upgrade modules - // in the build list. - var matches []*search.Match - for { - var seenPkgs map[string]bool - seenQuery := make(map[querySpec]bool) - var queries []*query - addQuery := func(q *query) { - if !seenQuery[q.querySpec] { - seenQuery[q.querySpec] = true - queries = append(queries, q) - } + if len(pkgPatterns) > 0 { + // We skipped over missing-package errors earlier: we want to resolve + // pathSets ourselves, but at that point we don't have enough context + // to log the package-import chains leading to the error. Reload the package + // import graph one last time to report any remaining unresolved + // dependencies. + pkgOpts := modload.PackageOpts{ + LoadTests: *getT, + ResolveMissingImports: false, + AllowErrors: false, } - - if len(pkgPatterns) > 0 { - // Don't load packages if pkgPatterns is empty. Both - // modload.LoadPackages and ModulePackages convert an empty list - // of patterns to []string{"."}, which is not what we want. - loadOpts := modload.PackageOpts{ - Tags: imports.AnyTags(), - ResolveMissingImports: true, // dubious; see https://golang.org/issue/32567 - LoadTests: *getT, - SilenceErrors: true, // Errors may be fixed by subsequent upgrades or downgrades. - SilenceUnmatchedWarnings: true, // We will warn after iterating below. - } - matches, _ = modload.LoadPackages(ctx, loadOpts, pkgPatterns...) - seenPkgs = make(map[string]bool) - for i, match := range matches { - arg := pkgGets[i] - - if len(match.Pkgs) == 0 { - // If the pattern did not match any packages, look up a new module. - // If the pattern doesn't match anything on the last iteration, - // we'll print a warning after the outer loop. - if !match.IsLocal() && !match.IsLiteral() && arg.path != "all" { - addQuery(&query{querySpec: querySpec{path: arg.path, vers: arg.vers}, arg: arg.raw}) - } else { - for _, err := range match.Errs { - base.Errorf("go get: %v", err) - } - } - continue - } - - allStd := true - for _, pkg := range match.Pkgs { - if !seenPkgs[pkg] { - seenPkgs[pkg] = true - if _, _, err := modload.Lookup("", false, pkg); err != nil { - allStd = false - base.Errorf("go get %s: %v", arg.raw, err) - continue - } - } - m := modload.PackageModule(pkg) - if m.Path == "" { - // pkg is in the standard library. - continue - } - allStd = false - if m.Path == modload.Target.Path { - // pkg is in the main module. - continue - } - addQuery(&query{querySpec: querySpec{path: m.Path, vers: arg.vers, forceModulePath: true, prevM: m}, arg: arg.raw}) - } - if allStd && arg.path != arg.raw { - base.Errorf("go get %s: cannot use pattern %q with explicit version", arg.raw, arg.raw) - } - } - } - base.ExitIfErrors() - - // Query target versions for modules providing packages matched by - // command line arguments. - byPath = runQueries(ctx, queryCache, queries, modOnly) - - // Handle upgrades. This is needed for arguments that didn't match - // modules or matched different modules from a previous iteration. It - // also upgrades modules providing package dependencies if -u is set. - buildList, err := mvs.UpgradeAll(modload.Target, newUpgrader(byPath, seenPkgs)) - if err != nil { - base.Fatalf("go get: %v", err) - } - modload.SetBuildList(buildList) - base.ExitIfErrors() - - // Stop if no changes have been made to the build list. - buildList = modload.LoadedModules() - eq := len(buildList) == len(prevBuildList) - for i := 0; eq && i < len(buildList); i++ { - eq = buildList[i] == prevBuildList[i] - } - if eq { - break - } - prevBuildList = buildList - } - - // Handle downgrades. - var down []module.Version - for _, m := range modload.LoadedModules() { - q := byPath[m.Path] - if q != nil && semver.Compare(m.Version, q.m.Version) > 0 { - down = append(down, module.Version{Path: m.Path, Version: q.m.Version}) - } - } - if len(down) > 0 { - buildList, err := mvs.Downgrade(modload.Target, modload.Reqs(), down...) - if err != nil { - base.Fatalf("go: %v", err) - } - - // TODO(bcmills) What should happen here under lazy loading? - // Downgrading may intentionally violate the lazy-loading invariants. - - modload.SetBuildList(buildList) - modload.ReloadBuildList() // note: does not update go.mod + modload.LoadPackages(ctx, pkgOpts, pkgPatterns...) base.ExitIfErrors() } - // Scan for any upgrades lost by the downgrades. - var lostUpgrades []*query - if len(down) > 0 { - selectedVersion = make(map[string]string) - for _, m := range modload.LoadedModules() { - selectedVersion[m.Path] = m.Version - } - for _, q := range byPath { - if v, ok := selectedVersion[q.m.Path]; q.m.Version != "none" && (!ok || semver.Compare(v, q.m.Version) != 0) { - lostUpgrades = append(lostUpgrades, q) - } - } - sort.Slice(lostUpgrades, func(i, j int) bool { - return lostUpgrades[i].m.Path < lostUpgrades[j].m.Path - }) - } - if len(lostUpgrades) > 0 { - desc := func(m module.Version) string { - s := m.Path + "@" + m.Version - t := byPath[m.Path] - if t != nil && t.arg != s { - s += " from " + t.arg - } - return s - } - downByPath := make(map[string]module.Version) - for _, d := range down { - downByPath[d.Path] = d - } - - var buf strings.Builder - fmt.Fprintf(&buf, "go get: inconsistent versions:") - reqs := modload.Reqs() - for _, q := range lostUpgrades { - // We lost q because its build list requires a newer version of something in down. - // Figure out exactly what. - // Repeatedly constructing the build list is inefficient - // if there are MANY command-line arguments, - // but at least all the necessary requirement lists are cached at this point. - list, err := buildListForLostUpgrade(q.m, reqs) - if err != nil { - base.Fatalf("go: %v", err) - } - - fmt.Fprintf(&buf, "\n\t%s", desc(q.m)) - sep := " requires" - for _, m := range list { - if down, ok := downByPath[m.Path]; ok && semver.Compare(down.Version, m.Version) < 0 { - fmt.Fprintf(&buf, "%s %s@%s (not %s)", sep, m.Path, m.Version, desc(down)) - sep = "," - } - } - if sep != "," { - // We have no idea why this happened. - // At least report the problem. - if v := selectedVersion[q.m.Path]; v == "" { - fmt.Fprintf(&buf, " removed unexpectedly") - } else { - fmt.Fprintf(&buf, " ended up at %s unexpectedly", v) - } - fmt.Fprintf(&buf, " (please report at golang.org/issue/new)") - } - } - base.Fatalf("%v", buf.String()) - } - - if len(pkgPatterns) > 0 || len(args) == 0 { - // Before we write the updated go.mod file, reload the requested packages to - // check for errors. - loadOpts := modload.PackageOpts{ - Tags: imports.AnyTags(), - LoadTests: *getT, - - // Only print warnings after the last iteration, and only if we aren't going - // to build (to avoid doubled warnings). - // - // Only local patterns in the main module, such as './...', can be unmatched. - // (See the mod_get_nopkgs test for more detail.) - SilenceUnmatchedWarnings: !*getD, - } - modload.LoadPackages(ctx, loadOpts, pkgPatterns...) - } - - // If -d was specified, we're done after the module work. - // We've already downloaded modules by loading packages above. + // We've already downloaded modules (and identified direct and indirect + // dependencies) by loading packages in findAndUpgradeImports. + // So if -d is set, we're done after the module work. + // // Otherwise, we need to build and install the packages matched by - // command line arguments. This may be a different set of packages, - // since we only build packages for the target platform. + // command line arguments. // Note that 'go get -u' without arguments is equivalent to // 'go get -u .', so we'll typically build the package in the current // directory. - if !*getD && len(pkgPatterns) > 0 { - work.BuildInit() - pkgs := load.PackagesForBuild(ctx, pkgPatterns) - work.InstallPackages(ctx, pkgPatterns, pkgs) + if !*getD { + if len(pkgPatterns) > 0 { + work.BuildInit() + pkgs := load.PackagesForBuild(ctx, pkgPatterns) + work.InstallPackages(ctx, pkgPatterns, pkgs) + } } // Everything succeeded. Update go.mod. @@ -609,9 +376,10 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // Report warnings if any retracted versions are in the build list. // This must be done after writing go.mod to avoid spurious '// indirect' // comments. These functions read and write global state. - // TODO(golang.org/issue/40775): ListModules resets modload.loader, which - // contains information about direct dependencies that WriteGoMod uses. - // Refactor to avoid these kinds of global side effects. + // + // TODO(golang.org/issue/40775): ListModules (called from reportRetractions) + // resets modload.loader, which contains information about direct dependencies + // that WriteGoMod uses. Refactor to avoid these kinds of global side effects. reportRetractions(ctx) } @@ -619,318 +387,37 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // // The command-line arguments are of the form path@version or simply path, with // implicit @upgrade. path@none is "downgrade away". -func parseArgs(rawArgs []string) []getArg { +func parseArgs(ctx context.Context, rawArgs []string) []*query { defer base.ExitIfErrors() - var gets []getArg - for _, raw := range search.CleanPatterns(rawArgs) { - // Argument is path or path@vers. - path := raw - vers := "" - if i := strings.Index(raw, "@"); i >= 0 { - path, vers = raw[:i], raw[i+1:] - } - if strings.Contains(vers, "@") || raw != path && vers == "" { - base.Errorf("go get %s: invalid module version syntax", raw) + var queries []*query + for _, arg := range search.CleanPatterns(rawArgs) { + q, err := newQuery(arg) + if err != nil { + base.Errorf("go get: %v", err) continue } // Guard against 'go get x.go', a common mistake. // Note that package and module paths may end with '.go', so only print an error // if the argument has no version and either has no slash or refers to an existing file. - if strings.HasSuffix(raw, ".go") && vers == "" { - if !strings.Contains(raw, "/") { - base.Errorf("go get %s: arguments must be package or module paths", raw) + if strings.HasSuffix(q.raw, ".go") && q.rawVersion == "" { + if !strings.Contains(q.raw, "/") { + base.Errorf("go get %s: arguments must be package or module paths", q.raw) continue } - if fi, err := os.Stat(raw); err == nil && !fi.IsDir() { - base.Errorf("go get: %s exists as a file, but 'go get' requires package arguments", raw) + if fi, err := os.Stat(q.raw); err == nil && !fi.IsDir() { + base.Errorf("go get: %s exists as a file, but 'go get' requires package arguments", q.raw) continue } } - // If no version suffix is specified, assume @upgrade. - // If -u=patch was specified, assume @patch instead. - if vers == "" { - if getU != "" { - vers = string(getU) - } else { - vers = "upgrade" - } - } - - gets = append(gets, getArg{raw: raw, path: path, vers: vers}) - } - - return gets -} - -// classifyArgs determines which arguments refer to packages and which refer to -// modules, and creates queries to look up modules at target versions before -// loading packages. -// -// This is an imprecise process, but it helps reduce unnecessary -// queries and package loading. It's also necessary for handling -// patterns like golang.org/x/tools/..., which can't be expanded -// during package loading until they're in the build list. -func classifyArgs(ctx context.Context, selectedVersion map[string]string, args []getArg) []*query { - defer base.ExitIfErrors() - - queries := make([]*query, 0, len(args)) - - for _, arg := range args { - path := arg.path - switch { - case filepath.IsAbs(path) || search.IsRelativePath(path): - // Absolute paths like C:\foo and relative paths like ../foo... - // are restricted to matching packages in the main module. If the path - // is explicit and contains no wildcards (...), check that it is a - // package in the main module. If the path contains wildcards but - // matches no packages, we'll warn after package loading. - if !strings.Contains(path, "...") { - m := search.NewMatch(path) - if pkgPath := modload.DirImportPath(path); pkgPath != "." { - m = modload.TargetPackages(ctx, pkgPath) - } - if len(m.Pkgs) == 0 { - for _, err := range m.Errs { - base.Errorf("go get %s: %v", arg, err) - } - - abs, err := filepath.Abs(path) - if err != nil { - abs = path - } - base.Errorf("go get %s: path %s is not a package in module rooted at %s", arg, abs, modload.ModRoot()) - continue - } - } - - if arg.path != arg.raw { - base.Errorf("go get %s: can't request explicit version of path in main module", arg) - continue - } - - case strings.Contains(path, "..."): - // Wait until we load packages to look up modules. - // We don't know yet whether any modules in the build list provide - // packages matching the pattern. For example, suppose - // golang.org/x/tools and golang.org/x/tools/playground are separate - // modules, and only golang.org/x/tools is in the build list. If the - // user runs 'go get golang.org/x/tools/playground/...', we should - // add a requirement for golang.org/x/tools/playground. We should not - // upgrade golang.org/x/tools. - - case path == "all": - // If there is no main module, "all" is not meaningful. - if !modload.HasModRoot() { - base.Errorf(`go get %s: cannot match "all": working directory is not part of a module`, arg) - } - // Don't query modules until we load packages. We'll automatically - // look up any missing modules. - - case search.IsMetaPackage(path): - base.Errorf("go get %s: explicit requirement on standard-library module %s not allowed", path, path) - continue - - default: - // The argument is a package or module path. - if modload.HasModRoot() { - if m := modload.TargetPackages(ctx, path); len(m.Pkgs) != 0 { - // The path is in the main module. Nothing to query. - if arg.vers != "upgrade" && arg.vers != "patch" { - base.Errorf("go get %s: can't request explicit version of path in main module", arg) - } - continue - } - } - - first := path - if i := strings.IndexByte(first, '/'); i >= 0 { - first = path - } - if !strings.Contains(first, ".") { - // The path doesn't have a dot in the first component and cannot be - // queried as a module. It may be a package in the standard library, - // which is fine, so don't report an error unless we encounter - // a problem loading packages. - continue - } - - // If we're querying "upgrade" or "patch", we need to know the current - // version of the module. For "upgrade", we want to avoid accidentally - // downgrading from a newer prerelease. For "patch", we need to query - // the correct minor version. - // Here, we check if "path" is the name of a module in the build list - // (other than the main module) and set prevM if so. If "path" isn't - // a module in the build list, the current version doesn't matter - // since it's either an unknown module or a package within a module - // that we'll discover later. - q := &query{querySpec: querySpec{path: arg.path, vers: arg.vers}, arg: arg.raw} - if v, ok := selectedVersion[path]; ok { - if path == modload.Target.Path { - // TODO(bcmills): This is held over from a previous version of the get - // implementation. Why was it a special case? - } else { - q.prevM = module.Version{Path: path, Version: v} - q.forceModulePath = true - } - } - queries = append(queries, q) - } + queries = append(queries, q) } return queries } -// runQueries looks up modules at target versions in parallel. Results will be -// cached. If the same module is referenced by multiple queries at different -// versions (including earlier queries in the modOnly map), an error will be -// reported. A map from module paths to queries is returned, which includes -// queries and modOnly. -func runQueries(ctx context.Context, cache map[querySpec]*query, queries []*query, modOnly map[string]*query) map[string]*query { - - runQuery := func(q *query) { - if q.vers == "none" { - // Wait for downgrade step. - q.m = module.Version{Path: q.path, Version: "none"} - return - } - m, err := getQuery(ctx, q.path, q.vers, q.prevM, q.forceModulePath) - if err != nil { - base.Errorf("go get %s: %v", q.arg, err) - } - q.m = m - } - - type token struct{} - sem := make(chan token, runtime.GOMAXPROCS(0)) - for _, q := range queries { - if cached := cache[q.querySpec]; cached != nil { - *q = *cached - } else { - sem <- token{} - go func(q *query) { - runQuery(q) - <-sem - }(q) - } - } - - // Fill semaphore channel to wait for goroutines to finish. - for n := cap(sem); n > 0; n-- { - sem <- token{} - } - - // Add to cache after concurrent section to avoid races... - for _, q := range queries { - cache[q.querySpec] = q - } - - base.ExitIfErrors() - - byPath := make(map[string]*query) - check := func(q *query) { - if prev, ok := byPath[q.m.Path]; prev != nil && prev.m != q.m { - base.Errorf("go get: conflicting versions for module %s: %s and %s", q.m.Path, prev.m.Version, q.m.Version) - byPath[q.m.Path] = nil // sentinel to stop errors - return - } else if !ok { - byPath[q.m.Path] = q - } - } - for _, q := range queries { - check(q) - } - for _, q := range modOnly { - check(q) - } - base.ExitIfErrors() - - return byPath -} - -// getQuery evaluates the given (package or module) path and version -// to determine the underlying module version being requested. -// If forceModulePath is set, getQuery must interpret path -// as a module path. -func getQuery(ctx context.Context, path, vers string, prevM module.Version, forceModulePath bool) (module.Version, error) { - if (prevM.Version != "") != forceModulePath { - // We resolve package patterns by calling QueryPattern, which does not - // accept a previous version and therefore cannot take it into account for - // the "latest" or "patch" queries. - // If we are resolving a package path or pattern, the caller has already - // resolved any existing packages to their containing module(s), and - // will set both prevM.Version and forceModulePath for those modules. - // The only remaining package patterns are those that are not already - // provided by the build list, which are indicated by - // an empty prevM.Version. - base.Fatalf("go get: internal error: prevM may be set if and only if forceModulePath is set") - } - - // If vers is a query like "latest", we should ignore retracted and excluded - // versions. If vers refers to a specific version or commit like "v1.0.0" - // or "master", we should only ignore excluded versions. - allowed := modload.CheckAllowed - if modload.IsRevisionQuery(vers) { - allowed = modload.CheckExclusions - } else if vers == "upgrade" || vers == "patch" { - allowed = checkAllowedOrCurrent(prevM.Version) - } - - // If the query must be a module path, try only that module path. - if forceModulePath { - if path == modload.Target.Path { - if vers != "latest" { - return module.Version{}, fmt.Errorf("can't get a specific version of the main module") - } - } - - info, err := modload.Query(ctx, path, vers, prevM.Version, allowed) - if err == nil { - if info.Version != vers && info.Version != prevM.Version { - logOncef("go: %s %s => %s", path, vers, info.Version) - } - return module.Version{Path: path, Version: info.Version}, nil - } - - // If the query was "upgrade" or "patch" and the current version has been - // replaced, check to see whether the error was for that same version: - // if so, the version was probably replaced because it is invalid, - // and we should keep that replacement without complaining. - if vers == "upgrade" || vers == "patch" { - var vErr *module.InvalidVersionError - if errors.As(err, &vErr) && vErr.Version == prevM.Version && modload.Replacement(prevM).Path != "" { - return prevM, nil - } - } - - return module.Version{}, err - } - - // If the query may be either a package or a module, try it as a package path. - // If it turns out to only exist as a module, we can detect the resulting - // PackageNotInModuleError and avoid a second round-trip through (potentially) - // all of the configured proxies. - results, modOnly, err := modload.QueryPattern(ctx, path, vers, modload.Selected, allowed) - if err != nil { - return module.Version{}, err - } - if len(results) == 0 { - // The path doesn't contain a wildcard, but was actually a - // module path instead. Return that. - return modOnly.Mod, nil - } - - m := results[0].Mod - if m.Path != path { - logOncef("go: found %s in %s %s", path, m.Path, m.Version) - } else if m.Version != vers { - logOncef("go: %s %s => %s", path, vers, m.Version) - } - return m, nil -} - // reportRetractions prints warnings if any modules in the build list are // retracted. func reportRetractions(ctx context.Context) { @@ -960,34 +447,1137 @@ func reportRetractions(ctx context.Context) { retractPath = "" } rationale := modload.ShortRetractionRationale(mod.Retracted[0]) - logOncef("go: warning: %s@%s is retracted: %s", mod.Path, mod.Version, rationale) + fmt.Fprintf(os.Stderr, "go: warning: %s@%s is retracted: %s\n", mod.Path, mod.Version, rationale) } } if modload.HasModRoot() && retractPath != "" { - logOncef("go: run 'go get %s@latest' to switch to the latest unretracted version", retractPath) + fmt.Fprintf(os.Stderr, "go: run 'go get %s@latest' to switch to the latest unretracted version\n", retractPath) } } -var loggedLines sync.Map +type resolver struct { + localQueries []*query // queries for absolute or relative paths + pathQueries []*query // package path literal queries in original order + wildcardQueries []*query // path wildcard queries in original order + patternAllQueries []*query // queries with the pattern "all" -func logOncef(format string, args ...interface{}) { - msg := fmt.Sprintf(format, args...) - if _, dup := loggedLines.LoadOrStore(msg, true); !dup { - fmt.Fprintln(os.Stderr, msg) - } + // Indexed "none" queries. These are also included in the slices above; + // they are indexed here to speed up noneForPath. + nonesByPath map[string]*query // path-literal "@none" queries indexed by path + wildcardNones []*query // wildcard "@none" queries + + // resolvedVersion maps each module path to the version of that module that + // must be selected in the final build list, along with the first query + // that resolved the module to that version (the “reason”). + resolvedVersion map[string]versionReason + + buildList []module.Version + buildListResolvedVersions int // len(resolvedVersion) when buildList was computed + buildListVersion map[string]string // index of buildList (module path → version) + + initialVersion map[string]string // index of the initial build list at the start of 'go get' + + missing []pathSet // candidates for missing transitive dependencies + + work *par.Queue + + queryModuleCache par.Cache + queryPackagesCache par.Cache + queryPatternCache par.Cache + matchInModuleCache par.Cache } -// checkAllowedOrCurrent is like modload.CheckAllowed, but always allows the -// current version (even if it is retracted or otherwise excluded). -func checkAllowedOrCurrent(current string) modload.AllowedFunc { - if current == "" { - return modload.CheckAllowed +type versionReason struct { + version string + reason *query +} + +func newResolver(ctx context.Context, queries []*query) *resolver { + buildList := modload.LoadAllModules(ctx) + initialVersion := make(map[string]string, len(buildList)) + for _, m := range buildList { + initialVersion[m.Path] = m.Version } + r := &resolver{ + work: par.NewQueue(runtime.GOMAXPROCS(0)), + resolvedVersion: map[string]versionReason{}, + buildList: buildList, + buildListVersion: initialVersion, + initialVersion: initialVersion, + nonesByPath: map[string]*query{}, + } + + for _, q := range queries { + if q.pattern == "all" { + r.patternAllQueries = append(r.patternAllQueries, q) + } else if q.patternIsLocal { + r.localQueries = append(r.localQueries, q) + } else if q.isWildcard() { + r.wildcardQueries = append(r.wildcardQueries, q) + } else { + r.pathQueries = append(r.pathQueries, q) + } + + if q.version == "none" { + // Index "none" queries to make noneForPath more efficient. + if q.isWildcard() { + r.wildcardNones = append(r.wildcardNones, q) + } else { + // All "@none" queries for the same path are identical; we only + // need to index one copy. + r.nonesByPath[q.pattern] = q + } + } + } + + return r +} + +// initialSelected returns the version of the module with the given path that +// was selected at the start of this 'go get' invocation. +func (r *resolver) initialSelected(mPath string) (version string) { + v, ok := r.initialVersion[mPath] + if !ok { + return "none" + } + return v +} + +// selected returns the version of the module with the given path that is +// selected in the resolver's current build list. +func (r *resolver) selected(mPath string) (version string) { + v, ok := r.buildListVersion[mPath] + if !ok { + return "none" + } + return v +} + +// noneForPath returns a "none" query matching the given module path, +// or found == false if no such query exists. +func (r *resolver) noneForPath(mPath string) (nq *query, found bool) { + if nq = r.nonesByPath[mPath]; nq != nil { + return nq, true + } + for _, nq := range r.wildcardNones { + if nq.matchesPath(mPath) { + return nq, true + } + } + return nil, false +} + +// queryModule wraps modload.Query, substituting r.checkAllowedor to decide +// allowed versions. +func (r *resolver) queryModule(ctx context.Context, mPath, query string, selected func(string) string) (module.Version, error) { + current := r.initialSelected(mPath) + rev, err := modload.Query(ctx, mPath, query, current, r.checkAllowedOr(query, selected)) + if err != nil { + return module.Version{}, err + } + return module.Version{Path: mPath, Version: rev.Version}, nil +} + +// queryPackage wraps modload.QueryPackage, substituting r.checkAllowedOr to +// decide allowed versions. +func (r *resolver) queryPackages(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, err error) { + results, err := modload.QueryPackages(ctx, pattern, query, selected, r.checkAllowedOr(query, selected)) + if len(results) > 0 { + pkgMods = make([]module.Version, 0, len(results)) + for _, qr := range results { + pkgMods = append(pkgMods, qr.Mod) + } + } + return pkgMods, err +} + +// queryPattern wraps modload.QueryPattern, substituting r.checkAllowedOr to +// decide allowed versions. +func (r *resolver) queryPattern(ctx context.Context, pattern, query string, selected func(string) string) (pkgMods []module.Version, mod module.Version, err error) { + results, modOnly, err := modload.QueryPattern(ctx, pattern, query, selected, r.checkAllowedOr(query, selected)) + if len(results) > 0 { + pkgMods = make([]module.Version, 0, len(results)) + for _, qr := range results { + pkgMods = append(pkgMods, qr.Mod) + } + } + if modOnly != nil { + mod = modOnly.Mod + } + return pkgMods, mod, err +} + +// checkAllowedOr is like modload.CheckAllowed, but it always allows the requested +// and current versions (even if they are retracted or otherwise excluded). +func (r *resolver) checkAllowedOr(requested string, selected func(string) string) modload.AllowedFunc { return func(ctx context.Context, m module.Version) error { - if m.Version == current { + if m.Version == requested { + return modload.CheckExclusions(ctx, m) + } + if (requested == "upgrade" || requested == "patch") && m.Version == selected(m.Path) { return nil } return modload.CheckAllowed(ctx, m) } } + +// matchInModule is a caching wrapper around modload.MatchInModule. +func (r *resolver) matchInModule(ctx context.Context, pattern string, m module.Version) (packages []string, err error) { + type key struct { + pattern string + m module.Version + } + type entry struct { + packages []string + err error + } + + e := r.matchInModuleCache.Do(key{pattern, m}, func() interface{} { + match := modload.MatchInModule(ctx, pattern, m, imports.AnyTags()) + if len(match.Errs) > 0 { + return entry{match.Pkgs, match.Errs[0]} + } + return entry{match.Pkgs, nil} + }).(entry) + + return e.packages, e.err +} + +// queryNone adds a candidate set to q for each module matching q.pattern. +// Each candidate set has only one possible module version: the matched +// module at version "none". +// +// We interpret arguments to 'go get' as packages first, and fall back to +// modules second. However, no module exists at version "none", and therefore no +// package exists at that version either: we know that the argument cannot match +// any packages, and thus it must match modules instead. +func (r *resolver) queryNone(ctx context.Context, q *query) { + if search.IsMetaPackage(q.pattern) { + panic(fmt.Sprintf("internal error: queryNone called with pattern %q", q.pattern)) + } + + if !q.isWildcard() { + q.pathOnce(q.pattern, func() pathSet { + if modload.HasModRoot() && q.pattern == modload.Target.Path { + // The user has explicitly requested to downgrade their own module to + // version "none". This is not an entirely unreasonable request: it + // could plausibly mean “downgrade away everything that depends on any + // explicit version of the main module”, or “downgrade away the + // package with the same path as the main module, found in a module + // with a prefix of the main module's path”. + // + // However, neither of those behaviors would be consistent with the + // plain meaning of the query. To try to reduce confusion, reject the + // query explicitly. + return errSet(&modload.QueryMatchesMainModuleError{Pattern: q.pattern, Query: q.version}) + } + + return pathSet{mod: module.Version{Path: q.pattern, Version: "none"}} + }) + } + + for _, curM := range r.buildList { + if !q.matchesPath(curM.Path) { + continue + } + q.pathOnce(curM.Path, func() pathSet { + if modload.HasModRoot() && curM == modload.Target { + return errSet(&modload.QueryMatchesMainModuleError{Pattern: q.pattern, Query: q.version}) + } + return pathSet{mod: module.Version{Path: curM.Path, Version: "none"}} + }) + } +} + +func (r *resolver) performLocalQueries(ctx context.Context) { + for _, q := range r.localQueries { + q.pathOnce(q.pattern, func() pathSet { + absDetail := "" + if !filepath.IsAbs(q.pattern) { + if absPath, err := filepath.Abs(q.pattern); err == nil { + absDetail = fmt.Sprintf(" (%s)", absPath) + } + } + + // Absolute paths like C:\foo and relative paths like ../foo... are + // restricted to matching packages in the main module. + pkgPattern := modload.DirImportPath(q.pattern) + if pkgPattern == "." { + return errSet(fmt.Errorf("%s%s is not within module rooted at %s", q.pattern, absDetail, modload.ModRoot())) + } + + match := modload.MatchInModule(ctx, pkgPattern, modload.Target, imports.AnyTags()) + if len(match.Errs) > 0 { + return pathSet{err: match.Errs[0]} + } + + if len(match.Pkgs) == 0 { + if !q.isWildcard() { + return errSet(fmt.Errorf("%s%s is not a package in module rooted at %s", q.pattern, absDetail, modload.ModRoot())) + } + search.WarnUnmatched([]*search.Match{match}) + return pathSet{} + } + + return pathSet{pkgMods: []module.Version{modload.Target}} + }) + } +} + +// performWildcardQueries populates the candidates for each query whose pattern +// is a wildcard. +// +// The candidates for a given module path matching (or containing a package +// matching) a wildcard query depend only on the initial build list, but the set +// of modules may be expanded by other queries, so wildcard queries need to be +// re-evaluated whenever a potentially-matching module path is added to the +// build list. +func (r *resolver) performWildcardQueries(ctx context.Context) { + for _, q := range r.wildcardQueries { + q := q + r.work.Add(func() { + if q.version == "none" { + r.queryNone(ctx, q) + } else { + r.queryWildcard(ctx, q) + } + }) + } + <-r.work.Idle() +} + +// queryWildcard adds a candidate set to q for each module for which: +// - some version of the module is already in the build list, and +// - that module exists at some version matching q.version, and +// - either the module path itself matches q.pattern, or some package within +// the module at q.version matches q.pattern. +func (r *resolver) queryWildcard(ctx context.Context, q *query) { + // For wildcard patterns, modload.QueryPattern only identifies modules + // matching the prefix of the path before the wildcard. However, the build + // list may already contain other modules with matching packages, and we + // should consider those modules to satisfy the query too. + // We want to match any packages in existing dependencies, but we only want to + // resolve new dependencies if nothing else turns up. + for _, curM := range r.buildList { + if !q.canMatchInModule(curM.Path) { + continue + } + q.pathOnce(curM.Path, func() pathSet { + if _, hit := r.noneForPath(curM.Path); hit { + // This module is being removed, so it will no longer be in the build list + // (and thus will no longer match the pattern). + return pathSet{} + } + + if curM.Path == modload.Target.Path && !versionOkForMainModule(q.version) { + if q.matchesPath(curM.Path) { + return errSet(&modload.QueryMatchesMainModuleError{ + Pattern: q.pattern, + Query: q.version, + }) + } + + packages, err := r.matchInModule(ctx, q.pattern, curM) + if err != nil { + return errSet(err) + } + if len(packages) > 0 { + return errSet(&modload.QueryMatchesPackagesInMainModuleError{ + Pattern: q.pattern, + Query: q.version, + Packages: packages, + }) + } + + return r.tryWildcard(ctx, q, curM) + } + + m, err := r.queryModule(ctx, curM.Path, q.version, r.initialSelected) + if err != nil { + if !isNoSuchModuleVersion(err) { + // We can't tell whether a matching version exists. + return errSet(err) + } + // There is no version of curM.Path matching the query. + + // We haven't checked whether curM contains any matching packages at its + // currently-selected version, or whether curM.Path itself matches q. If + // either of those conditions holds, *and* no other query changes the + // selected version of curM, then we will fail in checkWildcardVersions. + // (This could be an error, but it's too soon to tell.) + // + // However, even then the transitive requirements of some other query + // may downgrade this module out of the build list entirely, in which + // case the pattern will no longer include it and it won't be an error. + // + // Either way, punt on the query rather than erroring out just yet. + return pathSet{} + } + + return r.tryWildcard(ctx, q, m) + }) + } + + // Even if no modules matched, we shouldn't query for a new module to provide + // the pattern yet: some other query may yet induce a new requirement that + // will match the wildcard. Instead, we'll check in findMissingWildcards. +} + +// tryWildcard returns a pathSet for module m matching query q. +// If m does not actually match q, tryWildcard returns an empty pathSet. +func (r *resolver) tryWildcard(ctx context.Context, q *query, m module.Version) pathSet { + mMatches := q.matchesPath(m.Path) + packages, err := r.matchInModule(ctx, q.pattern, m) + if err != nil { + return errSet(err) + } + if len(packages) > 0 { + return pathSet{pkgMods: []module.Version{m}} + } + if mMatches { + return pathSet{mod: m} + } + return pathSet{} +} + +// findMissingWildcards adds a candidate set for each query in r.wildcardQueries +// that has not yet resolved to any version containing packages. +func (r *resolver) findMissingWildcards(ctx context.Context) { + for _, q := range r.wildcardQueries { + if q.version == "none" || q.matchesPackages { + continue // q is not “missing” + } + r.work.Add(func() { + q.pathOnce(q.pattern, func() pathSet { + pkgMods, mod, err := r.queryPattern(ctx, q.pattern, q.version, r.initialSelected) + if err != nil { + if isNoSuchPackageVersion(err) && len(q.resolved) > 0 { + // q already resolved one or more modules but matches no packages. + // That's ok: this pattern is just a module pattern, and we don't + // need to add any more modules to satisfy it. + return pathSet{} + } + return errSet(err) + } + + return pathSet{pkgMods: pkgMods, mod: mod} + }) + }) + } + <-r.work.Idle() +} + +// checkWildcardVersions reports an error if any module in the build list has a +// path (or contains a package) matching a query with a wildcard pattern, but +// has a selected version that does *not* match the query. +func (r *resolver) checkWildcardVersions(ctx context.Context) { + defer base.ExitIfErrors() + + for _, q := range r.wildcardQueries { + for _, curM := range r.buildList { + if !q.canMatchInModule(curM.Path) { + continue + } + if !q.matchesPath(curM.Path) { + packages, err := r.matchInModule(ctx, q.pattern, curM) + if len(packages) == 0 { + if err != nil { + reportError(q, err) + } + continue // curM is not relevant to q. + } + } + + rev, err := r.queryModule(ctx, curM.Path, q.version, r.initialSelected) + if err != nil { + reportError(q, err) + continue + } + if rev.Version == curM.Version { + continue // curM already matches q. + } + + if !q.matchesPath(curM.Path) { + m := module.Version{Path: curM.Path, Version: rev.Version} + packages, err := r.matchInModule(ctx, q.pattern, m) + if err != nil { + reportError(q, err) + continue + } + if len(packages) == 0 { + // curM at its original version contains a path matching q.pattern, + // but at rev.Version it does not, so (somewhat paradoxically) if + // we changed the version of curM it would no longer match the query. + var version interface{} = m + if rev.Version != q.version { + version = fmt.Sprintf("%s@%s (%s)", m.Path, q.version, m.Version) + } + reportError(q, fmt.Errorf("%v matches packages in %v but not %v: specify a different version for module %s", q, curM, version, m.Path)) + continue + } + } + + // Since queryModule succeeded and either curM or one of the packages it + // contains matches q.pattern, we should have either selected the version + // of curM matching q, or reported a conflict error (and exited). + // If we're still here and the version doesn't match, + // something has gone very wrong. + reportError(q, fmt.Errorf("internal error: selected %v instead of %v", curM, rev.Version)) + } + } +} + +// performPathQueries populates the candidates for each query whose pattern is +// a path literal. +// +// The candidate packages and modules for path literals depend only on the +// initial build list, not the current build list, so we only need to query path +// literals once. +func (r *resolver) performPathQueries(ctx context.Context) { + for _, q := range r.pathQueries { + q := q + r.work.Add(func() { + if q.version == "none" { + r.queryNone(ctx, q) + } else { + r.queryPath(ctx, q) + } + }) + } + <-r.work.Idle() +} + +// queryPath adds a candidate set to q for the package with path q.pattern. +// The candidate set consists of all modules that could provide q.pattern +// and have a version matching q, plus (if it exists) the module whose path +// is itself q.pattern (at a matching version). +func (r *resolver) queryPath(ctx context.Context, q *query) { + q.pathOnce(q.pattern, func() pathSet { + if search.IsMetaPackage(q.pattern) || q.isWildcard() { + panic(fmt.Sprintf("internal error: queryPath called with pattern %q", q.pattern)) + } + if q.version == "none" { + panic(`internal error: queryPath called with version "none"`) + } + + if search.IsStandardImportPath(q.pattern) { + stdOnly := module.Version{} + packages, _ := r.matchInModule(ctx, q.pattern, stdOnly) + if len(packages) > 0 { + if q.rawVersion != "" { + return errSet(fmt.Errorf("can't request explicit version %q of standard library package %s", q.version, q.pattern)) + } + + q.matchesPackages = true + return pathSet{} // No module needed for standard library. + } + } + + pkgMods, mod, err := r.queryPattern(ctx, q.pattern, q.version, r.initialSelected) + if err != nil { + return errSet(err) + } + return pathSet{pkgMods: pkgMods, mod: mod} + }) +} + +// performPatternAllQueries populates the candidates for each query whose +// pattern is "all". +// +// The candidate modules for a given package in "all" depend only on the initial +// build list, but we cannot follow the dependencies of a given package until we +// know which candidate is selected — and that selection may depend on the +// results of other queries. We need to re-evaluate the "all" queries whenever +// the module for one or more packages in "all" are resolved. +func (r *resolver) performPatternAllQueries(ctx context.Context) { + if len(r.patternAllQueries) == 0 { + return + } + + findPackage := func(ctx context.Context, path string, m module.Version) (versionOk bool) { + versionOk = true + for _, q := range r.patternAllQueries { + q.pathOnce(path, func() pathSet { + pkgMods, err := r.queryPackages(ctx, path, q.version, r.initialSelected) + if len(pkgMods) != 1 || pkgMods[0] != m { + // There are candidates other than m for the given path, so we can't + // be certain that m will actually be the module selected to provide + // the package. Don't load its dependencies just yet, because they + // might no longer be dependencies after we resolve the correct + // version. + versionOk = false + } + return pathSet{pkgMods: pkgMods, err: err} + }) + } + return versionOk + } + + r.loadPackages(ctx, []string{"all"}, findPackage) + + // Since we built up the candidate lists concurrently, they may be in a + // nondeterministic order. We want 'go get' to be fully deterministic, + // including in which errors it chooses to report, so sort the candidates + // into a deterministic-but-arbitrary order. + for _, q := range r.patternAllQueries { + sort.Slice(q.candidates, func(i, j int) bool { + return q.candidates[i].path < q.candidates[j].path + }) + } +} + +// findAndUpgradeImports returns a pathSet for each package that is not yet +// in the build list but is transitively imported by the packages matching the +// given queries (which must already have been resolved). +// +// If the getU flag ("-u") is set, findAndUpgradeImports also returns a +// pathSet for each module that is not constrained by any other +// command-line argument and has an available matching upgrade. +func (r *resolver) findAndUpgradeImports(ctx context.Context, queries []*query) (upgrades []pathSet) { + patterns := make([]string, 0, len(queries)) + for _, q := range queries { + if q.matchesPackages { + patterns = append(patterns, q.pattern) + } + } + if len(patterns) == 0 { + return nil + } + + // mu guards concurrent writes to upgrades, which will be sorted + // (to restore determinism) after loading. + var mu sync.Mutex + + findPackage := func(ctx context.Context, path string, m module.Version) (versionOk bool) { + version := "latest" + if m.Path != "" { + if getU.version == "" { + // The user did not request that we upgrade transitive dependencies. + return true + } + if _, ok := r.resolvedVersion[m.Path]; ok { + // We cannot upgrade m implicitly because its version is determined by + // an explicit pattern argument. + return true + } + version = getU.version + } + + // Unlike other queries, the "-u" flag upgrades relative to the build list + // after applying changes so far, not the initial build list. + // This is for two reasons: + // + // - The "-u" flag intentionally applies to transitive dependencies, + // which may not be known or even resolved in advance of applying + // other version changes. + // + // - The "-u" flag, unlike other arguments, does not cause version + // conflicts with other queries. (The other query always wins.) + + pkgMods, err := r.queryPackages(ctx, path, version, r.selected) + for _, u := range pkgMods { + if u == m { + // The selected package version is already upgraded appropriately; there + // is no need to change it. + return true + } + } + + if err != nil { + if isNoSuchPackageVersion(err) || (m.Path == "" && module.CheckPath(path) != nil) { + // We can't find the package because it doesn't — or can't — even exist + // in any module at the latest version. (Note that invalid module paths + // could in general exist due to replacements, so we at least need to + // run the query to check those.) + // + // There is no version change we can make to fix the package, so leave + // it unresolved. Either some other query (perhaps a wildcard matching a + // newly-added dependency for some other missing package) will fill in + // the gaps, or we will report an error (with a better import stack) in + // the final LoadPackages call. + return true + } + } + + mu.Lock() + upgrades = append(upgrades, pathSet{pkgMods: pkgMods, err: err}) + mu.Unlock() + return false + } + + r.loadPackages(ctx, patterns, findPackage) + + // Since we built up the candidate lists concurrently, they may be in a + // nondeterministic order. We want 'go get' to be fully deterministic, + // including in which errors it chooses to report, so sort the candidates + // into a deterministic-but-arbitrary order. + sort.Slice(upgrades, func(i, j int) bool { + return upgrades[i].path < upgrades[j].path + }) + return upgrades +} + +// loadPackages loads the packages matching the given patterns, invoking the +// findPackage function for each package that may require a change to the +// build list. +// +// loadPackages invokes the findPackage function for each package loaded from a +// module outside the main module. If the module or version that supplies that +// package needs to be changed due to a query, findPackage may return false +// and the imports of that package will not be loaded. +// +// loadPackages also invokes the findPackage function for each imported package +// that is neither present in the standard library nor in any module in the +// build list. +func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPackage func(ctx context.Context, path string, m module.Version) (versionOk bool)) { + opts := modload.PackageOpts{ + Tags: imports.AnyTags(), + LoadTests: *getT, + SilenceErrors: true, // May be fixed by subsequent upgrades or downgrades. + } + + opts.AllowPackage = func(ctx context.Context, path string, m module.Version) error { + if m.Path == "" || m == modload.Target { + // Packages in the standard library and main module are already at their + // latest (and only) available versions. + return nil + } + if ok := findPackage(ctx, path, m); !ok { + return errVersionChange + } + return nil + } + + _, pkgs := modload.LoadPackages(ctx, opts, patterns...) + for _, path := range pkgs { + const ( + parentPath = "" + parentIsStd = false + ) + _, _, err := modload.Lookup(parentPath, parentIsStd, path) + if err == nil { + continue + } + if errors.Is(err, errVersionChange) { + // We already added candidates during loading. + continue + } + + var ( + importMissing *modload.ImportMissingError + ambiguous *modload.AmbiguousImportError + ) + if !errors.As(err, &importMissing) && !errors.As(err, &ambiguous) { + // The package, which is a dependency of something we care about, has some + // problem that we can't resolve with a version change. + // Leave the error for the final LoadPackages call. + continue + } + + path := path + r.work.Add(func() { + findPackage(ctx, path, module.Version{}) + }) + } + <-r.work.Idle() +} + +// errVersionChange is a sentinel error indicating that a module's version needs +// to be updated before its dependencies can be loaded. +var errVersionChange = errors.New("version change needed") + +// resolveCandidates resolves candidates sets that are attached to the given +// queries and/or needed to provide the given missing-package dependencies. +// +// resolveCandidates starts by resolving one module version from each +// unambiguous pathSet attached to the given queries. +// +// If no unambiguous query results in a change to the build list, +// resolveCandidates modifies the build list by adding one module version from +// each pathSet in missing, but does not mark those versions as resolved +// (so they can still be modified by other queries). +// +// If that still does not result in any changes to the build list, +// resolveCandidates revisits the ambiguous query candidates and resolves them +// arbitrarily in order to guarantee forward progress. +// +// If all pathSets are resolved without any changes to the build list, +// resolveCandidates returns with changed=false. +func (r *resolver) resolveCandidates(ctx context.Context, queries []*query, upgrades []pathSet) (changed bool) { + defer base.ExitIfErrors() + + // Note: this is O(N²) with the number of pathSets in the worst case. + // + // We could perhaps get it down to O(N) if we were to index the pathSets + // by module path, so that we only revisit a given pathSet when the + // version of some module in its containingPackage list has been determined. + // + // However, N tends to be small, and most candidate sets will include only one + // candidate module (so they will be resolved in the first iteration), so for + // now we'll stick to the simple O(N²) approach. + + resolved := 0 + for { + prevResolved := resolved + + for _, q := range queries { + unresolved := q.candidates[:0] + + for _, cs := range q.candidates { + if cs.err != nil { + reportError(q, cs.err) + resolved++ + continue + } + + filtered, isPackage, m, unique := r.disambiguate(cs) + if !unique { + unresolved = append(unresolved, filtered) + continue + } + + if m.Path == "" { + // The query is not viable. Choose an arbitrary candidate from + // before filtering and “resolve” it to report a conflict. + isPackage, m = r.chooseArbitrarily(cs) + } + if isPackage { + q.matchesPackages = true + } + r.resolve(q, m) + resolved++ + } + + q.candidates = unresolved + } + + base.ExitIfErrors() + if resolved == prevResolved { + break // No unambiguous candidate remains. + } + } + + if changed := r.updateBuildList(ctx, nil); changed { + // The build list has changed, so disregard any missing packages: they might + // now be determined by requirements in the build list, which we would + // prefer to use instead of arbitrary "latest" versions. + return true + } + + // Arbitrarily add a "latest" version that provides each missing package, but + // do not mark the version as resolved: we still want to allow the explicit + // queries to modify the resulting versions. + var tentative []module.Version + for _, cs := range upgrades { + if cs.err != nil { + base.Errorf("go get: %v", cs.err) + continue + } + + filtered, _, m, unique := r.disambiguate(cs) + if !unique { + _, m = r.chooseArbitrarily(filtered) + } + if m.Path == "" { + // There is no viable candidate for the missing package. + // Leave it unresolved. + continue + } + tentative = append(tentative, m) + } + base.ExitIfErrors() + if changed := r.updateBuildList(ctx, tentative); changed { + return true + } + + // The build list will be the same on the next iteration as it was on this + // iteration, so any ambiguous queries will remain so. In order to make + // progress, resolve them arbitrarily but deterministically. + // + // If that results in conflicting versions, the user can re-run 'go get' + // with additional explicit versions for the conflicting packages or + // modules. + for _, q := range queries { + for _, cs := range q.candidates { + isPackage, m := r.chooseArbitrarily(cs) + if isPackage { + q.matchesPackages = true + } + r.resolve(q, m) + } + } + return r.updateBuildList(ctx, nil) +} + +// disambiguate eliminates candidates from cs that conflict with other module +// versions that have already been resolved. If there is only one (unique) +// remaining candidate, disambiguate returns that candidate, along with +// an indication of whether that result interprets cs.path as a package +// +// Note: we're only doing very simple disambiguation here. The goal is to +// reproduce the user's intent, not to find a solution that a human couldn't. +// In the vast majority of cases, we expect only one module per pathSet, +// but we want to give some minimal additional tools so that users can add an +// extra argument or two on the command line to resolve simple ambiguities. +func (r *resolver) disambiguate(cs pathSet) (filtered pathSet, isPackage bool, m module.Version, unique bool) { + if len(cs.pkgMods) == 0 && cs.mod.Path == "" { + panic("internal error: resolveIfUnambiguous called with empty pathSet") + } + + for _, m := range cs.pkgMods { + if _, ok := r.noneForPath(m.Path); ok { + // A query with version "none" forces the candidate module to version + // "none", so we cannot use any other version for that module. + continue + } + + if m.Path == modload.Target.Path { + if m.Version == modload.Target.Version { + return pathSet{}, true, m, true + } + // The main module can only be set to its own version. + continue + } + + vr, ok := r.resolvedVersion[m.Path] + if !ok { + // m is a viable answer to the query, but other answers may also + // still be viable. + filtered.pkgMods = append(filtered.pkgMods, m) + continue + } + + if vr.version != m.Version { + // Some query forces the candidate module to a version other than this + // one. + // + // The command could be something like + // + // go get example.com/foo/bar@none example.com/foo/bar/baz@latest + // + // in which case we *cannot* resolve the package from + // example.com/foo/bar (because it is constrained to version + // "none") and must fall through to module example.com/foo@latest. + continue + } + + // Some query forces the candidate module *to* the candidate version. + // As a result, this candidate is the only viable choice to provide + // its package(s): any other choice would result in an ambiguous import + // for this path. + // + // For example, consider the command + // + // go get example.com/foo@latest example.com/foo/bar/baz@latest + // + // If modules example.com/foo and example.com/foo/bar both provide + // package example.com/foo/bar/baz, then we *must* resolve the package + // from example.com/foo: if we instead resolved it from + // example.com/foo/bar, we would have two copies of the package. + return pathSet{}, true, m, true + } + + if cs.mod.Path != "" { + vr, ok := r.resolvedVersion[cs.mod.Path] + if !ok || vr.version == cs.mod.Version { + filtered.mod = cs.mod + } + } + + if len(filtered.pkgMods) == 1 && + (filtered.mod.Path == "" || filtered.mod == filtered.pkgMods[0]) { + // Exactly one viable module contains the package with the given path + // (by far the common case), so we can resolve it unambiguously. + return pathSet{}, true, filtered.pkgMods[0], true + } + + if len(filtered.pkgMods) == 0 { + // All modules that could provide the path as a package conflict with other + // resolved arguments. If it can refer to a module instead, return that; + // otherwise, this pathSet cannot be resolved (and we will return the + // zero module.Version). + return pathSet{}, false, filtered.mod, true + } + + // The query remains ambiguous: there are at least two different modules + // to which cs.path could refer. + return filtered, false, module.Version{}, false +} + +// chooseArbitrarily returns an arbitrary (but deterministic) module version +// from among those in the given set. +// +// chooseArbitrarily prefers module paths that were already in the build list at +// the start of 'go get', prefers modules that provide packages over those that +// do not, and chooses the first module meeting those criteria (so biases toward +// longer paths). +func (r *resolver) chooseArbitrarily(cs pathSet) (isPackage bool, m module.Version) { + // Prefer to upgrade some module that was already in the build list. + for _, m := range cs.pkgMods { + if r.initialSelected(m.Path) != "none" { + return true, m + } + } + + // Otherwise, arbitrarily choose the first module that provides the package. + if len(cs.pkgMods) > 0 { + return true, cs.pkgMods[0] + } + + return false, cs.mod +} + +// reportChanges logs resolved version changes to os.Stderr. +func (r *resolver) reportChanges(queries []*query) { + for _, q := range queries { + if q.version == "none" { + continue + } + + if q.pattern == "all" { + // To reduce noise for "all", describe module version changes rather than + // package versions. + seen := make(map[module.Version]bool) + for _, m := range q.resolved { + if seen[m] { + continue + } + seen[m] = true + + before := r.initialSelected(m.Path) + if before == m.Version { + continue // m was resolved, but not changed + } + + was := "" + if before != "" { + was = fmt.Sprintf(" (was %s)", before) + } + fmt.Fprintf(os.Stderr, "go: %v added %s %s%s\n", q, m.Path, m.Version, was) + } + continue + } + + for _, m := range q.resolved { + before := r.initialSelected(m.Path) + if before == m.Version { + continue // m was resolved, but not changed + } + + was := "" + if before != "" { + was = fmt.Sprintf(" (was %s)", before) + } + switch { + case q.isWildcard(): + if q.matchesPath(m.Path) { + fmt.Fprintf(os.Stderr, "go: matched %v as %s %s%s\n", q, m.Path, m.Version, was) + } else { + fmt.Fprintf(os.Stderr, "go: matched %v in %s %s%s\n", q, m.Path, m.Version, was) + } + case q.matchesPackages: + fmt.Fprintf(os.Stderr, "go: found %v in %s %s%s\n", q, m.Path, m.Version, was) + default: + fmt.Fprintf(os.Stderr, "go: found %v in %s %s%s\n", q, m.Path, m.Version, was) + } + } + } + + // TODO(#33284): Also print relevant upgrades. +} + +// resolve records that module m must be at its indicated version (which may be +// "none") due to query q. If some other query forces module m to be at a +// different version, resolve reports a conflict error. +func (r *resolver) resolve(q *query, m module.Version) { + if m.Path == "" { + panic("internal error: resolving a module.Version with an empty path") + } + + if m.Path == modload.Target.Path && m.Version != modload.Target.Version { + reportError(q, &modload.QueryMatchesMainModuleError{ + Pattern: q.pattern, + Query: q.version, + }) + return + } + + vr, ok := r.resolvedVersion[m.Path] + if ok && vr.version != m.Version { + reportConflict(q, m, vr) + return + } + r.resolvedVersion[m.Path] = versionReason{m.Version, q} + q.resolved = append(q.resolved, m) +} + +// updateBuildList updates the module loader's global build list to be +// consistent with r.resolvedVersion, and to include additional modules +// provided that they do not conflict with the resolved versions. +// +// If the additional modules conflict with the resolved versions, they will be +// downgraded to a non-conflicting version (possibly "none"). +func (r *resolver) updateBuildList(ctx context.Context, additions []module.Version) (changed bool) { + if len(additions) == 0 && len(r.resolvedVersion) == r.buildListResolvedVersions { + return false + } + + defer base.ExitIfErrors() + + resolved := make([]module.Version, 0, len(r.resolvedVersion)) + for mPath, rv := range r.resolvedVersion { + if mPath != modload.Target.Path { + resolved = append(resolved, module.Version{Path: mPath, Version: rv.version}) + } + } + + if err := modload.EditBuildList(ctx, additions, resolved); err != nil { + var constraint *modload.ConstraintError + if !errors.As(err, &constraint) { + base.Errorf("go get: %v", err) + return false + } + + reason := func(m module.Version) string { + rv, ok := r.resolvedVersion[m.Path] + if !ok { + panic(fmt.Sprintf("internal error: can't find reason for requirement on %v", m)) + } + return rv.reason.ResolvedString(module.Version{Path: m.Path, Version: rv.version}) + } + for _, c := range constraint.Conflicts { + base.Errorf("go get: %v requires %v, not %v", reason(c.Source), c.Dep, reason(c.Constraint)) + } + return false + } + + buildList := modload.LoadAllModules(ctx) + r.buildListResolvedVersions = len(r.resolvedVersion) + if reflect.DeepEqual(r.buildList, buildList) { + return false + } + r.buildList = buildList + r.buildListVersion = make(map[string]string, len(r.buildList)) + for _, m := range r.buildList { + r.buildListVersion[m.Path] = m.Version + } + return true +} + +// isNoSuchModuleVersion reports whether err indicates that the requested module +// does not exist at the requested version, either because the module does not +// exist at all or because it does not include that specific version. +func isNoSuchModuleVersion(err error) bool { + var noMatch *modload.NoMatchingVersionError + return errors.Is(err, os.ErrNotExist) || errors.As(err, &noMatch) +} + +// isNoSuchPackageVersion reports whether err indicates that the requested +// package does not exist at the requested version, either because no module +// that could contain it exists at that version, or because every such module +// that does exist does not actually contain the package. +func isNoSuchPackageVersion(err error) bool { + var noPackage *modload.PackageNotInModuleError + return isNoSuchModuleVersion(err) || errors.As(err, &noPackage) +} diff --git a/src/cmd/go/internal/modget/mvs.go b/src/cmd/go/internal/modget/mvs.go deleted file mode 100644 index e7e0ec80d09..00000000000 --- a/src/cmd/go/internal/modget/mvs.go +++ /dev/null @@ -1,202 +0,0 @@ -// Copyright 2020 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 modget - -import ( - "context" - "errors" - - "cmd/go/internal/base" - "cmd/go/internal/modload" - "cmd/go/internal/mvs" - - "golang.org/x/mod/module" -) - -// An upgrader adapts an underlying mvs.Reqs to apply an -// upgrade policy to a list of targets and their dependencies. -type upgrader struct { - mvs.Reqs - - // cmdline maps a module path to a query made for that module at a - // specific target version. Each query corresponds to a module - // matched by a command line argument. - cmdline map[string]*query - - // upgrade is a set of modules providing dependencies of packages - // matched by command line arguments. If -u or -u=patch is set, - // these modules are upgraded accordingly. - upgrade map[string]bool -} - -// newUpgrader creates an upgrader. cmdline contains queries made at -// specific versions for modules matched by command line arguments. pkgs -// is the set of packages matched by command line arguments. If -u or -u=patch -// is set, modules providing dependencies of pkgs are upgraded accordingly. -func newUpgrader(cmdline map[string]*query, pkgs map[string]bool) *upgrader { - u := &upgrader{ - Reqs: modload.Reqs(), - cmdline: cmdline, - } - if getU != "" { - u.upgrade = make(map[string]bool) - - // Traverse package import graph. - // Initialize work queue with root packages. - seen := make(map[string]bool) - var work []string - add := func(path string) { - if !seen[path] { - seen[path] = true - work = append(work, path) - } - } - for pkg := range pkgs { - add(pkg) - } - for len(work) > 0 { - pkg := work[0] - work = work[1:] - m := modload.PackageModule(pkg) - u.upgrade[m.Path] = true - - // testImports is empty unless test imports were actually loaded, - // i.e., -t was set or "all" was one of the arguments. - imports, testImports := modload.PackageImports(pkg) - for _, imp := range imports { - add(imp) - } - for _, imp := range testImports { - add(imp) - } - } - } - return u -} - -// Required returns the requirement list for m. -// For the main module, we override requirements with the modules named -// one the command line, and we include new requirements. Otherwise, -// we defer to u.Reqs. -func (u *upgrader) Required(m module.Version) ([]module.Version, error) { - rs, err := u.Reqs.Required(m) - if err != nil { - return nil, err - } - if m != modload.Target { - return rs, nil - } - - overridden := make(map[string]bool) - for i, m := range rs { - if q := u.cmdline[m.Path]; q != nil && q.m.Version != "none" { - rs[i] = q.m - overridden[q.m.Path] = true - } - } - for _, q := range u.cmdline { - if !overridden[q.m.Path] && q.m.Path != modload.Target.Path && q.m.Version != "none" { - rs = append(rs, q.m) - } - } - return rs, nil -} - -// Upgrade returns the desired upgrade for m. -// -// If m was requested at a specific version on the command line, then -// Upgrade returns that version. -// -// If -u is set and m provides a dependency of a package matched by -// command line arguments, then Upgrade may provider a newer tagged version. -// If m is a tagged version, then Upgrade will return the latest tagged -// version (with the same minor version number if -u=patch). -// If m is a pseudo-version, then Upgrade returns the latest tagged version -// only if that version has a time-stamp newer than m. This special case -// prevents accidental downgrades when already using a pseudo-version -// newer than the latest tagged version. -// -// If none of the above cases apply, then Upgrade returns m. -func (u *upgrader) Upgrade(m module.Version) (module.Version, error) { - // Allow pkg@vers on the command line to override the upgrade choice v. - // If q's version is < m.Version, then we're going to downgrade anyway, - // and it's cleaner to avoid moving back and forth and picking up - // extraneous other newer dependencies. - // If q's version is > m.Version, then we're going to upgrade past - // m.Version anyway, and again it's cleaner to avoid moving back and forth - // picking up extraneous other newer dependencies. - if q := u.cmdline[m.Path]; q != nil { - return q.m, nil - } - - if !u.upgrade[m.Path] { - // Not involved in upgrade. Leave alone. - return m, nil - } - - // Run query required by upgrade semantics. - // Note that Query "latest" is not the same as using repo.Latest, - // which may return a pseudoversion for the latest commit. - // Query "latest" returns the newest tagged version or the newest - // prerelease version if there are no non-prereleases, or repo.Latest - // if there aren't any tagged versions. - // If we're querying "upgrade" or "patch", Query will compare the current - // version against the chosen version and will return the current version - // if it is newer. - info, err := modload.Query(context.TODO(), m.Path, string(getU), m.Version, checkAllowedOrCurrent(m.Version)) - if err != nil { - // Report error but return m, to let version selection continue. - // (Reporting the error will fail the command at the next base.ExitIfErrors.) - - // Special case: if the error is for m.Version itself and m.Version has a - // replacement, then keep it and don't report the error: the fact that the - // version is invalid is likely the reason it was replaced to begin with. - var vErr *module.InvalidVersionError - if errors.As(err, &vErr) && vErr.Version == m.Version && modload.Replacement(m).Path != "" { - return m, nil - } - - // Special case: if the error is "no matching versions" then don't - // even report the error. Because Query does not consider pseudo-versions, - // it may happen that we have a pseudo-version but during -u=patch - // the query v0.0 matches no versions (not even the one we're using). - var noMatch *modload.NoMatchingVersionError - if !errors.As(err, &noMatch) { - base.Errorf("go get: upgrading %s@%s: %v", m.Path, m.Version, err) - } - return m, nil - } - - if info.Version != m.Version { - logOncef("go: %s %s => %s", m.Path, getU, info.Version) - } - return module.Version{Path: m.Path, Version: info.Version}, nil -} - -// buildListForLostUpgrade returns the build list for the module graph -// rooted at lost. Unlike mvs.BuildList, the target module (lost) is not -// treated specially. The returned build list may contain a newer version -// of lost. -// -// buildListForLostUpgrade is used after a downgrade has removed a module -// requested at a specific version. This helps us understand the requirements -// implied by each downgrade. -func buildListForLostUpgrade(lost module.Version, reqs mvs.Reqs) ([]module.Version, error) { - return mvs.BuildList(lostUpgradeRoot, &lostUpgradeReqs{Reqs: reqs, lost: lost}) -} - -var lostUpgradeRoot = module.Version{Path: "lost-upgrade-root", Version: ""} - -type lostUpgradeReqs struct { - mvs.Reqs - lost module.Version -} - -func (r *lostUpgradeReqs) Required(mod module.Version) ([]module.Version, error) { - if mod == lostUpgradeRoot { - return []module.Version{r.lost}, nil - } - return r.Reqs.Required(mod) -} diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go new file mode 100644 index 00000000000..53b60cc71a0 --- /dev/null +++ b/src/cmd/go/internal/modget/query.go @@ -0,0 +1,353 @@ +// Copyright 2020 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 modget + +import ( + "fmt" + "path/filepath" + "regexp" + "strings" + "sync" + + "cmd/go/internal/base" + "cmd/go/internal/modload" + "cmd/go/internal/search" + "cmd/go/internal/str" + + "golang.org/x/mod/module" +) + +// A query describes a command-line argument and the modules and/or packages +// to which that argument may resolve.. +type query struct { + // raw is the original argument, to be printed in error messages. + raw string + + // rawVersion is the portion of raw corresponding to version, if any + rawVersion string + + // pattern is the part of the argument before "@" (or the whole argument + // if there is no "@"), which may match either packages (preferred) or + // modules (if no matching packages). + // + // The pattern may also be "-u", for the synthetic query representing the -u + // (“upgrade”)flag. + pattern string + + // patternIsLocal indicates whether pattern is restricted to match only paths + // local to the main module, such as absolute filesystem paths or paths + // beginning with './'. + // + // A local pattern must resolve to one or more packages in the main module. + patternIsLocal bool + + // version is the part of the argument after "@", or an implied + // "upgrade" or "patch" if there is no "@". version specifies the + // module version to get. + version string + + // matchWildcard, if non-nil, reports whether pattern, which must be a + // wildcard (with the substring "..."), matches the given package or module + // path. + matchWildcard func(path string) bool + + // canMatchWildcard, if non-nil, reports whether the module with the given + // path could lexically contain a package matching pattern, which must be a + // wildcard. + canMatchWildcardInModule func(mPath string) bool + + // conflict is the first query identified as incompatible with this one. + // conflict forces one or more of the modules matching this query to a + // version that does not match version. + conflict *query + + // candidates is a list of sets of alternatives for a path that matches (or + // contains packages that match) the pattern. The query can be resolved by + // choosing exactly one alternative from each set in the list. + // + // A path-literal query results in only one set: the path itself, which + // may resolve to either a package path or a module path. + // + // A wildcard query results in one set for each matching module path, each + // module for which the matching version contains at least one matching + // package, and (if no other modules match) one candidate set for the pattern + // overall if no existing match is identified in the build list. + // + // A query for pattern "all" results in one set for each package transitively + // imported by the main module. + // + // The special query for the "-u" flag results in one set for each + // otherwise-unconstrained package that has available upgrades. + candidates []pathSet + candidatesMu sync.Mutex + + // pathSeen ensures that only one pathSet is added to the query per + // unique path. + pathSeen sync.Map + + // resolved contains the set of modules whose versions have been determined by + // this query, in the order in which they were determined. + // + // The resolver examines the candidate sets for each query, resolving one + // module per candidate set in a way that attempts to avoid obvious conflicts + // between the versions resolved by different queries. + resolved []module.Version + + // matchesPackages is true if the resolved modules provide at least one + // package mathcing q.pattern. + matchesPackages bool +} + +// A pathSet describes the possible options for resolving a specific path +// to a package and/or module. +type pathSet struct { + // path is a package (if "all" or "-u" or a non-wildcard) or module (if + // wildcard) path that could be resolved by adding any of the modules in this + // set. For a wildcard pattern that so far matches no packages, the path is + // the wildcard pattern itself. + // + // Each path must occur only once in a query's candidate sets, and the path is + // added implicitly to each pathSet returned to pathOnce. + path string + + // pkgMods is a set of zero or more modules, each of which contains the + // package with the indicated path. Due to the requirement that imports be + // unambiguous, only one such module can be in the build list, and all others + // must be excluded. + pkgMods []module.Version + + // mod is either the zero Version, or a module that does not contain any + // packages matching the query but for which the module path itself + // matches the query pattern. + // + // We track this module separately from pkgMods because, all else equal, we + // prefer to match a query to a package rather than just a module. Also, + // unlike the modules in pkgMods, this module does not inherently exclude + // any other module in pkgMods. + mod module.Version + + err error +} + +// errSet returns a pathSet containing the given error. +func errSet(err error) pathSet { return pathSet{err: err} } + +// newQuery returns a new query parsed from the raw argument, +// which must be either path or path@version. +func newQuery(raw string) (*query, error) { + pattern := raw + rawVers := "" + if i := strings.Index(raw, "@"); i >= 0 { + pattern, rawVers = raw[:i], raw[i+1:] + if strings.Contains(rawVers, "@") || rawVers == "" { + return nil, fmt.Errorf("invalid module version syntax %q", raw) + } + } + + // If no version suffix is specified, assume @upgrade. + // If -u=patch was specified, assume @patch instead. + version := rawVers + if version == "" { + if getU.version == "" { + version = "upgrade" + } else { + version = getU.version + } + } + + q := &query{ + raw: raw, + rawVersion: rawVers, + pattern: pattern, + patternIsLocal: filepath.IsAbs(pattern) || search.IsRelativePath(pattern), + version: version, + } + if strings.Contains(q.pattern, "...") { + q.matchWildcard = search.MatchPattern(q.pattern) + q.canMatchWildcardInModule = search.TreeCanMatchPattern(q.pattern) + } + if err := q.validate(); err != nil { + return q, err + } + return q, nil +} + +// validate reports a non-nil error if q is not sensible and well-formed. +func (q *query) validate() error { + if q.patternIsLocal { + if q.rawVersion != "" { + return fmt.Errorf("can't request explicit version %q of path %q in main module", q.rawVersion, q.pattern) + } + return nil + } + + if q.pattern == "all" { + // If there is no main module, "all" is not meaningful. + if !modload.HasModRoot() { + return fmt.Errorf(`cannot match "all": working directory is not part of a module`) + } + if !versionOkForMainModule(q.version) { + // TODO(bcmills): "all@none" seems like a totally reasonable way to + // request that we remove all module requirements, leaving only the main + // module and standard library. Perhaps we should implement that someday. + return &modload.QueryMatchesMainModuleError{ + Pattern: q.pattern, + Query: q.version, + } + } + } + + if search.IsMetaPackage(q.pattern) && q.pattern != "all" { + if q.pattern != q.raw { + return fmt.Errorf("can't request explicit version of standard-library pattern %q", q.pattern) + } + } + + return nil +} + +// String returns the original argument from which q was parsed. +func (q *query) String() string { return q.raw } + +// ResolvedString returns a string describing m as a resolved match for q. +func (q *query) ResolvedString(m module.Version) string { + if m.Path != q.pattern { + if m.Version != q.version { + return fmt.Sprintf("%v (matching %s@%s)", m, q.pattern, q.version) + } + return fmt.Sprintf("%v (matching %v)", m, q) + } + if m.Version != q.version { + return fmt.Sprintf("%s@%s (%s)", q.pattern, q.version, m.Version) + } + return q.String() +} + +// isWildcard reports whether q is a pattern that can match multiple paths. +func (q *query) isWildcard() bool { + return q.matchWildcard != nil || (q.patternIsLocal && strings.Contains(q.pattern, "...")) +} + +// matchesPath reports whether the given path matches q.pattern. +func (q *query) matchesPath(path string) bool { + if q.matchWildcard != nil { + return q.matchWildcard(path) + } + return path == q.pattern +} + +// canMatchInModule reports whether the given module path can potentially +// contain q.pattern. +func (q *query) canMatchInModule(mPath string) bool { + if q.canMatchWildcardInModule != nil { + return q.canMatchWildcardInModule(mPath) + } + return str.HasPathPrefix(q.pattern, mPath) +} + +// pathOnce invokes f to generate the pathSet for the given path, +// if one is still needed. +// +// Note that, unlike sync.Once, pathOnce does not guarantee that a concurrent +// call to f for the given path has completed on return. +// +// pathOnce is safe for concurrent use by multiple goroutines, but note that +// multiple concurrent calls will result in the sets being added in +// nondeterministic order. +func (q *query) pathOnce(path string, f func() pathSet) { + if _, dup := q.pathSeen.LoadOrStore(path, nil); dup { + return + } + + cs := f() + + if len(cs.pkgMods) > 0 || cs.mod != (module.Version{}) || cs.err != nil { + cs.path = path + q.candidatesMu.Lock() + q.candidates = append(q.candidates, cs) + q.candidatesMu.Unlock() + } +} + +// reportError logs err concisely using base.Errorf. +func reportError(q *query, err error) { + errStr := err.Error() + + // If err already mentions all of the relevant parts of q, just log err to + // reduce stutter. Otherwise, log both q and err. + // + // TODO(bcmills): Use errors.As to unpack these errors instead of parsing + // strings with regular expressions. + + patternRE := regexp.MustCompile("(?m)(?:[ \t(\"`]|^)" + regexp.QuoteMeta(q.pattern) + "(?:[ @:)\"`]|$)") + if patternRE.MatchString(errStr) { + if q.rawVersion == "" { + base.Errorf("go get: %s", errStr) + return + } + + versionRE := regexp.MustCompile("(?m)(?:[ @(\"`]|^)" + regexp.QuoteMeta(q.version) + "(?:[ :)\"`]|$)") + if versionRE.MatchString(errStr) { + base.Errorf("go get: %s", errStr) + return + } + } + + base.Errorf("go get %s: %s", q, errStr) +} + +func reportConflict(pq *query, m module.Version, conflict versionReason) { + if pq.conflict != nil { + // We've already reported a conflict for the proposed query. + // Don't report it again, even if it has other conflicts. + return + } + pq.conflict = conflict.reason + + proposed := versionReason{ + version: m.Version, + reason: pq, + } + if pq.isWildcard() && !conflict.reason.isWildcard() { + // Prefer to report the specific path first and the wildcard second. + proposed, conflict = conflict, proposed + } + reportError(pq, &conflictError{ + mPath: m.Path, + proposed: proposed, + conflict: conflict, + }) +} + +type conflictError struct { + mPath string + proposed versionReason + conflict versionReason +} + +func (e *conflictError) Error() string { + argStr := func(q *query, v string) string { + if v != q.version { + return fmt.Sprintf("%s@%s (%s)", q.pattern, q.version, v) + } + return q.String() + } + + pq := e.proposed.reason + rq := e.conflict.reason + modDetail := "" + if e.mPath != pq.pattern { + modDetail = fmt.Sprintf("for module %s, ", e.mPath) + } + + return fmt.Sprintf("%s%s conflicts with %s", + modDetail, + argStr(pq, e.proposed.version), + argStr(rq, e.conflict.version)) +} + +func versionOkForMainModule(version string) bool { + return version == "upgrade" || version == "patch" +} diff --git a/src/cmd/go/internal/modload/buildlist.go b/src/cmd/go/internal/modload/buildlist.go index 4a183d6881b..4aaaa8d2065 100644 --- a/src/cmd/go/internal/modload/buildlist.go +++ b/src/cmd/go/internal/modload/buildlist.go @@ -12,6 +12,7 @@ import ( "context" "fmt" "os" + "strings" "golang.org/x/mod/module" ) @@ -27,6 +28,11 @@ import ( // var buildList []module.Version +// capVersionSlice returns s with its cap reduced to its length. +func capVersionSlice(s []module.Version) []module.Version { + return s[:len(s):len(s)] +} + // LoadAllModules loads and returns the list of modules matching the "all" // module pattern, starting with the Target module and in a deterministic // (stable) order, without loading any packages. @@ -35,21 +41,21 @@ var buildList []module.Version // LoadAllModules need only be called if LoadPackages is not, // typically in commands that care about modules but no particular package. // -// The caller must not modify the returned list. +// The caller must not modify the returned list, but may append to it. func LoadAllModules(ctx context.Context) []module.Version { LoadModFile(ctx) ReloadBuildList() WriteGoMod() - return buildList + return capVersionSlice(buildList) } // LoadedModules returns the list of module requirements loaded or set by a // previous call (typically LoadAllModules or LoadPackages), starting with the // Target module and in a deterministic (stable) order. // -// The caller must not modify the returned list. +// The caller must not modify the returned list, but may append to it. func LoadedModules() []module.Version { - return buildList + return capVersionSlice(buildList) } // Selected returns the selected version of the module with the given path, or @@ -74,6 +80,147 @@ func SetBuildList(list []module.Version) { buildList = append([]module.Version{}, list...) } +// EditBuildList edits the global build list by first adding every module in add +// to the existing build list, then adjusting versions (and adding or removing +// requirements as needed) until every module in mustSelect is selected at the +// given version. +// +// (Note that the newly-added modules might not be selected in the resulting +// build list: they could be lower than existing requirements or conflict with +// versions in mustSelect.) +// +// After performing the requested edits, EditBuildList returns the updated build +// list. +// +// If the versions listed in mustSelect are mutually incompatible (due to one of +// the listed modules requiring a higher version of another), EditBuildList +// returns a *ConstraintError and leaves the build list in its previous state. +func EditBuildList(ctx context.Context, add, mustSelect []module.Version) error { + var upgraded = capVersionSlice(buildList) + if len(add) > 0 { + // First, upgrade the build list with any additions. + // In theory we could just append the additions to the build list and let + // mvs.Downgrade take care of resolving the upgrades too, but the + // diagnostics from Upgrade are currently much better in case of errors. + var err error + upgraded, err = mvs.Upgrade(Target, &mvsReqs{buildList: upgraded}, add...) + if err != nil { + return err + } + } + + downgraded, err := mvs.Downgrade(Target, &mvsReqs{buildList: append(upgraded, mustSelect...)}, mustSelect...) + if err != nil { + return err + } + + final, err := mvs.Upgrade(Target, &mvsReqs{buildList: downgraded}, mustSelect...) + if err != nil { + return err + } + + selected := make(map[string]module.Version, len(final)) + for _, m := range final { + selected[m.Path] = m + } + inconsistent := false + for _, m := range mustSelect { + s, ok := selected[m.Path] + if !ok { + if m.Version != "none" { + panic(fmt.Sprintf("internal error: mvs.BuildList lost %v", m)) + } + continue + } + if s.Version != m.Version { + inconsistent = true + break + } + } + + if !inconsistent { + buildList = final + return nil + } + + // We overshot one or more of the modules in mustSelected, which means that + // Downgrade removed something in mustSelect because it conflicted with + // something else in mustSelect. + // + // Walk the requirement graph to find the conflict. + // + // TODO(bcmills): Ideally, mvs.Downgrade (or a replacement for it) would do + // this directly. + + reqs := &mvsReqs{buildList: final} + reason := map[module.Version]module.Version{} + for _, m := range mustSelect { + reason[m] = m + } + queue := mustSelect[:len(mustSelect):len(mustSelect)] + for len(queue) > 0 { + var m module.Version + m, queue = queue[0], queue[1:] + required, err := reqs.Required(m) + if err != nil { + return err + } + for _, r := range required { + if _, ok := reason[r]; !ok { + reason[r] = reason[m] + queue = append(queue, r) + } + } + } + + var conflicts []Conflict + for _, m := range mustSelect { + s, ok := selected[m.Path] + if !ok { + if m.Version != "none" { + panic(fmt.Sprintf("internal error: mvs.BuildList lost %v", m)) + } + continue + } + if s.Version != m.Version { + conflicts = append(conflicts, Conflict{ + Source: reason[s], + Dep: s, + Constraint: m, + }) + } + } + + return &ConstraintError{ + Conflicts: conflicts, + } +} + +// A ConstraintError describes inconsistent constraints in EditBuildList +type ConstraintError struct { + // Conflict lists the source of the conflict for each version in mustSelect + // that could not be selected due to the requirements of some other version in + // mustSelect. + Conflicts []Conflict +} + +func (e *ConstraintError) Error() string { + b := new(strings.Builder) + b.WriteString("version constraints conflict:") + for _, c := range e.Conflicts { + fmt.Fprintf(b, "\n\t%v requires %v, but %v is requested", c.Source, c.Dep, c.Constraint) + } + return b.String() +} + +// A Conflict documents that Source requires Dep, which conflicts with Constraint. +// (That is, Dep has the same module path as Constraint but a higher version.) +type Conflict struct { + Source module.Version + Dep module.Version + Constraint module.Version +} + // ReloadBuildList resets the state of loaded packages, then loads and returns // the build list set in SetBuildList. func ReloadBuildList() []module.Version { @@ -84,7 +231,7 @@ func ReloadBuildList() []module.Version { listRoots: func() []string { return nil }, allClosesOverTests: index.allPatternClosesOverTests(), // but doesn't matter because the root list is empty. }) - return buildList + return capVersionSlice(buildList) } // TidyBuildList trims the build list to the minimal requirements needed to diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 193edfdd208..eb0a366f924 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -188,9 +188,9 @@ func (e *invalidImportError) Unwrap() error { // importFromBuildList can return an empty directory string, for fake packages // like "C" and "unsafe". // -// If the package cannot be found in the current build list, +// If the package cannot be found in buildList, // importFromBuildList returns an *ImportMissingError. -func importFromBuildList(ctx context.Context, path string) (m module.Version, dir string, err error) { +func importFromBuildList(ctx context.Context, path string, buildList []module.Version) (m module.Version, dir string, err error) { if strings.Contains(path, "@") { return module.Version{}, "", fmt.Errorf("import path should not have @version") } diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index 0a84a1765a5..302330278eb 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -141,6 +141,15 @@ type PackageOpts struct { // if the flag is set to "readonly" (the default) or "vendor". ResolveMissingImports bool + // AllowPackage, if non-nil, is called after identifying the module providing + // each package. If AllowPackage returns a non-nil error, that error is set + // for the package, and the imports and test of that package will not be + // loaded. + // + // AllowPackage may be invoked concurrently by multiple goroutines, + // and may be invoked multiple times for a given package path. + AllowPackage func(ctx context.Context, path string, mod module.Version) error + // LoadTests loads the test dependencies of each package matching a requested // pattern. If ResolveMissingImports is also true, test dependencies will be // resolved if missing. @@ -550,6 +559,7 @@ func DirImportPath(dir string) string { func TargetPackages(ctx context.Context, pattern string) *search.Match { // TargetPackages is relative to the main module, so ensure that the main // module is a thing that can contain packages. + LoadModFile(ctx) ModRoot() m := search.NewMatch(pattern) @@ -1042,7 +1052,7 @@ func (ld *loader) load(pkg *loadPkg) { return } - pkg.mod, pkg.dir, pkg.err = importFromBuildList(context.TODO(), pkg.path) + pkg.mod, pkg.dir, pkg.err = importFromBuildList(context.TODO(), pkg.path, buildList) if pkg.dir == "" { return } @@ -1058,6 +1068,11 @@ func (ld *loader) load(pkg *loadPkg) { // to scanning source code for imports). ld.applyPkgFlags(pkg, pkgInAll) } + if ld.AllowPackage != nil { + if err := ld.AllowPackage(context.TODO(), pkg.path, pkg.mod); err != nil { + pkg.err = err + } + } imports, testImports, err := scanDir(pkg.dir, ld.Tags) if err != nil { diff --git a/src/cmd/go/internal/modload/mvs.go b/src/cmd/go/internal/modload/mvs.go index 045cbead3b2..02b13cdd053 100644 --- a/src/cmd/go/internal/modload/mvs.go +++ b/src/cmd/go/internal/modload/mvs.go @@ -99,8 +99,16 @@ func versions(ctx context.Context, path string, allowed AllowedFunc) ([]string, // Previous returns the tagged version of m.Path immediately prior to // m.Version, or version "none" if no prior version is tagged. +// +// Since the version of Target is not found in the version list, +// it has no previous version. func (*mvsReqs) Previous(m module.Version) (module.Version, error) { // TODO(golang.org/issue/38714): thread tracing context through MVS. + + if m == Target { + return module.Version{Path: m.Path, Version: "none"}, nil + } + list, err := versions(context.TODO(), m.Path, CheckAllowed) if err != nil { if errors.Is(err, os.ErrNotExist) { diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 99cbac1aa79..d4a1e850415 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -47,8 +47,9 @@ import ( // with non-prereleases preferred over prereleases. // - a repository commit identifier or tag, denoting that commit. // -// current denotes the current version of the module; it may be "" if the -// current version is unknown or should not be considered. If query is +// current denotes the currently-selected version of the module; it may be +// "none" if no version is currently selected, or "" if the currently-selected +// version is unknown or should not be considered. If query is // "upgrade" or "patch", current will be returned if it is a newer // semantic version or a chronologically later pseudo-version than the // version that would otherwise be chosen. This prevents accidental downgrades @@ -98,7 +99,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed ctx, span := trace.StartSpan(ctx, "modload.queryProxy "+path+" "+query) defer span.Done() - if current != "" && !semver.IsValid(current) { + if current != "" && current != "none" && !semver.IsValid(current) { return nil, fmt.Errorf("invalid previous version %q", current) } if cfg.BuildMod == "vendor" { @@ -109,7 +110,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed } if path == Target.Path { - if query != "latest" && query != "upgrade" && query != "patch" { + if query != "upgrade" && query != "patch" { return nil, &QueryMatchesMainModuleError{Pattern: path, Query: query} } if err := allowed(ctx, Target); err != nil { @@ -236,7 +237,7 @@ func queryProxy(ctx context.Context, proxy, path, query, current string, allowed } } - if (query == "upgrade" || query == "patch") && current != "" { + if (query == "upgrade" || query == "patch") && current != "" && current != "none" { // "upgrade" and "patch" may stay on the current version if allowed. if err := allowed(ctx, module.Version{Path: path, Version: current}); errors.Is(err, ErrDisallowed) { return nil, err @@ -323,7 +324,7 @@ func newQueryMatcher(path string, query, current string, allowed AllowedFunc) (* qm.mayUseLatest = true case query == "upgrade": - if current == "" { + if current == "" || current == "none" { qm.mayUseLatest = true } else { qm.mayUseLatest = modfetch.IsPseudoVersion(current) @@ -331,6 +332,9 @@ func newQueryMatcher(path string, query, current string, allowed AllowedFunc) (* } case query == "patch": + if current == "none" { + return nil, &NoPatchBaseError{path} + } if current == "" { qm.mayUseLatest = true } else { @@ -554,6 +558,9 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if i := strings.Index(pattern, "..."); i >= 0 { base = pathpkg.Dir(pattern[:i+3]) + if base == "." { + return nil, nil, &WildcardInFirstElementError{Pattern: pattern, Query: query} + } match = func(mod module.Version, root string, isLocal bool) *search.Match { m := search.NewMatch(pattern) matchPackages(ctx, m, imports.AnyTags(), omitStd, []module.Version{mod}) @@ -578,7 +585,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin if HasModRoot() { m := match(Target, modRoot, true) if len(m.Pkgs) > 0 { - if query != "latest" && query != "upgrade" && query != "patch" { + if query != "upgrade" && query != "patch" { return nil, nil, &QueryMatchesPackagesInMainModuleError{ Pattern: pattern, Query: query, @@ -598,7 +605,7 @@ func QueryPattern(ctx context.Context, pattern, query string, current func(strin return nil, nil, err } - if query != "latest" && query != "upgrade" && query != "patch" && matchPattern(Target.Path) { + if query != "upgrade" && query != "patch" && matchPattern(Target.Path) { if err := allowed(ctx, Target); err == nil { modOnly = &QueryResult{ Mod: Target, @@ -724,6 +731,7 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod var ( noPackage *PackageNotInModuleError noVersion *NoMatchingVersionError + noPatchBase *NoPatchBaseError notExistErr error ) for _, r := range results { @@ -740,6 +748,10 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod if noVersion == nil { noVersion = rErr } + case *NoPatchBaseError: + if noPatchBase == nil { + noPatchBase = rErr + } default: if errors.Is(rErr, fs.ErrNotExist) { if notExistErr == nil { @@ -771,6 +783,8 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod err = noPackage case noVersion != nil: err = noVersion + case noPatchBase != nil: + err = noPatchBase case notExistErr != nil: err = notExistErr default: @@ -795,12 +809,34 @@ type NoMatchingVersionError struct { func (e *NoMatchingVersionError) Error() string { currentSuffix := "" - if (e.query == "upgrade" || e.query == "patch") && e.current != "" { + if (e.query == "upgrade" || e.query == "patch") && e.current != "" && e.current != "none" { currentSuffix = fmt.Sprintf(" (current version is %s)", e.current) } return fmt.Sprintf("no matching versions for query %q", e.query) + currentSuffix } +// A NoPatchBaseError indicates that Query was called with the query "patch" +// but with a current version of "" or "none". +type NoPatchBaseError struct { + path string +} + +func (e *NoPatchBaseError) Error() string { + return fmt.Sprintf(`can't query version "patch" of module %s: no existing version is required`, e.path) +} + +// A WildcardInFirstElementError indicates that a pattern passed to QueryPattern +// had a wildcard in its first path element, and therefore had no pattern-prefix +// modules to search in. +type WildcardInFirstElementError struct { + Pattern string + Query string +} + +func (e *WildcardInFirstElementError) Error() string { + return fmt.Sprintf("no modules to query for %s@%s because first path element contains a wildcard", e.Pattern, e.Query) +} + // A PackageNotInModuleError indicates that QueryPattern found a candidate // module at the requested version, but that module did not contain any packages // matching the requested pattern. diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go index f6d6f5f764e..1fe742dc97d 100644 --- a/src/cmd/go/internal/modload/search.go +++ b/src/cmd/go/internal/modload/search.go @@ -156,7 +156,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f isLocal = true } else { var err error - needSum := true + const needSum = true root, isLocal, err = fetch(ctx, mod, needSum) if err != nil { m.AddError(err) @@ -174,3 +174,46 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f return } + +// MatchInModule identifies the packages matching the given pattern within the +// given module version, which does not need to be in the build list or module +// requirement graph. +// +// If m is the zero module.Version, MatchInModule matches the pattern +// against the standard library (std and cmd) in GOROOT/src. +func MatchInModule(ctx context.Context, pattern string, m module.Version, tags map[string]bool) *search.Match { + match := search.NewMatch(pattern) + if m == (module.Version{}) { + matchPackages(ctx, match, tags, includeStd, nil) + } + + LoadModFile(ctx) + + if !match.IsLiteral() { + matchPackages(ctx, match, tags, omitStd, []module.Version{m}) + return match + } + + const needSum = true + root, isLocal, err := fetch(ctx, m, needSum) + if err != nil { + match.Errs = []error{err} + return match + } + + dir, haveGoFiles, err := dirInModule(pattern, m.Path, root, isLocal) + if err != nil { + match.Errs = []error{err} + return match + } + if haveGoFiles { + if _, _, err := scanDir(dir, tags); err != imports.ErrNoGo { + // ErrNoGo indicates that the directory is not actually a Go package, + // perhaps due to the tags in use. Any other non-nil error indicates a + // problem with one or more of the Go source files, but such an error does + // not stop the package from existing, so it has no impact on matching. + match.Pkgs = []string{pattern} + } + } + return match +} diff --git a/src/cmd/go/testdata/script/get_update_all.txt b/src/cmd/go/testdata/script/get_update_all.txt index d0b9860ade0..2b758492095 100644 --- a/src/cmd/go/testdata/script/get_update_all.txt +++ b/src/cmd/go/testdata/script/get_update_all.txt @@ -3,5 +3,7 @@ [!net] skip +env GO111MODULE=off + go get -u -n .../ ! stderr 'duplicate loads of' # make sure old packages are removed from cache diff --git a/src/cmd/go/testdata/script/mod_bad_domain.txt b/src/cmd/go/testdata/script/mod_bad_domain.txt index 868a8d43d67..20199c1c2ca 100644 --- a/src/cmd/go/testdata/script/mod_bad_domain.txt +++ b/src/cmd/go/testdata/script/mod_bad_domain.txt @@ -2,7 +2,7 @@ env GO111MODULE=on # explicit get should report errors about bad names ! go get appengine -stderr '^go get appengine: package appengine is not in GOROOT \(.*\)$' +stderr '^go get: malformed module path "appengine": missing dot in first path element$' ! go get x/y.z stderr 'malformed module path "x/y.z": missing dot in first path element' diff --git a/src/cmd/go/testdata/script/mod_dot.txt b/src/cmd/go/testdata/script/mod_dot.txt index 1f7643e1dea..72be6127999 100644 --- a/src/cmd/go/testdata/script/mod_dot.txt +++ b/src/cmd/go/testdata/script/mod_dot.txt @@ -5,7 +5,7 @@ env GO111MODULE=on # to resolve an external module. cd dir ! go get . -stderr 'go get \.: path .* is not a package in module rooted at .*[/\\]dir$' +stderr 'go get: \. \(.*[/\\]dir\) is not a package in module rooted at .*[/\\]dir$' ! go list ! stderr 'cannot find module providing package' stderr '^no Go files in '$WORK'[/\\]gopath[/\\]src[/\\]dir$' diff --git a/src/cmd/go/testdata/script/mod_download.txt b/src/cmd/go/testdata/script/mod_download.txt index c53bbe45674..2775fca44ee 100644 --- a/src/cmd/go/testdata/script/mod_download.txt +++ b/src/cmd/go/testdata/script/mod_download.txt @@ -101,11 +101,11 @@ stderr '^rsc.io/quote@v1.999.999: reading .*/v1.999.999.info: 404 Not Found$' ! go mod download -json bad/path stdout '^\t"Error": "module bad/path: not a known dependency"' -# download main module returns an error +# download main module produces a warning or error go mod download m stderr '^go mod download: skipping argument m that resolves to the main module\n' -go mod download m@latest -stderr '^go mod download: skipping argument m@latest that resolves to the main module\n' +! go mod download m@latest +stderr 'm@latest: can''t request version "latest" of the main module \(m\)' # download updates go.mod and populates go.sum cd update diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt index f64da3a3fd0..daed03b02c6 100644 --- a/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt +++ b/src/cmd/go/testdata/script/mod_get_ambiguous_arg.txt @@ -1,23 +1,22 @@ go mod tidy cp go.mod go.mod.orig -# If there is no sensible *package* meaning for 'm/p', perhaps it should refer -# to *module* m/p? -# Today, it still seems to refer to the package. +# If there is no sensible *package* meaning for 'm/p', it should refer +# to *module* m/p. -! go get -d m/p@v0.1.0 -stderr 'go get m/p@v0.1.0: module m/p@latest found \(v0.1.0, replaced by ./mp01\), but does not contain package m/p' -cmp go.mod.orig go.mod - - -# TODO(#37438): If we add v0.2.0 before this point, we end up (somehow!) -# resolving m/p@v0.1.0 as *both* a module and a package. +go get -d m/p # @latest +go list -m all +stdout '^m/p v0.3.0 ' +! stdout '^m ' cp go.mod.orig go.mod -go mod edit -replace=m@v0.2.0=./m02 -go mod edit -replace=m/p@v0.2.0=./mp02 -# The argument 'm/p' in 'go get m/p' refers to *package* m/p, +go get -d m/p@v0.1.0 +go list -m all +stdout '^m/p v0.1.0 ' +! stdout '^m ' + +# When feasible, the argument 'm/p' in 'go get m/p' refers to *package* m/p, # which is in module m. # # (It only refers to *module* m/p if there is no such package at the @@ -26,7 +25,7 @@ go mod edit -replace=m/p@v0.2.0=./mp02 go get -d m/p@v0.2.0 go list -m all stdout '^m v0.2.0 ' -stdout '^m/p v0.1.0 ' +stdout '^m/p v0.1.0 ' # unchanged from the previous case # Repeating the above with module m/p already in the module graph does not # change its meaning. @@ -36,26 +35,6 @@ go list -m all stdout '^m v0.2.0 ' stdout '^m/p v0.1.0 ' - -# TODO(#37438): If we add v0.3.0 before this point, we get a totally bogus error -# today, because 'go get' ends up attempting to resolve package 'm/p' without a -# specific version and can't find it if module m no longer contains v0.3.0. - -cp go.mod.orig go.mod -go mod edit -replace=m@v0.3.0=./m03 -go mod edit -replace=m/p@v0.3.0=./mp03 - -! go get -d m/p@v0.2.0 -stderr 'go get m/p@v0.2.0: module m/p@latest found \(v0.3.0, replaced by ./mp03\), but does not contain package m/p$' - -# If there is no sensible package meaning for 'm/p', perhaps it should refer -# to *module* m/p? -# Today, it still seems to refer to the package. - -! go get -d m/p@v0.3.0 -stderr '^go get m/p@v0.3.0: module m/p@latest found \(v0\.3\.0, replaced by \./mp03\), but does not contain package m/p$' - - -- go.mod -- module example.com @@ -63,7 +42,11 @@ go 1.16 replace ( m v0.1.0 => ./m01 + m v0.2.0 => ./m02 + m v0.3.0 => ./m03 m/p v0.1.0 => ./mp01 + m/p v0.2.0 => ./mp02 + m/p v0.3.0 => ./mp03 ) -- m01/go.mod -- module m diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt index 8f5bf20636d..33605f51a5b 100644 --- a/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt +++ b/src/cmd/go/testdata/script/mod_get_ambiguous_import.txt @@ -9,7 +9,7 @@ cp go.mod go.mod.orig # TODO(#27899): Should we automatically upgrade example.net/m to v0.2.0 # to resolve the conflict? ! go get -d example.net/m/p@v1.0.0 -stderr '^go get example.net/m/p@v1.0.0: ambiguous import: found package example.net/m/p in multiple modules:\n\texample.net/m v0.1.0 \(.*[/\\]m1[/\\]p\)\n\texample.net/m/p v1.0.0 \(.*[/\\]p0\)\n\z' +stderr '^example.net/m/p: ambiguous import: found package example.net/m/p in multiple modules:\n\texample.net/m v0.1.0 \(.*[/\\]m1[/\\]p\)\n\texample.net/m/p v1.0.0 \(.*[/\\]p0\)\n\z' cmp go.mod go.mod.orig # Upgrading both modules simultaneously resolves the ambiguous upgrade. diff --git a/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt b/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt index f00f99ee8c8..0e7f93bccb5 100644 --- a/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt +++ b/src/cmd/go/testdata/script/mod_get_ambiguous_pkg.txt @@ -15,22 +15,20 @@ stdout '^example.net/ambiguous/nested v0.1.0$' # From an initial state that already depends on the shorter path, -# the same 'go get' command attempts to add the longer path and fails. -# -# TODO(bcmills): What should really happen here? -# Should we match the versioned package path against the existing package -# (reducing unexpected errors), or give it the same meaning regardless of the -# initial state? +# the same 'go get' command should (somewhat arbitrarily) keep the +# existing path, since it is a valid interpretation of the command. cp go.mod.orig go.mod go mod edit -require=example.net/ambiguous@v0.1.0 -! go get -d example.net/ambiguous/nested/pkg@v0.1.0 -stderr '^go get example.net/ambiguous/nested/pkg@v0.1.0: ambiguous import: found package example.net/ambiguous/nested/pkg in multiple modules:\n\texample.net/ambiguous v0.1.0 \(.*\)\n\texample.net/ambiguous/nested v0.1.0 \(.*\)\n\z' +go get -d example.net/ambiguous/nested/pkg@v0.1.0 +go list -m all +stdout '^example.net/ambiguous v0.1.0$' +! stdout '^example.net/ambiguous/nested ' -# The user should be able to fix the aforementioned failure by explicitly -# upgrading the conflicting module. +# The user should be able to make the command unambiguous by explicitly +# upgrading the conflicting module... go get -d example.net/ambiguous@v0.2.0 example.net/ambiguous/nested/pkg@v0.1.0 go list -m all @@ -39,38 +37,26 @@ stdout '^example.net/ambiguous v0.2.0$' # ...or by explicitly NOT adding the conflicting module. -# -# BUG(#37438): Today, this does not work: explicit module version constraints do -# not affect the package-to-module mapping during package upgrades, so the -# arguments are interpreted as specifying conflicting versions of the longer -# module path. cp go.mod.orig go.mod go mod edit -require=example.net/ambiguous@v0.1.0 -! go get -d example.net/ambiguous/nested/pkg@v0.1.0 example.net/ambiguous/nested@none -stderr '^go get: conflicting versions for module example.net/ambiguous/nested: v0.1.0 and none$' - - # go list -m all - # ! stdout '^example.net/ambiguous/nested ' - # stdout '^example.net/ambiguous v0.1.0$' +go get -d example.net/ambiguous/nested/pkg@v0.1.0 example.net/ambiguous/nested@none +go list -m all +! stdout '^example.net/ambiguous/nested ' +stdout '^example.net/ambiguous v0.1.0$' # The user should also be able to fix it by *downgrading* the conflicting module # away. -# -# BUG(#37438): Today, this does not work: the "ambiguous import" error causes -# 'go get' to fail before applying the requested downgrade. cp go.mod.orig go.mod go mod edit -require=example.net/ambiguous@v0.1.0 -! go get -d example.net/ambiguous@none example.net/ambiguous/nested/pkg@v0.1.0 -stderr '^go get example.net/ambiguous/nested/pkg@v0.1.0: ambiguous import: found package example.net/ambiguous/nested/pkg in multiple modules:\n\texample.net/ambiguous v0.1.0 \(.*\)\n\texample.net/ambiguous/nested v0.1.0 \(.*\)\n\z' - - # go list -m all - # stdout '^example.net/ambiguous/nested v0.1.0$' - # !stdout '^example.net/ambiguous ' +go get -d example.net/ambiguous@none example.net/ambiguous/nested/pkg@v0.1.0 +go list -m all +stdout '^example.net/ambiguous/nested v0.1.0$' +! stdout '^example.net/ambiguous ' # In contrast, if we do the same thing tacking a wildcard pattern ('/...') on diff --git a/src/cmd/go/testdata/script/mod_get_downgrade.txt b/src/cmd/go/testdata/script/mod_get_downgrade.txt index ee9ac964751..77dad2b3853 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade.txt @@ -19,7 +19,8 @@ go list -m all stdout 'rsc.io/quote v1.5.1' stdout 'rsc.io/sampler v1.3.0' ! go get rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none -stderr 'go get: inconsistent versions:\n\trsc.io/quote@v1.5.2 requires golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c \(not golang.org/x/text@none\), rsc.io/sampler@v1.3.0 \(not rsc.io/sampler@v1.0.0\)' +stderr '^go get: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$' +stderr '^go get: rsc.io/quote@v1.5.2 requires golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c, not golang.org/x/text@none$' go list -m all stdout 'rsc.io/quote v1.5.1' stdout 'rsc.io/sampler v1.3.0' diff --git a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt index 543f9f8111d..f1167fb578a 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt @@ -5,12 +5,12 @@ cp go.mod go.mod.orig # rather than a "matched no packages" warning. ! go get example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... -stderr '^go get: conflicting versions for module example\.net/pkgadded: v1\.1\.0 and v1\.2\.0$' +stderr '^go get: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$' ! stderr 'matched no packages' cmp go.mod.orig go.mod -# A wildcard pattern should match a package in a module with that path. +# A wildcard pattern should match the pattern with that path. go get example.net/pkgadded/...@v1.0.0 go list -m all @@ -23,8 +23,8 @@ cp go.mod.orig go.mod # package, then 'go get' should fail with a useful error message. ! go get example.net/pkgadded@v1.0.0 . -stderr -count=1 '^go: found example.net/pkgadded/subpkg in example.net/pkgadded v1\.2\.0$' # TODO: We shouldn't even try v1.2.0. stderr '^example.com/m imports\n\texample.net/pkgadded/subpkg: cannot find module providing package example.net/pkgadded/subpkg$' +! stderr 'example.net/pkgadded v1\.2\.0' cmp go.mod.orig go.mod go get example.net/pkgadded@v1.0.0 diff --git a/src/cmd/go/testdata/script/mod_get_extra.txt b/src/cmd/go/testdata/script/mod_get_extra.txt new file mode 100644 index 00000000000..7efa24e87b0 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_extra.txt @@ -0,0 +1,69 @@ +cp go.mod go.mod.orig + +# The -u flag should not (even temporarily) upgrade modules whose versions are +# determined by explicit queries to any version other than the explicit one. +# Otherwise, 'go get -u' could introduce spurious dependencies. + +go get -d -u example.net/a@v0.1.0 example.net/b@v0.1.0 +go list -m all +stdout '^example.net/a v0.1.0 ' +stdout '^example.net/b v0.1.0 ' +! stdout '^example.net/c ' + + +# TODO(bcmills): This property does not yet hold for modules added for +# missing packages when the newly-added module matches a wildcard. + +cp go.mod.orig go.mod + +go get -d -u example.net/a@v0.1.0 example.net/b/...@v0.1.0 +go list -m all +stdout '^example.net/a v0.1.0 ' +stdout '^example.net/b v0.1.0 ' +stdout '^example.net/c ' # BUG, but a minor and rare one + + +-- go.mod -- +module example + +go 1.15 + +replace ( + example.net/a v0.1.0 => ./a1 + example.net/b v0.1.0 => ./b1 + example.net/b v0.2.0 => ./b2 + example.net/c v0.1.0 => ./c1 + example.net/c v0.2.0 => ./c1 +) + +-- a1/go.mod -- +module example.net/a + +go 1.15 + +// example.net/a needs a dependency on example.net/b, but lacks a requirement +// on it (perhaps due to a missed file in a VCS commit). +-- a1/a.go -- +package a +import _ "example.net/b" + +-- b1/go.mod -- +module example.net/b + +go 1.15 +-- b1/b.go -- +package b + +-- b2/go.mod -- +module example.net/b + +go 1.15 + +require example.net/c v0.1.0 +-- b2/b.go -- +package b + +-- c1/go.mod -- +module example.net/c + +go 1.15 diff --git a/src/cmd/go/testdata/script/mod_get_issue37438.txt b/src/cmd/go/testdata/script/mod_get_issue37438.txt new file mode 100644 index 00000000000..38b2031d3ae --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_issue37438.txt @@ -0,0 +1,37 @@ +# Regression test for https://golang.org/issue/37438. +# +# If a path exists at the requested version, but does not exist at the +# version of the module that is already required and does not exist at +# the version that would be selected by 'go mod tidy', then +# 'go get foo@requested' should resolve the requested version, +# not error out on the (unrelated) latest one. + +go get -d example.net/a/p@v0.2.0 + +-- go.mod -- +module example + +go 1.15 + +require example.net/a v0.1.0 + +replace ( + example.net/a v0.1.0 => ./a1 + example.net/a v0.2.0 => ./a2 + example.net/a v0.3.0 => ./a1 +) + +-- a1/go.mod -- +module example.net/a + +go 1.15 +-- a1/README -- +package example.net/a/p does not exist at this version. + +-- a2/go.mod -- +module example.net/a + +go 1.15 +-- a2/p/p.go -- +// Package p exists only at v0.2.0. +package p diff --git a/src/cmd/go/testdata/script/mod_get_main.txt b/src/cmd/go/testdata/script/mod_get_main.txt index 408a5b51c84..eeaa92d8ca5 100644 --- a/src/cmd/go/testdata/script/mod_get_main.txt +++ b/src/cmd/go/testdata/script/mod_get_main.txt @@ -3,13 +3,13 @@ cp go.mod.orig go.mod # relative and absolute paths must be within the main module. ! go get -d .. -stderr '^go get \.\.: path '$WORK'[/\\]gopath is not a package in module rooted at '$WORK'[/\\]gopath[/\\]src$' +stderr '^go get: \.\. \('$WORK'[/\\]gopath\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' ! go get -d $WORK -stderr '^go get '$WORK': path '$WORK' is not a package in module rooted at '$WORK'[/\\]gopath[/\\]src$' +stderr '^go get: '$WORK' is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' ! go get -d ../... -stderr '^go get: pattern \.\./\.\.\.: directory prefix \.\. outside available modules$' +stderr '^go get: \.\./\.\.\. \('$WORK'[/\\]gopath([/\\]...)?\) is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' ! go get -d $WORK/... -stderr '^go get: pattern '$WORK'[/\\]\.\.\.: directory prefix \.\.[/\\]\.\. outside available modules$' +stderr '^go get: '$WORK'[/\\]\.\.\. is not within module rooted at '$WORK'[/\\]gopath[/\\]src$' # @patch and @latest within the main module refer to the current version. # The main module won't be upgraded, but missing dependencies will be added. @@ -22,21 +22,21 @@ go get -d rsc.io/x@patch grep 'rsc.io/quote v1.5.2' go.mod cp go.mod.orig go.mod -# The main module cannot be updated to @latest, which is a specific version. -! go get -d rsc.io/x@latest -stderr '^go get rsc.io/x@latest: can.t request explicit version of path in main module$' - -# The main module cannot be updated to a specific version. -! go get -d rsc.io/x@v0.1.0 -stderr '^go get rsc.io/x@v0.1.0: can.t request explicit version of path in main module$' -! go get -d rsc.io/x@v0.1.0 -stderr '^go get rsc.io/x@v0.1.0: can.t request explicit version of path in main module$' # Upgrading a package pattern not contained in the main module should not # attempt to upgrade the main module. go get -d rsc.io/quote/...@v1.5.1 grep 'rsc.io/quote v1.5.1' go.mod + +# The main module cannot be updated to a specific version. +! go get -d rsc.io/x@v0.1.0 +stderr '^go get: package rsc.io/x is in the main module, so can''t request version v0.1.0$' + +# The main module cannot be updated to @latest, which is a specific version. +! go get -d rsc.io/x/...@latest +stderr '^go get: pattern rsc.io/x/... matches package rsc.io/x in the main module, so can''t request version latest$' + -- go.mod.orig -- module rsc.io diff --git a/src/cmd/go/testdata/script/mod_get_moved.txt b/src/cmd/go/testdata/script/mod_get_moved.txt index b46ec8e8b6f..e16c1608909 100644 --- a/src/cmd/go/testdata/script/mod_get_moved.txt +++ b/src/cmd/go/testdata/script/mod_get_moved.txt @@ -28,7 +28,9 @@ go list -m all stdout 'example.com/join/subpkg v1.0.0' # A 'go get' that simultaneously upgrades away conflicting package definitions is not ambiguous. -go get example.com/join/subpkg@v1.1.0 +# (A wildcard pattern applies to both packages and modules, +# because we define wildcard matching to apply after version resolution.) +go get example.com/join/subpkg/...@v1.1.0 # A 'go get' without an upgrade should find the package. rm go.mod diff --git a/src/cmd/go/testdata/script/mod_get_newcycle.txt b/src/cmd/go/testdata/script/mod_get_newcycle.txt index 5c197bb0b82..f71620c1bcb 100644 --- a/src/cmd/go/testdata/script/mod_get_newcycle.txt +++ b/src/cmd/go/testdata/script/mod_get_newcycle.txt @@ -11,5 +11,4 @@ go mod init m cmp stderr stderr-expected -- stderr-expected -- -go get: inconsistent versions: - example.com/newcycle/a@v1.0.0 requires example.com/newcycle/a@v1.0.1 (not example.com/newcycle/a@v1.0.0) +go get: example.com/newcycle/a@v1.0.0 requires example.com/newcycle/a@v1.0.1, not example.com/newcycle/a@v1.0.0 diff --git a/src/cmd/go/testdata/script/mod_get_patch.txt b/src/cmd/go/testdata/script/mod_get_patch.txt new file mode 100644 index 00000000000..053ef621471 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_patch.txt @@ -0,0 +1,130 @@ +# This test examines the behavior of 'go get …@patch' +# See also mod_upgrade_patch.txt (focused on "-u=patch" specifically) +# and mod_get_patchmod.txt (focused on module/package ambiguities). + +cp go.mod go.mod.orig + +# example.net/b@patch refers to the patch for the version of b that was selected +# at the start of 'go get', not the version after applying other changes. + +! go get -d example.net/a@v0.2.0 example.net/b@patch +stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' +cmp go.mod go.mod.orig + + +# -u=patch changes the default version for other arguments to '@patch', +# but they continue to be resolved against the originally-selected version, +# not the updated one. +# +# TODO(#42360): Reconsider the change in defaults. + +! go get -d -u=patch example.net/a@v0.2.0 example.net/b +stderr '^go get: example.net/a@v0.2.0 requires example.net/b@v0.2.0, not example.net/b@patch \(v0.1.1\)$' +cmp go.mod go.mod.orig + + +# -u=patch refers to the patches for the selected versions of dependencies *after* +# applying other version changes, not the versions that were selected at the start. +# However, it should not patch versions determined by explicit arguments. + +go get -d -u=patch example.net/a@v0.2.0 +go list -m all +stdout '^example.net/a v0.2.0 ' +stdout '^example.net/b v0.2.1 ' + + +# "-u=patch all" should be equivalent to "all@patch", and should fail if the +# patched versions result in a higher-than-patch upgrade. + +cp go.mod.orig go.mod +! go get -u=patch all +stderr '^go get: example.net/a@v0.1.1 \(matching all@patch\) requires example.net/b@v0.2.0, not example.net/b@v0.1.1 \(matching all@patch\)$' +cmp go.mod go.mod.orig + + +# On the other hand, "-u=patch ./..." should patch-upgrade dependencies until +# they reach a fixed point, even if that results in higher-than-patch upgrades. + +go get -u=patch ./... +go list -m all +stdout '^example.net/a v0.1.1 ' +stdout '^example.net/b v0.2.1 ' + + +-- go.mod -- +module example + +go 1.16 + +require ( + example.net/a v0.1.0 + example.net/b v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a10 + example.net/a v0.1.1 => ./a11 + example.net/a v0.2.0 => ./a20 + example.net/a v0.2.1 => ./a21 + example.net/b v0.1.0 => ./b + example.net/b v0.1.1 => ./b + example.net/b v0.2.0 => ./b + example.net/b v0.2.1 => ./b + example.net/b v0.3.0 => ./b + example.net/b v0.3.1 => ./b +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a10/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a10/a.go -- +package a + +import _ "example.net/b" + +-- a11/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.2.0 // upgraded +-- a11/a.go -- +package a + +import _ "example.net/b" + +-- a20/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.2.0 +-- a20/a.go -- +package a + +import _ "example.net/b" + +-- a21/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.2.0 // not upgraded +-- a21/a.go -- +package a + +import _ "example.net/b" + +-- b/go.mod -- +module example.net/b + +go 1.16 +-- b/b.go -- +package b diff --git a/src/cmd/go/testdata/script/mod_get_patchbound.txt b/src/cmd/go/testdata/script/mod_get_patchbound.txt new file mode 100644 index 00000000000..4fd1ec53e16 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_patchbound.txt @@ -0,0 +1,84 @@ +# -u=patch will patch dependencies as far as possible, but not so far that they +# conflict with other command-line arguments. + +go list -m all +stdout '^example.net/a v0.1.0 ' +stdout '^example.net/b v0.1.0 ' + +go get -d -u=patch example.net/a@v0.2.0 +go list -m all +stdout '^example.net/a v0.2.0 ' +stdout '^example.net/b v0.1.1 ' # not v0.1.2, which requires …/a v0.3.0. + +-- go.mod -- +module example + +go 1.16 + +require ( + example.net/a v0.1.0 + example.net/b v0.1.0 // indirect +) + +replace ( + example.net/a v0.1.0 => ./a + example.net/a v0.2.0 => ./a + example.net/a v0.3.0 => ./a + example.net/b v0.1.0 => ./b10 + example.net/b v0.1.1 => ./b11 + example.net/b v0.1.2 => ./b12 +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a/a.go -- +package a + +import _ "example.net/b" + +-- b10/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.1.0 +-- b10/b.go -- +package b +-- b10/b_test.go -- +package b_test + +import _ "example.net/a" + +-- b11/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.2.0 +-- b11/b.go -- +package b +-- b11/b_test.go -- +package b_test + +import _ "example.net/a" + +-- b12/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.3.0 +-- b12/b.go -- +package b +-- b12/b_test.go -- +package b_test + +import _ "example.net/a" diff --git a/src/cmd/go/testdata/script/mod_get_patchcycle.txt b/src/cmd/go/testdata/script/mod_get_patchcycle.txt new file mode 100644 index 00000000000..d1db56f935c --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_patchcycle.txt @@ -0,0 +1,64 @@ +# If a patch of a module requires a higher version of itself, +# it should be reported as its own conflict. +# +# This case is weird and unlikely to occur often at all, but it should not +# spuriously succeed. +# (It used to print v0.1.1 but then silently upgrade to v0.2.0.) + +! go get example.net/a@patch +stderr '^go get: example.net/a@patch \(v0.1.1\) requires example.net/a@v0.2.0, not example.net/a@patch \(v0.1.1\)$' # TODO: A mention of b v0.1.0 would be nice. + +-- go.mod -- +module example + +go 1.16 + +require example.net/a v0.1.0 + +replace ( + example.net/a v0.1.0 => ./a10 + example.net/a v0.1.1 => ./a11 + example.net/a v0.2.0 => ./a20 + example.net/b v0.1.0 => ./b10 +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a10/go.mod -- +module example.net/a + +go 1.16 +-- a10/a.go -- +package a + +-- a11/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a11/a.go -- +package a + +import _ "example.net/b" + +-- a20/go.mod -- +module example.net/a + +go 1.16 +-- a20/a.go -- +package a + + +-- b10/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.2.0 +-- b10/b.go -- +package b + +import _ "example.net/a" diff --git a/src/cmd/go/testdata/script/mod_get_patchmod.txt b/src/cmd/go/testdata/script/mod_get_patchmod.txt index 0f4e2e1647f..e39d13a0f41 100644 --- a/src/cmd/go/testdata/script/mod_get_patchmod.txt +++ b/src/cmd/go/testdata/script/mod_get_patchmod.txt @@ -4,20 +4,41 @@ go get -d example.net/pkgremoved@v0.1.0 go list example.net/pkgremoved stdout '^example.net/pkgremoved' +cp go.mod go.mod.orig + + # When we resolve a new dependency on example.net/other, # it will change the meaning of the path "example.net/pkgremoved" # from a package (at v0.1.0) to only a module (at v0.2.0). # # If we simultaneously 'get' that module at the query "patch", the module should -# be upgraded to its patch release (v0.2.1) even though it no longer matches a -# package. -# -# BUG(#37438): Today, the pattern is only interpreted as its initial kind -# (a package), so the 'go get' invocation fails. +# be constrained to the latest patch of its originally-selected version (v0.1.0), +# not upgraded to the latest patch of the new transitive dependency. ! go get -d example.net/pkgremoved@patch example.net/other@v0.1.0 +stderr '^go get: example.net/other@v0.1.0 requires example.net/pkgremoved@v0.2.0, not example.net/pkgremoved@patch \(v0.1.1\)$' +cmp go.mod.orig go.mod -stderr '^go get example.net/pkgremoved@patch: module example.net/pkgremoved@latest found \(v0.2.1, replaced by ./pr2\), but does not contain package example.net/pkgremoved$' + +# However, we should be able to patch from a package to a module and vice-versa. + +# Package to module ... + +go get -d example.net/pkgremoved@v0.3.0 +go list example.net/pkgremoved +stdout 'example.net/pkgremoved' + +go get -d example.net/pkgremoved@patch +! go list example.net/pkgremoved + +# ... and module to package. + +go get -d example.net/pkgremoved@v0.4.0 +! go list example.net/pkgremoved + +go get -d example.net/pkgremoved@patch +go list example.net/pkgremoved +stdout 'example.net/pkgremoved' -- go.mod -- @@ -27,10 +48,18 @@ go 1.16 replace ( example.net/other v0.1.0 => ./other - example.net/pkgremoved v0.1.0 => ./pr1 - example.net/pkgremoved v0.1.1 => ./pr1 - example.net/pkgremoved v0.2.0 => ./pr2 - example.net/pkgremoved v0.2.1 => ./pr2 + + example.net/pkgremoved v0.1.0 => ./prpkg + example.net/pkgremoved v0.1.1 => ./prpkg + + example.net/pkgremoved v0.2.0 => ./prmod + example.net/pkgremoved v0.2.1 => ./prmod + + example.net/pkgremoved v0.3.0 => ./prpkg + example.net/pkgremoved v0.3.1 => ./prmod + + example.net/pkgremoved v0.4.0 => ./prmod + example.net/pkgremoved v0.4.1 => ./prpkg ) -- other/go.mod -- module example.net/other @@ -40,13 +69,14 @@ go 1.16 require example.net/pkgremoved v0.2.0 -- other/other.go -- package other --- pr1/go.mod -- +-- prpkg/go.mod -- module example.net/pkgremoved go 1.16 --- pr1/pkgremoved.go -- +-- prpkg/pkgremoved.go -- package pkgremoved --- pr2/go.mod -- +-- prmod/go.mod -- module example.net/pkgremoved --- pr2/README.txt -- -Package pkgremoved was removed in v0.2.0. +-- prmod/README.txt -- +Package pkgremoved was removed in v0.2.0 and v0.3.1, +and added in v0.1.0 and v0.4.1. diff --git a/src/cmd/go/testdata/script/mod_get_patterns.txt b/src/cmd/go/testdata/script/mod_get_patterns.txt index 8adc4b0c065..aee4374dc8a 100644 --- a/src/cmd/go/testdata/script/mod_get_patterns.txt +++ b/src/cmd/go/testdata/script/mod_get_patterns.txt @@ -10,21 +10,27 @@ grep 'require rsc.io/quote' go.mod cp go.mod.orig go.mod ! go get -d rsc.io/quote/x... -stderr 'go get rsc.io/quote/x...: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x...' +stderr 'go get: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x...' ! grep 'require rsc.io/quote' go.mod ! go get -d rsc.io/quote/x/... -stderr 'go get rsc.io/quote/x/...: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x/...' +stderr 'go get: module rsc.io/quote@upgrade found \(v1.5.2\), but does not contain packages matching rsc.io/quote/x/...' ! grep 'require rsc.io/quote' go.mod # If a pattern matches no packages within a module, the module should not -# be upgraded, even if the module path matches the pattern. +# be upgraded, even if the module path is a prefix of the pattern. cp go.mod.orig go.mod go mod edit -require example.com/nest@v1.0.0 go get -d example.com/nest/sub/y... grep 'example.com/nest/sub v1.0.0' go.mod grep 'example.com/nest v1.0.0' go.mod +# However, if the pattern matches the module path itself, the module +# should be upgraded even if it contains no matching packages. +go get -d example.com/n...t +grep 'example.com/nest v1.1.0' go.mod +grep 'example.com/nest/sub v1.0.0' go.mod + -- go.mod.orig -- module m diff --git a/src/cmd/go/testdata/script/mod_get_replaced.txt b/src/cmd/go/testdata/script/mod_get_replaced.txt index f8386059008..76d0793ffef 100644 --- a/src/cmd/go/testdata/script/mod_get_replaced.txt +++ b/src/cmd/go/testdata/script/mod_get_replaced.txt @@ -82,7 +82,7 @@ cp go.mod.orig go.mod ! go list example stderr '^package example is not in GOROOT \(.*\)$' ! go get -d example -stderr '^go get example: package example is not in GOROOT \(.*\)$' +stderr '^go get: malformed module path "example": missing dot in first path element$' go mod edit -replace example@v0.1.0=./example diff --git a/src/cmd/go/testdata/script/mod_get_split.txt b/src/cmd/go/testdata/script/mod_get_split.txt new file mode 100644 index 00000000000..f4e7661f9b2 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_split.txt @@ -0,0 +1,157 @@ +cp go.mod go.mod.orig + + +# 'go get' on a package already provided by the build list should update +# the module already in the build list, not fail with an ambiguous import error. + +go get -d example.net/split/nested@patch +go list -m all +stdout '^example.net/split v0.2.1 ' +! stdout '^example.net/split/nested' + +# We should get the same behavior if we use a pattern that matches only that package. + +cp go.mod.orig go.mod + +go get -d example.net/split/nested/...@patch +go list -m all +stdout '^example.net/split v0.2.1 ' +! stdout '^example.net/split/nested' + + +# If we request a version for which the package only exists in one particular module, +# we should add that one particular module but not resolve import ambiguities. +# +# In particular, if the module that previously provided the package has a +# matching version, but does not itself match the pattern and contains no +# matching packages, we should not change its version. (We should *not* downgrade +# module example.net/split to v0.1.0, despite the fact that +# example.net/split v0.2.0 currently provides the package with the requested path.) +# +# TODO(#27899): Maybe we should resolve the ambiguities by upgrading. + +cp go.mod.orig go.mod + +! go get -d example.net/split/nested@v0.1.0 +stderr '^example.net/split/nested: ambiguous import: found package example.net/split/nested in multiple modules:\n\texample.net/split v0.2.0 \(.*split.2[/\\]nested\)\n\texample.net/split/nested v0.1.0 \(.*nested.1\)$' + +# A wildcard that matches packages in some module at its selected version +# but not at the requested version should fail. +# +# We can't set the module to the selected version, because that version doesn't +# even match the query: if we ran the same query twice, we wouldn't consider the +# module to match the wildcard during the second call, so why should we consider +# it to match during the first one? ('go get' should be idempotent, and if we +# did that then it would not be.) +# +# But we also can't leave it where it is: the user requested that we set everything +# matching the pattern to the given version, and right now we have packages +# that match the pattern but *not* the version. +# +# That only leaves two options: we can set the module to an arbitrary version +# (perhaps 'latest' or 'none'), or we can report an error and the let the user +# disambiguate. We would rather not choose arbitrarily, so we do the latter. +# +# TODO(#27899): Should we instead upgrade or downgrade to an arbirary version? + +! go get -d example.net/split/nested/...@v0.1.0 +stderr '^go get: example.net/split/nested/\.\.\.@v0.1.0 matches packages in example.net/split@v0.2.0 but not example.net/split@v0.1.0: specify a different version for module example.net/split$' + +cmp go.mod go.mod.orig + + +# If another argument resolves the ambiguity, we should be ok again. + +go get -d example.net/split@none example.net/split/nested@v0.1.0 +go list -m all +! stdout '^example.net/split ' +stdout '^example.net/split/nested v0.1.0 ' + +cp go.mod.orig go.mod + +go get -d example.net/split@v0.3.0 example.net/split/nested@v0.1.0 +go list -m all +stdout '^example.net/split v0.3.0 ' +stdout '^example.net/split/nested v0.1.0 ' + + +# If a pattern applies to modules and to packages, we should set all matching +# modules to the version indicated by the pattern, and also resolve packages +# to match the pattern if possible. + +cp go.mod.orig go.mod +go get -d example.net/split/nested@v0.0.0 + +go get -d example.net/...@v0.1.0 +go list -m all +stdout '^example.net/split v0.1.0 ' +stdout '^example.net/split/nested v0.1.0 ' + +go get -d example.net/... +go list -m all +stdout '^example.net/split v0.3.0 ' +stdout '^example.net/split/nested v0.2.0 ' + + +# @none applies to all matching module paths, +# regardless of whether they contain any packages. + +go get -d example.net/...@none +go list -m all +! stdout '^example.net' + +# Starting from no dependencies, a wildcard can resolve to an empty module with +# the same prefix even if it contains no packages. + +go get -d example.net/...@none +go get -d example.net/split/...@v0.1.0 +go list -m all +stdout '^example.net/split v0.1.0 ' + + +-- go.mod -- +module m + +go 1.16 + +require example.net/split v0.2.0 + +replace ( + example.net/split v0.1.0 => ./split.1 + example.net/split v0.2.0 => ./split.2 + example.net/split v0.2.1 => ./split.2 + example.net/split v0.3.0 => ./split.3 + example.net/split/nested v0.0.0 => ./nested.0 + example.net/split/nested v0.1.0 => ./nested.1 + example.net/split/nested v0.2.0 => ./nested.2 +) +-- split.1/go.mod -- +module example.net/split + +go 1.16 +-- split.2/go.mod -- +module example.net/split + +go 1.16 +-- split.2/nested/nested.go -- +package nested +-- split.3/go.mod -- +module example.net/split + +go 1.16 +-- nested.0/go.mod -- +module example.net/split/nested + +go 1.16 +-- nested.1/go.mod -- +module example.net/split/nested + +go 1.16 +-- nested.1/nested.go -- +package nested +-- nested.2/go.mod -- +module example.net/split/nested + +go 1.16 +-- nested.2/nested.go -- +package nested diff --git a/src/cmd/go/testdata/script/mod_get_wild.txt b/src/cmd/go/testdata/script/mod_get_wild.txt new file mode 100644 index 00000000000..78c645c6b9f --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_wild.txt @@ -0,0 +1,95 @@ +# This test covers a crazy edge-case involving wildcards and multiple passes of +# patch-upgrades, but if we get it right we probably get many other edge-cases +# right too. + +go list -m all +stdout '^example.net/a v0.1.0 ' +! stdout '^example.net/b ' + + +# Requesting pattern example.../b by itself fails: there is no such module +# already in the build list, and the wildcard in the first element prevents us +# from attempting to resolve a new module whose path is a prefix of the pattern. + +! go get -d -u=patch example.../b@upgrade +stderr '^go get: no modules to query for example\.\.\./b@upgrade because first path element contains a wildcard$' + + +# Patching . causes a patch to example.net/a, which introduces a new match +# for example.net/b/..., which is itself patched and causes another upgrade to +# example.net/a, which is then patched again. + +go get -d -u=patch . example.../b@upgrade +go list -m all +stdout '^example.net/a v0.2.1 ' # upgraded by dependency of b and -u=patch +stdout '^example.net/b v0.2.0 ' # introduced by patch of a and upgraded by wildcard + + +-- go.mod -- +module example + +go 1.16 + +require example.net/a v0.1.0 + +replace ( + example.net/a v0.1.0 => ./a10 + example.net/a v0.1.1 => ./a11 + example.net/a v0.2.0 => ./a20 + example.net/a v0.2.1 => ./a20 + example.net/b v0.1.0 => ./b1 + example.net/b v0.1.1 => ./b1 + example.net/b v0.2.0 => ./b2 +) +-- example.go -- +package example + +import _ "example.net/a" + +-- a10/go.mod -- +module example.net/a + +go 1.16 +-- a10/a.go -- +package a + +-- a11/go.mod -- +module example.net/a + +go 1.16 + +require example.net/b v0.1.0 +-- a11/a.go -- +package a +-- a11/unimported/unimported.go -- +package unimported + +import _ "example.net/b" + + +-- a20/go.mod -- +module example.net/a + +go 1.16 +-- a20/a.go -- +package a + +-- b1/go.mod -- +module example.net/b + +go 1.16 +-- b1/b.go -- +package b + +-- b2/go.mod -- +module example.net/b + +go 1.16 + +require example.net/a v0.2.0 +-- b2/b.go -- +package b +-- b2/b_test.go -- +package b_test + +import _ "example.net/a" diff --git a/src/cmd/go/testdata/script/mod_invalid_version.txt b/src/cmd/go/testdata/script/mod_invalid_version.txt index f9dfdd63462..43b95643561 100644 --- a/src/cmd/go/testdata/script/mod_invalid_version.txt +++ b/src/cmd/go/testdata/script/mod_invalid_version.txt @@ -222,7 +222,7 @@ stdout 'github.com/pierrec/lz4 v2.0.5\+incompatible' # not resolve to a pseudo-version with a different major version. cp go.mod.orig go.mod ! go get -d github.com/pierrec/lz4@v2.0.8 -stderr 'go get github.com/pierrec/lz4@v2.0.8: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2' +stderr 'go get: github.com/pierrec/lz4@v2.0.8: invalid version: module contains a go.mod file, so major version must be compatible: should be v0 or v1, not v2' # An invalid +incompatible suffix for a canonical version should error out, # not resolve to a pseudo-version. diff --git a/src/cmd/go/testdata/script/mod_load_badchain.txt b/src/cmd/go/testdata/script/mod_load_badchain.txt index a71c4a849e5..c0c382bfa63 100644 --- a/src/cmd/go/testdata/script/mod_load_badchain.txt +++ b/src/cmd/go/testdata/script/mod_load_badchain.txt @@ -69,14 +69,13 @@ import ( func Test(t *testing.T) {} -- update-main-expected -- -go: example.com/badchain/c upgrade => v1.1.0 go get: example.com/badchain/c@v1.0.0 updating to example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c but was required as: example.com/badchain/c -- update-a-expected -- -go: example.com/badchain/a upgrade => v1.1.0 -go get: example.com/badchain/a@v1.1.0 requires +go get: example.com/badchain/a@v1.0.0 updating to + example.com/badchain/a@v1.1.0 requires example.com/badchain/b@v1.1.0 requires example.com/badchain/c@v1.1.0: parsing go.mod: module declares its path as: badchain.example.com/c diff --git a/src/cmd/go/testdata/script/mod_outside.txt b/src/cmd/go/testdata/script/mod_outside.txt index d969fce145e..28379ab40d8 100644 --- a/src/cmd/go/testdata/script/mod_outside.txt +++ b/src/cmd/go/testdata/script/mod_outside.txt @@ -130,12 +130,12 @@ stderr 'cannot find main module' # 'go get -u all' upgrades the transitive import graph of the main module, # which is empty. ! go get -u all -stderr 'go get all: cannot match "all": working directory is not part of a module' +stderr 'go get: cannot match "all": working directory is not part of a module' # 'go get' should check the proposed module graph for consistency, # even though we won't write it anywhere. ! go get -d example.com/printversion@v1.0.0 example.com/version@none -stderr 'inconsistent versions' +stderr '^go get: example.com/printversion@v1.0.0 requires example.com/version@v1.0.0, not example.com/version@none$' # 'go get -d' should download and extract the source code needed to build the requested version. rm -r $GOPATH/pkg/mod/example.com diff --git a/src/cmd/go/testdata/script/mod_query_empty.txt b/src/cmd/go/testdata/script/mod_query_empty.txt index a07a07c4bcc..1f13d7ad693 100644 --- a/src/cmd/go/testdata/script/mod_query_empty.txt +++ b/src/cmd/go/testdata/script/mod_query_empty.txt @@ -8,7 +8,7 @@ go mod download example.com/join@v1.1.0 env GOPROXY=file:///$WORK/badproxy cp go.mod.orig go.mod ! go get -d example.com/join/subpkg -stderr 'go get example.com/join/subpkg: example.com/join/subpkg@v0.0.0-20190624000000-123456abcdef: .*' +stderr 'go get: example.com/join/subpkg@v0.0.0-20190624000000-123456abcdef: .*' # If @v/list is empty, the 'go' command should still try to resolve # other module paths. @@ -40,7 +40,7 @@ env GOPROXY=file:///$WORK/gatekeeper chmod 0000 $WORK/gatekeeper/example.com/join/subpkg/@latest cp go.mod.orig go.mod ! go get -d example.com/join/subpkg -stderr 'go get example.com/join/subpkg: module example.com/join/subpkg: (invalid response from proxy ".+": json: invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' +stderr 'go get: module example.com/join/subpkg: (invalid response from proxy ".+": json: invalid character .+|reading file://.*/gatekeeper/example.com/join/subpkg/@latest: .+)' -- go.mod.orig -- module example.com/othermodule diff --git a/src/cmd/go/testdata/script/mod_query_exclude.txt b/src/cmd/go/testdata/script/mod_query_exclude.txt index 742c6f17e34..b0019694119 100644 --- a/src/cmd/go/testdata/script/mod_query_exclude.txt +++ b/src/cmd/go/testdata/script/mod_query_exclude.txt @@ -19,7 +19,7 @@ stdout '^rsc.io/quote v1.5.1$' # get excluded version cp go.exclude.mod go.exclude.mod.orig ! go get -modfile=go.exclude.mod -d rsc.io/quote@v1.5.0 -stderr '^go get rsc.io/quote@v1.5.0: rsc.io/quote@v1.5.0: excluded by go.mod$' +stderr '^go get: rsc.io/quote@v1.5.0: excluded by go.mod$' # get non-excluded version cp go.exclude.mod.orig go.exclude.mod diff --git a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt index 93609f36c95..eb00e8405c0 100644 --- a/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt +++ b/src/cmd/go/testdata/script/mod_retract_pseudo_base.txt @@ -29,7 +29,7 @@ go list -m vcs-test.golang.org/git/retract-pseudo.git stdout '^vcs-test.golang.org/git/retract-pseudo.git v1.0.1-0.20201009173747-713affd19d7b$' ! go get -d vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371 -stderr '^go get vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$' +stderr '^go get: vcs-test.golang.org/git/retract-pseudo.git@v1.0.1-0.20201009173747-64c061ed4371: invalid pseudo-version: tag \(v1.0.0\) found on revision 64c061ed4371 is already canonical, so should not be replaced with a pseudo-version derived from that tag$' -- retract-pseudo.sh -- #!/bin/bash diff --git a/src/cmd/go/testdata/script/mod_sumdb.txt b/src/cmd/go/testdata/script/mod_sumdb.txt index fb320a557ab..9a688e1461c 100644 --- a/src/cmd/go/testdata/script/mod_sumdb.txt +++ b/src/cmd/go/testdata/script/mod_sumdb.txt @@ -9,7 +9,7 @@ env dbname=localhost.localdev/sumdb cp go.mod.orig go.mod env GOSUMDB=$sumdb' '$proxy/sumdb-wrong ! go get -d rsc.io/quote -stderr 'go get rsc.io/quote: rsc.io/quote@v1.5.2: verifying module: checksum mismatch' +stderr 'go get: rsc.io/quote@v1.5.2: verifying module: checksum mismatch' stderr 'downloaded: h1:3fEy' stderr 'localhost.localdev/sumdb: h1:wrong' stderr 'SECURITY ERROR\nThis download does NOT match the one reported by the checksum server.' diff --git a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt index 6108c0a5d36..22fcbf3de84 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_file_path.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_file_path.txt @@ -13,7 +13,7 @@ env GOPATH=$WORK/gopath1 [windows] env GOPROXY=file:///$WORK/sumproxy,https://proxy.golang.org [!windows] env GOPROXY=file://$WORK/sumproxy,https://proxy.golang.org ! go get -d golang.org/x/text@v0.3.2 -stderr '^go get golang.org/x/text@v0.3.2: golang.org/x/text@v0.3.2: verifying module: golang.org/x/text@v0.3.2: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/text@v0.3.2: (no such file or directory|.*cannot find the path specified.*)' +stderr '^go get: golang.org/x/text@v0.3.2: verifying module: golang.org/x/text@v0.3.2: reading file://.*/sumdb/sum.golang.org/lookup/golang.org/x/text@v0.3.2: (no such file or directory|.*cannot find the path specified.*)' # If the proxy does not claim to support the database, # checksum verification should fall through to the next proxy, diff --git a/src/cmd/go/testdata/script/mod_upgrade_patch.txt b/src/cmd/go/testdata/script/mod_upgrade_patch.txt index 1ef25b9aef5..8b34f8bf27d 100644 --- a/src/cmd/go/testdata/script/mod_upgrade_patch.txt +++ b/src/cmd/go/testdata/script/mod_upgrade_patch.txt @@ -9,6 +9,11 @@ stdout '^patch.example.com/direct v1.0.0' stdout '^patch.example.com/indirect v1.0.0' ! stdout '^patch.example.com/depofdirectpatch' +# @patch should be rejected for modules not already in the build list. +! go get -d patch.example.com/depofdirectpatch@patch +stderr '^go get: can''t query version "patch" of module patch.example.com/depofdirectpatch: no existing version is required$' +cmp go.mod.orig go.mod + # get -u=patch, with no arguments, should patch-update all dependencies # of the package in the current directory, pulling in transitive dependencies # and also patching those. @@ -19,7 +24,7 @@ stdout '^patch.example.com/direct v1.0.1' stdout '^patch.example.com/indirect v1.0.1' stdout '^patch.example.com/depofdirectpatch v1.0.0' -# 'get all@patch' should be equivalent to 'get -u=patch all' +# 'get all@patch' should patch the modules that provide packages in 'all'. cp go.mod.orig go.mod go get -d all@patch go list -m all @@ -27,6 +32,15 @@ stdout '^patch.example.com/direct v1.0.1' stdout '^patch.example.com/indirect v1.0.1' stdout '^patch.example.com/depofdirectpatch v1.0.0' +# ...but 'all@patch' should fail if any of the affected modules do not already +# have a selected version. +cp go.mod.orig go.mod +go mod edit -droprequire=patch.example.com/direct +cp go.mod go.mod.dropped +! go get -d all@patch +stderr '^go get all@patch: can''t query version "patch" of module patch.example.com/direct: no existing version is required$' +cmp go.mod.dropped go.mod + # Requesting the direct dependency with -u=patch but without an explicit version # should patch-update it and its dependencies. cp go.mod.orig go.mod @@ -69,10 +83,10 @@ stdout '^patch.example.com/direct v1.1.0' stdout '^patch.example.com/indirect v1.0.1' ! stdout '^patch.example.com/depofdirectpatch' -# Standard-library packages cannot be upgraded explicitly. +# Standard library packages cannot be upgraded explicitly. cp go.mod.orig go.mod ! go get cmd/vet@patch -stderr 'cannot use pattern .* with explicit version' +stderr 'go get: can''t request explicit version "patch" of standard library package cmd/vet$' # However, standard-library packages without explicit versions are fine. go get -d -u=patch -d cmd/go @@ -85,6 +99,7 @@ go get -d example.com/noroot@patch go list -m all stdout '^example.com/noroot v1.0.1$' + -- go.mod -- module x From 370682ae98d7edc3ce9772d6d1d746df93ba9e6d Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 2 Nov 2020 16:34:51 -0500 Subject: [PATCH 365/403] runtime: disable preemption in startm startm contains a critical section from when it takes ownership of a P (either on function entry or call to pidleput) until it wakes the M receiving the P. If preempted in this critical section, the owned P is left in limbo. If preempted for a GC stop, there will be nothing to stop the owned P and STW will wait forever. golang.org/cl/232298 introduced the first call to startm that is not on the system stack (via a wakep call), introducing the possibility of preemption. Disable preemption in startm to ensure this remains non-preemptible. Since we're not always on the system stack anymore, we also need to be careful in allocm. Updates #42237 Change-Id: Icb95eef9eb262121856485316098331beea045da Reviewed-on: https://go-review.googlesource.com/c/go/+/267257 Reviewed-by: Austin Clements Reviewed-by: Michael Knyszek Trust: Michael Pratt --- src/runtime/proc.go | 50 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 87949a26949..0319de5fde8 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1665,7 +1665,12 @@ func allocm(_p_ *p, fn func(), id int64) *m { freem = next continue } - stackfree(freem.g0.stack) + // stackfree must be on the system stack, but allocm is + // reachable off the system stack transitively from + // startm. + systemstack(func() { + stackfree(freem.g0.stack) + }) freem = freem.freelink } sched.freem = newList @@ -2192,8 +2197,30 @@ func mspinning() { // May run with m.p==nil, so write barriers are not allowed. // If spinning is set, the caller has incremented nmspinning and startm will // either decrement nmspinning or set m.spinning in the newly started M. +// +// Callers passing a non-nil P must call from a non-preemptible context. See +// comment on acquirem below. +// +// Must not have write barriers because this may be called without a P. //go:nowritebarrierrec func startm(_p_ *p, spinning bool) { + // Disable preemption. + // + // Every owned P must have an owner that will eventually stop it in the + // event of a GC stop request. startm takes transient ownership of a P + // (either from argument or pidleget below) and transfers ownership to + // a started M, which will be responsible for performing the stop. + // + // Preemption must be disabled during this transient ownership, + // otherwise the P this is running on may enter GC stop while still + // holding the transient P, leaving that P in limbo and deadlocking the + // STW. + // + // Callers passing a non-nil P must already be in non-preemptible + // context, otherwise such preemption could occur on function entry to + // startm. Callers passing a nil P may be preemptible, so we must + // disable preemption before acquiring a P from pidleget below. + mp := acquirem() lock(&sched.lock) if _p_ == nil { _p_ = pidleget() @@ -2206,11 +2233,12 @@ func startm(_p_ *p, spinning bool) { throw("startm: negative nmspinning") } } + releasem(mp) return } } - mp := mget() - if mp == nil { + nmp := mget() + if nmp == nil { // No M is available, we must drop sched.lock and call newm. // However, we already own a P to assign to the M. // @@ -2232,22 +2260,28 @@ func startm(_p_ *p, spinning bool) { fn = mspinning } newm(fn, _p_, id) + // Ownership transfer of _p_ committed by start in newm. + // Preemption is now safe. + releasem(mp) return } unlock(&sched.lock) - if mp.spinning { + if nmp.spinning { throw("startm: m is spinning") } - if mp.nextp != 0 { + if nmp.nextp != 0 { throw("startm: m has p") } if spinning && !runqempty(_p_) { throw("startm: p has runnable gs") } // The caller incremented nmspinning, so set m.spinning in the new M. - mp.spinning = spinning - mp.nextp.set(_p_) - notewakeup(&mp.park) + nmp.spinning = spinning + nmp.nextp.set(_p_) + notewakeup(&nmp.park) + // Ownership transfer of _p_ committed by wakeup. Preemption is now + // safe. + releasem(mp) } // Hands off P from syscall or locked M. From d508d86cf12a3c4ee139d31f5f5c9e5e53566ecc Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 3 Nov 2020 13:12:19 -0500 Subject: [PATCH 366/403] cmd/go: account for flags when parsing regexps in TestScript Test script expects the regexp argument for stdout, stderr, and cmp to be the first argument after the command, but that might not be the case if the -q or -count flags are provided. Treat the first argument after a flag as a regexp instead. For #39958 Change-Id: I369926109ec10cca8b2c3baca27e7a3f7baf364b Reviewed-on: https://go-review.googlesource.com/c/go/+/267877 Trust: Michael Matloob Run-TryBot: Michael Matloob TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- src/cmd/go/script_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index d81f299c3cc..e301f2fb069 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -1255,7 +1255,12 @@ func (ts *testScript) parse(line string) command { if cmd.name != "" { cmd.args = append(cmd.args, arg) - isRegexp = false // Commands take only one regexp argument, so no subsequent args are regexps. + // Commands take only one regexp argument (after the optional flags), + // so no subsequent args are regexps. Liberally assume an argument that + // starts with a '-' is a flag. + if len(arg) == 0 || arg[0] != '-' { + isRegexp = false + } return } From 2822bae168fa5d7b14c87d2b2ee22cb85fc90cce Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Mon, 26 Oct 2020 22:44:54 -0400 Subject: [PATCH 367/403] go/types: add unexported start and end positions to type checker errors Tools often need to associate errors not with a single position, but with a span of source code. For example, gopls currently estimates diagnostic spans using heuristics to expand the positions reported by the type checker to surrounding source code. Unfortunately this is often inaccurate. This CL lays the groundwork to solve this within go/types by adding a start and end position to type checker errors. This is an experimental API, both because we are uncertain of the ideal representation for these spans and because their initial positioning is naive. In most cases this CL simply expands errors to the surrounding ast.Node being typechecked, if available. This might not be the best error span to present to the user. For these reasons the API is unexported -- gopls can read these positions using reflection, allowing us to gain experience and improve them during the next development cycle. For golang/go#42290 Change-Id: I39a04d70ea2bb2134b4d4c937f32b2ddb4456430 Reviewed-on: https://go-review.googlesource.com/c/go/+/265250 Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer Trust: Robert Findley Trust: Robert Griesemer --- src/go/types/api.go | 4 +- src/go/types/assignments.go | 28 ++++---- src/go/types/builtins.go | 50 +++++++------- src/go/types/call.go | 34 +++++----- src/go/types/check.go | 16 ++--- src/go/types/conversions.go | 2 +- src/go/types/decl.go | 26 ++++---- src/go/types/errors.go | 117 +++++++++++++++++++++++++-------- src/go/types/expr.go | 126 +++++++++++++++++++----------------- src/go/types/initorder.go | 6 +- src/go/types/labels.go | 14 ++-- src/go/types/operand.go | 4 +- src/go/types/resolver.go | 34 +++++----- src/go/types/stmt.go | 104 ++++++++++++++--------------- src/go/types/typexpr.go | 70 ++++++++++---------- 15 files changed, 354 insertions(+), 281 deletions(-) diff --git a/src/go/types/api.go b/src/go/types/api.go index abe1f9f8625..d6259598172 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -49,7 +49,9 @@ type Error struct { // to preview this feature may read go116code using reflection (see // errorcodes_test.go), but beware that there is no guarantee of future // compatibility. - go116code errorCode + go116code errorCode + go116start token.Pos + go116end token.Pos } // Error returns an error string formatted as follows: diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index d895c6f099a..616564b567d 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -38,7 +38,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // complex, or string constant." if T == nil || IsInterface(T) { if T == nil && x.typ == Typ[UntypedNil] { - check.errorf(x.pos(), _UntypedNil, "use of untyped nil in %s", context) + check.errorf(x, _UntypedNil, "use of untyped nil in %s", context) x.mode = invalid return } @@ -59,7 +59,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { code = ierr.go116code } } - check.error(x.pos(), code, msg) + check.error(x, code, msg) x.mode = invalid return } @@ -76,9 +76,9 @@ func (check *Checker) assignment(x *operand, T Type, context string) { reason := "" if ok, code := x.assignableTo(check, T, &reason); !ok { if reason != "" { - check.errorf(x.pos(), code, "cannot use %s as %s value in %s: %s", x, T, context, reason) + check.errorf(x, code, "cannot use %s as %s value in %s: %s", x, T, context, reason) } else { - check.errorf(x.pos(), code, "cannot use %s as %s value in %s", x, T, context) + check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) } x.mode = invalid } @@ -94,7 +94,7 @@ func (check *Checker) initConst(lhs *Const, x *operand) { // rhs must be a constant if x.mode != constant_ { - check.errorf(x.pos(), _InvalidConstInit, "%s is not constant", x) + check.errorf(x, _InvalidConstInit, "%s is not constant", x) if lhs.typ == nil { lhs.typ = Typ[Invalid] } @@ -129,7 +129,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) Type { if isUntyped(typ) { // convert untyped types to default types if typ == Typ[UntypedNil] { - check.errorf(x.pos(), _UntypedNil, "use of untyped nil in %s", context) + check.errorf(x, _UntypedNil, "use of untyped nil in %s", context) lhs.typ = Typ[Invalid] return nil } @@ -203,11 +203,11 @@ func (check *Checker) assignVar(lhs ast.Expr, x *operand) Type { var op operand check.expr(&op, sel.X) if op.mode == mapindex { - check.errorf(z.pos(), _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr)) + check.errorf(&z, _UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(z.expr)) return nil } } - check.errorf(z.pos(), _UnassignableOperand, "cannot assign to %s", &z) + check.errorf(&z, _UnassignableOperand, "cannot assign to %s", &z) return nil } @@ -236,10 +236,10 @@ func (check *Checker) initVars(lhs []*Var, rhs []ast.Expr, returnPos token.Pos) } check.useGetter(get, r) if returnPos.IsValid() { - check.errorf(returnPos, _WrongResultCount, "wrong number of return values (want %d, got %d)", l, r) + check.errorf(atPos(returnPos), _WrongResultCount, "wrong number of return values (want %d, got %d)", l, r) return } - check.errorf(rhs[0].Pos(), _WrongAssignCount, "cannot initialize %d variables with %d values", l, r) + check.errorf(rhs[0], _WrongAssignCount, "cannot initialize %d variables with %d values", l, r) return } @@ -274,7 +274,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) { } if l != r { check.useGetter(get, r) - check.errorf(rhs[0].Pos(), _WrongAssignCount, "cannot assign %d values to %d variables", r, l) + check.errorf(rhs[0], _WrongAssignCount, "cannot assign %d values to %d variables", r, l) return } @@ -295,7 +295,7 @@ func (check *Checker) assignVars(lhs, rhs []ast.Expr) { } } -func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) { +func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) { top := len(check.delayed) scope := check.scope @@ -315,7 +315,7 @@ func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) { if alt, _ := alt.(*Var); alt != nil { obj = alt } else { - check.errorf(lhs.Pos(), _UnassignableOperand, "cannot assign to %s", lhs) + check.errorf(lhs, _UnassignableOperand, "cannot assign to %s", lhs) } check.recordUse(ident, alt) } else { @@ -328,7 +328,7 @@ func (check *Checker) shortVarDecl(pos token.Pos, lhs, rhs []ast.Expr) { } } else { check.useLHS(lhs) - check.invalidAST(lhs.Pos(), "cannot declare %s", lhs) + check.invalidAST(lhs, "cannot declare %s", lhs) } if obj == nil { obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go index 960d1f28bc2..fd35f786769 100644 --- a/src/go/types/builtins.go +++ b/src/go/types/builtins.go @@ -21,7 +21,9 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // append is the only built-in that permits the use of ... for the last argument bin := predeclaredFuncs[id] if call.Ellipsis.IsValid() && id != _Append { - check.invalidOp(call.Ellipsis, _InvalidDotDotDot, "invalid use of ... with built-in %s", bin.name) + check.invalidOp(atPos(call.Ellipsis), + _InvalidDotDotDot, + "invalid use of ... with built-in %s", bin.name) check.use(call.Args...) return } @@ -68,7 +70,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b msg = "too many" } if msg != "" { - check.invalidOp(call.Rparen, _WrongArgCount, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs) + check.invalidOp(inNode(call, call.Rparen), _WrongArgCount, "%s arguments for %s (expected %d, found %d)", msg, call, bin.nargs, nargs) return } } @@ -85,7 +87,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if s, _ := S.Underlying().(*Slice); s != nil { T = s.elem } else { - check.invalidArg(x.pos(), _InvalidAppend, "%s is not a slice", x) + check.invalidArg(x, _InvalidAppend, "%s is not a slice", x) return } @@ -181,7 +183,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if id == _Len { code = _InvalidLen } - check.invalidArg(x.pos(), code, "%s for %s", x, bin.name) + check.invalidArg(x, code, "%s for %s", x, bin.name) return } @@ -196,11 +198,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // close(c) c, _ := x.typ.Underlying().(*Chan) if c == nil { - check.invalidArg(x.pos(), _InvalidClose, "%s is not a channel", x) + check.invalidArg(x, _InvalidClose, "%s is not a channel", x) return } if c.dir == RecvOnly { - check.invalidArg(x.pos(), _InvalidClose, "%s must not be a receive-only channel", x) + check.invalidArg(x, _InvalidClose, "%s must not be a receive-only channel", x) return } @@ -264,13 +266,13 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // both argument types must be identical if !check.identical(x.typ, y.typ) { - check.invalidArg(x.pos(), _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ) + check.invalidArg(x, _InvalidComplex, "mismatched types %s and %s", x.typ, y.typ) return } // the argument types must be of floating-point type if !isFloat(x.typ) { - check.invalidArg(x.pos(), _InvalidComplex, "arguments have type %s, expected floating-point", x.typ) + check.invalidArg(x, _InvalidComplex, "arguments have type %s, expected floating-point", x.typ) return } @@ -324,12 +326,12 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } if dst == nil || src == nil { - check.invalidArg(x.pos(), _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) + check.invalidArg(x, _InvalidCopy, "copy expects slice arguments; found %s and %s", x, &y) return } if !check.identical(dst, src) { - check.invalidArg(x.pos(), _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) + check.invalidArg(x, _InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, &y, dst, src) return } @@ -343,7 +345,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // delete(m, k) m, _ := x.typ.Underlying().(*Map) if m == nil { - check.invalidArg(x.pos(), _InvalidDelete, "%s is not a map", x) + check.invalidArg(x, _InvalidDelete, "%s is not a map", x) return } arg(x, 1) // k @@ -352,7 +354,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } if ok, code := x.assignableTo(check, m.key, nil); !ok { - check.invalidArg(x.pos(), code, "%s is not assignable to %s", x, m.key) + check.invalidArg(x, code, "%s is not assignable to %s", x, m.key) return } @@ -392,7 +394,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b if id == _Real { code = _InvalidReal } - check.invalidArg(x.pos(), code, "argument has type %s, expected complex type", x.typ) + check.invalidArg(x, code, "argument has type %s, expected complex type", x.typ) return } @@ -444,11 +446,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b case *Map, *Chan: min = 1 default: - check.invalidArg(arg0.Pos(), _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) + check.invalidArg(arg0, _InvalidMake, "cannot make %s; type must be slice, map, or channel", arg0) return } if nargs < min || min+1 < nargs { - check.errorf(call.Pos(), _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs) + check.errorf(call, _WrongArgCount, "%v expects %d or %d arguments; found %d", call, min, min+1, nargs) return } types := []Type{T} @@ -461,7 +463,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b } } if len(sizes) == 2 && sizes[0] > sizes[1] { - check.invalidArg(call.Args[1].Pos(), _SwappedMakeArgs, "length and capacity swapped") + check.invalidArg(call.Args[1], _SwappedMakeArgs, "length and capacity swapped") // safe to continue } x.mode = value @@ -559,7 +561,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b arg0 := call.Args[0] selx, _ := unparen(arg0).(*ast.SelectorExpr) if selx == nil { - check.invalidArg(arg0.Pos(), _BadOffsetofSyntax, "%s is not a selector expression", arg0) + check.invalidArg(arg0, _BadOffsetofSyntax, "%s is not a selector expression", arg0) check.use(arg0) return } @@ -574,18 +576,18 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel) switch obj.(type) { case nil: - check.invalidArg(x.pos(), _MissingFieldOrMethod, "%s has no single field %s", base, sel) + check.invalidArg(x, _MissingFieldOrMethod, "%s has no single field %s", base, sel) return case *Func: // TODO(gri) Using derefStructPtr may result in methods being found // that don't actually exist. An error either way, but the error // message is confusing. See: https://play.golang.org/p/al75v23kUy , // but go/types reports: "invalid argument: x.m is a method value". - check.invalidArg(arg0.Pos(), _InvalidOffsetof, "%s is a method value", arg0) + check.invalidArg(arg0, _InvalidOffsetof, "%s is a method value", arg0) return } if indirect { - check.invalidArg(x.pos(), _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base) + check.invalidArg(x, _InvalidOffsetof, "field %s is embedded via a pointer in %s", sel, base) return } @@ -615,15 +617,15 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b // The result of assert is the value of pred if there is no error. // Note: assert is only available in self-test mode. if x.mode != constant_ || !isBoolean(x.typ) { - check.invalidArg(x.pos(), _Test, "%s is not a boolean constant", x) + check.invalidArg(x, _Test, "%s is not a boolean constant", x) return } if x.val.Kind() != constant.Bool { - check.errorf(x.pos(), _Test, "internal error: value of %s should be a boolean constant", x) + check.errorf(x, _Test, "internal error: value of %s should be a boolean constant", x) return } if !constant.BoolVal(x.val) { - check.errorf(call.Pos(), _Test, "%v failed", call) + check.errorf(call, _Test, "%v failed", call) // compile-time assertion failure - safe to continue } // result is constant - no need to record signature @@ -643,7 +645,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b x1 := x for _, arg := range call.Args { check.rawExpr(x1, arg, nil) // permit trace for types, e.g.: new(trace(T)) - check.dump("%v: %s", x1.pos(), x1) + check.dump("%v: %s", x1.Pos(), x1) x1 = &t // use incoming x only for first argument } // trace is only available in test mode - no need to record signature diff --git a/src/go/types/call.go b/src/go/types/call.go index fd0cfe3b28b..992598d08ce 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -29,7 +29,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { x.mode = invalid switch n := len(e.Args); n { case 0: - check.errorf(e.Rparen, _WrongArgCount, "missing argument in conversion to %s", T) + check.errorf(inNode(e, e.Rparen), _WrongArgCount, "missing argument in conversion to %s", T) case 1: check.expr(x, e.Args[0]) if x.mode != invalid { @@ -37,7 +37,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { } default: check.use(e.Args...) - check.errorf(e.Args[n-1].Pos(), _WrongArgCount, "too many arguments in conversion to %s", T) + check.errorf(e.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T) } x.expr = e return conversion @@ -60,7 +60,7 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { sig, _ := x.typ.Underlying().(*Signature) if sig == nil { - check.invalidOp(x.pos(), _InvalidCall, "cannot call non-function %s", x) + check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x) x.mode = invalid x.expr = e return statement @@ -231,13 +231,13 @@ func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, if call.Ellipsis.IsValid() { // last argument is of the form x... if !sig.variadic { - check.errorf(call.Ellipsis, _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun) + check.errorf(atPos(call.Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", call.Fun) check.useGetter(arg, n) return } if len(call.Args) == 1 && n > 1 { // f()... is not permitted if f() is multi-valued - check.errorf(call.Ellipsis, _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", n, call.Args[0]) + check.errorf(atPos(call.Ellipsis), _InvalidDotDotDotOperand, "cannot use ... with %d-valued %s", n, call.Args[0]) check.useGetter(arg, n) return } @@ -263,7 +263,7 @@ func (check *Checker) arguments(x *operand, call *ast.CallExpr, sig *Signature, n++ } if n < sig.params.Len() { - check.errorf(call.Rparen, _WrongArgCount, "too few arguments in call to %s", call.Fun) + check.errorf(inNode(call, call.Rparen), _WrongArgCount, "too few arguments in call to %s", call.Fun) // ok to continue } } @@ -291,18 +291,18 @@ func (check *Checker) argument(sig *Signature, i int, x *operand, ellipsis token } } default: - check.errorf(x.pos(), _WrongArgCount, "too many arguments") + check.errorf(x, _WrongArgCount, "too many arguments") return } if ellipsis.IsValid() { if i != n-1 { - check.errorf(ellipsis, _MisplacedDotDotDot, "can only use ... with matching parameter") + check.errorf(atPos(ellipsis), _MisplacedDotDotDot, "can only use ... with matching parameter") return } // argument is of the form x... and x is single-valued if _, ok := x.typ.Underlying().(*Slice); !ok && x.typ != Typ[UntypedNil] { // see issue #18268 - check.errorf(x.pos(), _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", x, typ) + check.errorf(x, _InvalidDotDotDotOperand, "cannot use %s as parameter of type %s", x, typ) return } } else if sig.variadic && i >= n-1 { @@ -365,7 +365,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { } } if exp == nil { - check.errorf(e.Sel.Pos(), _UndeclaredImportedName, "%s not declared by package C", sel) + check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package C", sel) goto Error } check.objDecl(exp, nil) @@ -373,12 +373,12 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { exp = pkg.scope.Lookup(sel) if exp == nil { if !pkg.fake { - check.errorf(e.Sel.Pos(), _UndeclaredImportedName, "%s not declared by package %s", sel, pkg.name) + check.errorf(e.Sel, _UndeclaredImportedName, "%s not declared by package %s", sel, pkg.name) } goto Error } if !exp.Exported() { - check.errorf(e.Sel.Pos(), _UnexportedName, "%s not exported by package %s", sel, pkg.name) + check.errorf(e.Sel, _UnexportedName, "%s not exported by package %s", sel, pkg.name) // ok to continue } } @@ -431,9 +431,9 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { switch { case index != nil: // TODO(gri) should provide actual type where the conflict happens - check.errorf(e.Sel.Pos(), _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel) + check.errorf(e.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", x.expr, sel) case indirect: - check.errorf(e.Sel.Pos(), _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ) + check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ) default: // Check if capitalization of sel matters and provide better error // message in that case. @@ -445,11 +445,11 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { changeCase = string(unicode.ToUpper(r)) + sel[1:] } if obj, _, _ = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, changeCase); obj != nil { - check.errorf(e.Sel.Pos(), _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", x.expr, sel, x.typ, sel, changeCase) + check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s, but does have %s)", x.expr, sel, x.typ, sel, changeCase) break } } - check.errorf(e.Sel.Pos(), _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel) + check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no field or method %s)", x.expr, sel, x.typ, sel) } goto Error } @@ -464,7 +464,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { m, _ := obj.(*Func) if m == nil { // TODO(gri) should check if capitalization of sel matters and provide better error message in that case - check.errorf(e.Sel.Pos(), _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel) + check.errorf(e.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", x.expr, sel, x.typ, sel) goto Error } diff --git a/src/go/types/check.go b/src/go/types/check.go index 407faa034f0..5e7bd920761 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -85,8 +85,8 @@ type Checker struct { // information collected during type-checking of a set of package files // (initialized by Files, valid only for the duration of check.Files; // maps and lists are allocated on demand) - files []*ast.File // package files - unusedDotImports map[*Scope]map[*Package]token.Pos // positions of unused dot-imported packages for each file scope + files []*ast.File // package files + unusedDotImports map[*Scope]map[*Package]*ast.ImportSpec // unused dot-imported packages firstErr error // first error encountered methods map[*TypeName][]*Func // maps package scope type names to associated non-blank (non-interface) methods @@ -105,18 +105,18 @@ type Checker struct { // addUnusedImport adds the position of a dot-imported package // pkg to the map of dot imports for the given file scope. -func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, pos token.Pos) { +func (check *Checker) addUnusedDotImport(scope *Scope, pkg *Package, spec *ast.ImportSpec) { mm := check.unusedDotImports if mm == nil { - mm = make(map[*Scope]map[*Package]token.Pos) + mm = make(map[*Scope]map[*Package]*ast.ImportSpec) check.unusedDotImports = mm } m := mm[scope] if m == nil { - m = make(map[*Package]token.Pos) + m = make(map[*Package]*ast.ImportSpec) mm[scope] = m } - m[pkg] = pos + m[pkg] = spec } // addDeclDep adds the dependency edge (check.decl -> to) if check.decl exists @@ -217,7 +217,7 @@ func (check *Checker) initFiles(files []*ast.File) { if name != "_" { pkg.name = name } else { - check.errorf(file.Name.Pos(), _BlankPkgName, "invalid package name _") + check.errorf(file.Name, _BlankPkgName, "invalid package name _") } fallthrough @@ -225,7 +225,7 @@ func (check *Checker) initFiles(files []*ast.File) { check.files = append(check.files, file) default: - check.errorf(file.Package, _MismatchedPkgName, "package %s; expected %s", name, pkg.name) + check.errorf(atPos(file.Package), _MismatchedPkgName, "package %s; expected %s", name, pkg.name) // ignore this file } } diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 4f47140aa2e..0955391d7bd 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -38,7 +38,7 @@ func (check *Checker) conversion(x *operand, T Type) { } if !ok { - check.errorf(x.pos(), _InvalidConversion, "cannot convert %s to %s", x, T) + check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T) x.mode = invalid return } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 416878d20d4..17b66ca387a 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -15,7 +15,7 @@ func (check *Checker) reportAltDecl(obj Object) { // We use "other" rather than "previous" here because // the first declaration seen may not be textually // earlier in the source. - check.errorf(pos, _DuplicateDecl, "\tother declaration of %s", obj.Name()) // secondary error, \t indented + check.errorf(obj, _DuplicateDecl, "\tother declaration of %s", obj.Name()) // secondary error, \t indented } } @@ -26,7 +26,7 @@ func (check *Checker) declare(scope *Scope, id *ast.Ident, obj Object, pos token // binding." if obj.Name() != "_" { if alt := scope.Insert(obj); alt != nil { - check.errorf(obj.Pos(), _DuplicateDecl, "%s redeclared in this block", obj.Name()) + check.errorf(obj, _DuplicateDecl, "%s redeclared in this block", obj.Name()) check.reportAltDecl(alt) return } @@ -357,16 +357,16 @@ func (check *Checker) cycleError(cycle []Object) { // cycle? That would be more consistent with other error messages. i := firstInSrc(cycle) obj := cycle[i] - check.errorf(obj.Pos(), _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name()) + check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name()) for range cycle { - check.errorf(obj.Pos(), _InvalidDeclCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented + check.errorf(obj, _InvalidDeclCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented i++ if i >= len(cycle) { i = 0 } obj = cycle[i] } - check.errorf(obj.Pos(), _InvalidDeclCycle, "\t%s", obj.Name()) + check.errorf(obj, _InvalidDeclCycle, "\t%s", obj.Name()) } // firstInSrc reports the index of the object with the "smallest" @@ -436,18 +436,18 @@ func (check *Checker) walkDecl(d ast.Decl, f func(decl)) { check.arityMatch(s, nil) f(varDecl{s}) default: - check.invalidAST(s.Pos(), "invalid token %s", d.Tok) + check.invalidAST(s, "invalid token %s", d.Tok) } case *ast.TypeSpec: f(typeDecl{s}) default: - check.invalidAST(s.Pos(), "unknown ast.Spec node %T", s) + check.invalidAST(s, "unknown ast.Spec node %T", s) } } case *ast.FuncDecl: f(funcDecl{d}) default: - check.invalidAST(d.Pos(), "unknown ast.Decl node %T", d) + check.invalidAST(d, "unknown ast.Decl node %T", d) } } @@ -468,7 +468,7 @@ func (check *Checker) constDecl(obj *Const, typ, init ast.Expr) { // don't report an error if the type is an invalid C (defined) type // (issue #22090) if t.Underlying() != Typ[Invalid] { - check.errorf(typ.Pos(), _InvalidConstType, "invalid constant type %s", t) + check.errorf(typ, _InvalidConstType, "invalid constant type %s", t) } obj.typ = Typ[Invalid] return @@ -694,9 +694,9 @@ func (check *Checker) addMethodDecls(obj *TypeName) { if alt := mset.insert(m); alt != nil { switch alt.(type) { case *Var: - check.errorf(m.pos, _DuplicateFieldAndMethod, "field and method with the same name %s", m.name) + check.errorf(m, _DuplicateFieldAndMethod, "field and method with the same name %s", m.name) case *Func: - check.errorf(m.pos, _DuplicateMethod, "method %s already declared for %s", m.name, obj) + check.errorf(m, _DuplicateMethod, "method %s already declared for %s", m.name, obj) default: unreachable() } @@ -721,7 +721,7 @@ func (check *Checker) funcDecl(obj *Func, decl *declInfo) { fdecl := decl.fdecl check.funcType(sig, fdecl.Recv, fdecl.Type) if sig.recv == nil && obj.name == "init" && (sig.params.Len() > 0 || sig.results.Len() > 0) { - check.errorf(fdecl.Pos(), _InvalidInitSig, "func init must have no arguments and no return values") + check.errorf(fdecl, _InvalidInitSig, "func init must have no arguments and no return values") // ok to continue } @@ -832,7 +832,7 @@ func (check *Checker) declStmt(d ast.Decl) { check.typeDecl(obj, d.spec.Type, nil, d.spec.Assign.IsValid()) check.pop().setColor(black) default: - check.invalidAST(d.node().Pos(), "unknown ast.Decl node %T", d.node()) + check.invalidAST(d.node(), "unknown ast.Decl node %T", d.node()) } }) } diff --git a/src/go/types/errors.go b/src/go/types/errors.go index b721cb1279b..c9c475e469b 100644 --- a/src/go/types/errors.go +++ b/src/go/types/errors.go @@ -110,43 +110,106 @@ func (check *Checker) err(err error) { f(err) } -func (check *Checker) error(pos token.Pos, code errorCode, msg string) { - check.err(Error{Fset: check.fset, Pos: pos, Msg: msg, go116code: code}) -} - -// newErrorf creates a new Error, but does not handle it. -func (check *Checker) newErrorf(pos token.Pos, code errorCode, format string, args ...interface{}) error { +func (check *Checker) newError(at positioner, code errorCode, soft bool, msg string) error { + ext := spanOf(at) return Error{ - Fset: check.fset, - Pos: pos, - Msg: check.sprintf(format, args...), - Soft: false, - go116code: code, + Fset: check.fset, + Pos: ext.pos, + Msg: msg, + Soft: soft, + go116code: code, + go116start: ext.start, + go116end: ext.end, } } -func (check *Checker) errorf(pos token.Pos, code errorCode, format string, args ...interface{}) { - check.error(pos, code, check.sprintf(format, args...)) +// newErrorf creates a new Error, but does not handle it. +func (check *Checker) newErrorf(at positioner, code errorCode, soft bool, format string, args ...interface{}) error { + msg := check.sprintf(format, args...) + return check.newError(at, code, soft, msg) } -func (check *Checker) softErrorf(pos token.Pos, code errorCode, format string, args ...interface{}) { - check.err(Error{ - Fset: check.fset, - Pos: pos, - Msg: check.sprintf(format, args...), - Soft: true, - go116code: code, - }) +func (check *Checker) error(at positioner, code errorCode, msg string) { + check.err(check.newError(at, code, false, msg)) } -func (check *Checker) invalidAST(pos token.Pos, format string, args ...interface{}) { - check.errorf(pos, 0, "invalid AST: "+format, args...) +func (check *Checker) errorf(at positioner, code errorCode, format string, args ...interface{}) { + check.error(at, code, check.sprintf(format, args...)) } -func (check *Checker) invalidArg(pos token.Pos, code errorCode, format string, args ...interface{}) { - check.errorf(pos, code, "invalid argument: "+format, args...) +func (check *Checker) softErrorf(at positioner, code errorCode, format string, args ...interface{}) { + check.err(check.newErrorf(at, code, true, format, args...)) } -func (check *Checker) invalidOp(pos token.Pos, code errorCode, format string, args ...interface{}) { - check.errorf(pos, code, "invalid operation: "+format, args...) +func (check *Checker) invalidAST(at positioner, format string, args ...interface{}) { + check.errorf(at, 0, "invalid AST: "+format, args...) +} + +func (check *Checker) invalidArg(at positioner, code errorCode, format string, args ...interface{}) { + check.errorf(at, code, "invalid argument: "+format, args...) +} + +func (check *Checker) invalidOp(at positioner, code errorCode, format string, args ...interface{}) { + check.errorf(at, code, "invalid operation: "+format, args...) +} + +// The positioner interface is used to extract the position of type-checker +// errors. +type positioner interface { + Pos() token.Pos +} + +// posSpan holds a position range along with a highlighted position within that +// range. This is used for positioning errors, with pos by convention being the +// first position in the source where the error is known to exist, and start +// and end defining the full span of syntax being considered when the error was +// detected. Invariant: start <= pos < end || start == pos == end. +type posSpan struct { + start, pos, end token.Pos +} + +func (e posSpan) Pos() token.Pos { + return e.pos +} + +// inNode creates a posSpan for the given node. +// Invariant: node.Pos() <= pos < node.End() (node.End() is the position of the +// first byte after node within the source). +func inNode(node ast.Node, pos token.Pos) posSpan { + start, end := node.Pos(), node.End() + if debug { + assert(start <= pos && pos < end) + } + return posSpan{start, pos, end} +} + +// atPos wraps a token.Pos to implement the positioner interface. +type atPos token.Pos + +func (s atPos) Pos() token.Pos { + return token.Pos(s) +} + +// spanOf extracts an error span from the given positioner. By default this is +// the trivial span starting and ending at pos, but this span is expanded when +// the argument naturally corresponds to a span of source code. +func spanOf(at positioner) posSpan { + switch x := at.(type) { + case nil: + panic("internal error: nil") + case posSpan: + return x + case ast.Node: + pos := x.Pos() + return posSpan{pos, pos, x.End()} + case *operand: + if x.expr != nil { + pos := x.Pos() + return posSpan{pos, pos, x.expr.End()} + } + return posSpan{token.NoPos, token.NoPos, token.NoPos} + default: + pos := at.Pos() + return posSpan{pos, pos, pos} + } } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 5f3415a59d9..1f8b9464074 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -68,11 +68,11 @@ var unaryOpPredicates = opPredicates{ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool { if pred := m[op]; pred != nil { if !pred(x.typ) { - check.invalidOp(x.pos(), _UndefinedOp, "operator %s not defined for %s", op, x) + check.invalidOp(x, _UndefinedOp, "operator %s not defined for %s", op, x) return false } } else { - check.invalidAST(x.pos(), "unknown operator %s", op) + check.invalidAST(x, "unknown operator %s", op) return false } return true @@ -85,7 +85,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) { // spec: "As an exception to the addressability // requirement x may also be a composite literal." if _, ok := unparen(x.expr).(*ast.CompositeLit); !ok && x.mode != variable { - check.invalidOp(x.pos(), _UnaddressableOperand, "cannot take address of %s", x) + check.invalidOp(x, _UnaddressableOperand, "cannot take address of %s", x) x.mode = invalid return } @@ -96,12 +96,12 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) { case token.ARROW: typ, ok := x.typ.Underlying().(*Chan) if !ok { - check.invalidOp(x.pos(), _InvalidReceive, "cannot receive from non-channel %s", x) + check.invalidOp(x, _InvalidReceive, "cannot receive from non-channel %s", x) x.mode = invalid return } if typ.dir == SendOnly { - check.invalidOp(x.pos(), _InvalidReceive, "cannot receive from send-only channel %s", x) + check.invalidOp(x, _InvalidReceive, "cannot receive from send-only channel %s", x) x.mode = invalid return } @@ -362,7 +362,7 @@ func (check *Checker) isRepresentable(x *operand, typ *Basic) error { msg = "cannot convert %s to %s" code = _InvalidConstVal } - return check.newErrorf(x.pos(), code, msg, x, typ) + return check.newErrorf(x, code, false, msg, x, typ) } return nil } @@ -470,7 +470,7 @@ func (check *Checker) updateExprType(x ast.Expr, typ Type, final bool) { // We already know from the shift check that it is representable // as an integer if it is a constant. if !isInteger(typ) { - check.invalidOp(x.Pos(), _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ) + check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s (type %s) must be integer", x, typ) return } // Even if we have an integer, if the value is a constant we @@ -521,7 +521,7 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error { check.updateExprType(x.expr, target, false) } } else if xkind != tkind { - return check.newErrorf(x.pos(), _InvalidUntypedConversion, "cannot convert %s to %s", x, target) + return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target) } return nil } @@ -535,7 +535,7 @@ func (check *Checker) canConvertUntyped(x *operand, target Type) error { } else { newTarget := check.implicitType(x, target) if newTarget == nil { - return check.newErrorf(x.pos(), _InvalidUntypedConversion, "cannot convert %s to %s", x, target) + return check.newErrorf(x, _InvalidUntypedConversion, false, "cannot convert %s to %s", x, target) } target = newTarget } @@ -641,7 +641,7 @@ func (check *Checker) comparison(x, y *operand, op token.Token) { } if err != "" { - check.errorf(x.pos(), code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err) + check.errorf(x, code, "cannot compare %s %s %s (%s)", x.expr, op, y.expr, err) x.mode = invalid return } @@ -678,7 +678,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { // as an integer. Nothing to do. } else { // shift has no chance - check.invalidOp(x.pos(), _InvalidShiftOperand, "shifted operand %s must be integer", x) + check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s must be integer", x) x.mode = invalid return } @@ -695,7 +695,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { return } default: - check.invalidOp(y.pos(), _InvalidShiftCount, "shift count %s must be integer", y) + check.invalidOp(y, _InvalidShiftCount, "shift count %s must be integer", y) x.mode = invalid return } @@ -708,7 +708,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { yval = constant.ToInt(y.val) assert(yval.Kind() == constant.Int) if constant.Sign(yval) < 0 { - check.invalidOp(y.pos(), _InvalidShiftCount, "negative shift count %s", y) + check.invalidOp(y, _InvalidShiftCount, "negative shift count %s", y) x.mode = invalid return } @@ -720,7 +720,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { const shiftBound = 1023 - 1 + 52 // so we can express smallestFloat64 s, ok := constant.Uint64Val(yval) if !ok || s > shiftBound { - check.invalidOp(y.pos(), _InvalidShiftCount, "invalid shift count %s", y) + check.invalidOp(y, _InvalidShiftCount, "invalid shift count %s", y) x.mode = invalid return } @@ -777,7 +777,7 @@ func (check *Checker) shift(x, y *operand, e *ast.BinaryExpr, op token.Token) { // non-constant shift - lhs must be an integer if !isInteger(x.typ) { - check.invalidOp(x.pos(), _InvalidShiftOperand, "shifted operand %s must be integer", x) + check.invalidOp(x, _InvalidShiftOperand, "shifted operand %s must be integer", x) x.mode = invalid return } @@ -841,7 +841,11 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o // only report an error if we have valid types // (otherwise we had an error reported elsewhere already) if x.typ != Typ[Invalid] && y.typ != Typ[Invalid] { - check.invalidOp(x.pos(), _MismatchedTypes, "mismatched types %s and %s", x.typ, y.typ) + var posn positioner = x + if e != nil { + posn = e + } + check.invalidOp(posn, _MismatchedTypes, "mismatched types %s and %s", x.typ, y.typ) } x.mode = invalid return @@ -855,7 +859,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o if op == token.QUO || op == token.REM { // check for zero divisor if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 { - check.invalidOp(y.pos(), _DivByZero, "division by zero") + check.invalidOp(&y, _DivByZero, "division by zero") x.mode = invalid return } @@ -865,7 +869,7 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o re, im := constant.Real(y.val), constant.Imag(y.val) re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { - check.invalidOp(y.pos(), _DivByZero, "division by zero") + check.invalidOp(&y, _DivByZero, "division by zero") x.mode = invalid return } @@ -918,7 +922,7 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) { // the index must be of integer type if !isInteger(x.typ) { - check.invalidArg(x.pos(), _InvalidIndex, "index %s must be integer", &x) + check.invalidArg(&x, _InvalidIndex, "index %s must be integer", &x) return } @@ -928,13 +932,13 @@ func (check *Checker) index(index ast.Expr, max int64) (typ Type, val int64) { // a constant index i must be in bounds if constant.Sign(x.val) < 0 { - check.invalidArg(x.pos(), _InvalidIndex, "index %s must not be negative", &x) + check.invalidArg(&x, _InvalidIndex, "index %s must not be negative", &x) return } v, valid := constant.Int64Val(constant.ToInt(x.val)) if !valid || max >= 0 && v >= max { - check.errorf(x.pos(), _InvalidIndex, "index %s is out of bounds", &x) + check.errorf(&x, _InvalidIndex, "index %s is out of bounds", &x) return } @@ -960,12 +964,12 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 index = i validIndex = true } else { - check.errorf(e.Pos(), _InvalidLitIndex, "index %s must be integer constant", kv.Key) + check.errorf(e, _InvalidLitIndex, "index %s must be integer constant", kv.Key) } } eval = kv.Value } else if length >= 0 && index >= length { - check.errorf(e.Pos(), _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length) + check.errorf(e, _OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length) } else { validIndex = true } @@ -973,7 +977,7 @@ func (check *Checker) indexedElts(elts []ast.Expr, typ Type, length int64) int64 // if we have a valid index, check for duplicate entries if validIndex { if visited[index] { - check.errorf(e.Pos(), _DuplicateLitKey, "duplicate index %d in array or slice literal", index) + check.errorf(e, _DuplicateLitKey, "duplicate index %d in array or slice literal", index) } visited[index] = true } @@ -1063,13 +1067,13 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case *ast.Ellipsis: // ellipses are handled explicitly where they are legal // (array composite literals and parameter lists) - check.error(e.Pos(), _BadDotDotDotSyntax, "invalid use of '...'") + check.error(e, _BadDotDotDotSyntax, "invalid use of '...'") goto Error case *ast.BasicLit: x.setConst(e.Kind, e.Value) if x.mode == invalid { - check.invalidAST(e.Pos(), "invalid literal %v", e.Value) + check.invalidAST(e, "invalid literal %v", e.Value) goto Error } @@ -1090,7 +1094,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { x.mode = value x.typ = sig } else { - check.invalidAST(e.Pos(), "invalid function literal %s", e) + check.invalidAST(e, "invalid function literal %s", e) goto Error } @@ -1122,7 +1126,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { default: // TODO(gri) provide better error messages depending on context - check.error(e.Pos(), _UntypedLit, "missing type in composite literal") + check.error(e, _UntypedLit, "missing type in composite literal") goto Error } @@ -1138,7 +1142,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { for _, e := range e.Elts { kv, _ := e.(*ast.KeyValueExpr) if kv == nil { - check.error(e.Pos(), _MixedStructLit, "mixture of field:value and value elements in struct literal") + check.error(e, _MixedStructLit, "mixture of field:value and value elements in struct literal") continue } key, _ := kv.Key.(*ast.Ident) @@ -1146,12 +1150,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // so we don't drop information on the floor check.expr(x, kv.Value) if key == nil { - check.errorf(kv.Pos(), _InvalidLitField, "invalid field name %s in struct literal", kv.Key) + check.errorf(kv, _InvalidLitField, "invalid field name %s in struct literal", kv.Key) continue } i := fieldIndex(utyp.fields, check.pkg, key.Name) if i < 0 { - check.errorf(kv.Pos(), _MissingLitField, "unknown field %s in struct literal", key.Name) + check.errorf(kv, _MissingLitField, "unknown field %s in struct literal", key.Name) continue } fld := fields[i] @@ -1160,7 +1164,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { check.assignment(x, etyp, "struct literal") // 0 <= i < len(fields) if visited[i] { - check.errorf(kv.Pos(), _DuplicateLitField, "duplicate field name %s in struct literal", key.Name) + check.errorf(kv, _DuplicateLitField, "duplicate field name %s in struct literal", key.Name) continue } visited[i] = true @@ -1169,25 +1173,27 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // no element must have a key for i, e := range e.Elts { if kv, _ := e.(*ast.KeyValueExpr); kv != nil { - check.error(kv.Pos(), _MixedStructLit, "mixture of field:value and value elements in struct literal") + check.error(kv, _MixedStructLit, "mixture of field:value and value elements in struct literal") continue } check.expr(x, e) if i >= len(fields) { - check.error(x.pos(), _InvalidStructLit, "too many values in struct literal") + check.error(x, _InvalidStructLit, "too many values in struct literal") break // cannot continue } // i < len(fields) fld := fields[i] if !fld.Exported() && fld.pkg != check.pkg { - check.errorf(x.pos(), _UnexportedLitField, "implicit assignment to unexported field %s in %s literal", fld.name, typ) + check.errorf(x, + _UnexportedLitField, + "implicit assignment to unexported field %s in %s literal", fld.name, typ) continue } etyp := fld.typ check.assignment(x, etyp, "struct literal") } if len(e.Elts) < len(fields) { - check.error(e.Rbrace, _InvalidStructLit, "too few values in struct literal") + check.error(inNode(e, e.Rbrace), _InvalidStructLit, "too few values in struct literal") // ok to continue } } @@ -1197,7 +1203,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // This is a stop-gap solution. Should use Checker.objPath to report entire // path starting with earliest declaration in the source. TODO(gri) fix this. if utyp.elem == nil { - check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration") + check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration") goto Error } n := check.indexedElts(e.Elts, utyp.elem, utyp.len) @@ -1224,7 +1230,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // Prevent crash if the slice referred to is not yet set up. // See analogous comment for *Array. if utyp.elem == nil { - check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration") + check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration") goto Error } check.indexedElts(e.Elts, utyp.elem, -1) @@ -1233,14 +1239,14 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // Prevent crash if the map referred to is not yet set up. // See analogous comment for *Array. if utyp.key == nil || utyp.elem == nil { - check.error(e.Pos(), _InvalidTypeCycle, "illegal cycle in type declaration") + check.error(e, _InvalidTypeCycle, "illegal cycle in type declaration") goto Error } visited := make(map[interface{}][]Type, len(e.Elts)) for _, e := range e.Elts { kv, _ := e.(*ast.KeyValueExpr) if kv == nil { - check.error(e.Pos(), _MissingLitKey, "missing key in map literal") + check.error(e, _MissingLitKey, "missing key in map literal") continue } check.exprWithHint(x, kv.Key, utyp.key) @@ -1265,7 +1271,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { visited[xkey] = nil } if duplicate { - check.errorf(x.pos(), _DuplicateLitKey, "duplicate key %s in map literal", x.val) + check.errorf(x, _DuplicateLitKey, "duplicate key %s in map literal", x.val) continue } } @@ -1287,7 +1293,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } // if utyp is invalid, an error was reported before if utyp != Typ[Invalid] { - check.errorf(e.Pos(), _InvalidLit, "invalid composite literal type %s", typ) + check.errorf(e, _InvalidLit, "invalid composite literal type %s", typ) goto Error } } @@ -1361,12 +1367,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } if !valid { - check.invalidOp(x.pos(), _NonIndexableOperand, "cannot index %s", x) + check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x) goto Error } if e.Index == nil { - check.invalidAST(e.Pos(), "missing index for %s", x) + check.invalidAST(e, "missing index for %s", x) goto Error } @@ -1386,7 +1392,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case *Basic: if isString(typ) { if e.Slice3 { - check.invalidOp(x.pos(), _InvalidSliceExpr, "3-index slice of string") + check.invalidOp(x, _InvalidSliceExpr, "3-index slice of string") goto Error } valid = true @@ -1404,7 +1410,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { valid = true length = typ.len if x.mode != variable { - check.invalidOp(x.pos(), _NonSliceableOperand, "cannot slice %s (value not addressable)", x) + check.invalidOp(x, _NonSliceableOperand, "cannot slice %s (value not addressable)", x) goto Error } x.typ = &Slice{elem: typ.elem} @@ -1422,7 +1428,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } if !valid { - check.invalidOp(x.pos(), _NonSliceableOperand, "cannot slice %s", x) + check.invalidOp(x, _NonSliceableOperand, "cannot slice %s", x) goto Error } @@ -1430,7 +1436,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // spec: "Only the first index may be omitted; it defaults to 0." if e.Slice3 && (e.High == nil || e.Max == nil) { - check.invalidAST(e.Rbrack, "2nd and 3rd index required in 3-index slice") + check.invalidAST(inNode(e, e.Rbrack), "2nd and 3rd index required in 3-index slice") goto Error } @@ -1467,7 +1473,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { if x > 0 { for _, y := range ind[i+1:] { if y >= 0 && x > y { - check.errorf(e.Rbrack, _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y) + check.errorf(inNode(e, e.Rbrack), _SwappedSliceIndices, "swapped slice indices: %d > %d", x, y) break L // only report one error, ok to continue } } @@ -1481,21 +1487,21 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { } xtyp, _ := x.typ.Underlying().(*Interface) if xtyp == nil { - check.invalidOp(x.pos(), _InvalidAssert, "%s is not an interface", x) + check.invalidOp(x, _InvalidAssert, "%s is not an interface", x) goto Error } // x.(type) expressions are handled explicitly in type switches if e.Type == nil { // Don't use invalidAST because this can occur in the AST produced by // go/parser. - check.error(e.Pos(), _BadTypeKeyword, "use of .(type) outside type switch") + check.error(e, _BadTypeKeyword, "use of .(type) outside type switch") goto Error } T := check.typ(e.Type) if T == Typ[Invalid] { goto Error } - check.typeAssertion(x.pos(), x, xtyp, T) + check.typeAssertion(x, x, xtyp, T) x.mode = commaok x.typ = T @@ -1514,7 +1520,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { x.mode = variable x.typ = typ.base } else { - check.invalidOp(x.pos(), _InvalidIndirection, "cannot indirect %s", x) + check.invalidOp(x, _InvalidIndirection, "cannot indirect %s", x) goto Error } } @@ -1541,7 +1547,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { case *ast.KeyValueExpr: // key:value expressions are handled in composite literals - check.invalidAST(e.Pos(), "no key:value expected") + check.invalidAST(e, "no key:value expected") goto Error case *ast.ArrayType, *ast.StructType, *ast.FuncType, @@ -1593,7 +1599,7 @@ func keyVal(x constant.Value) interface{} { } // typeAssertion checks that x.(T) is legal; xtyp must be the type of x. -func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, T Type) { +func (check *Checker) typeAssertion(at positioner, x *operand, xtyp *Interface, T Type) { method, wrongType := check.assertableTo(xtyp, T) if method == nil { return @@ -1608,7 +1614,7 @@ func (check *Checker) typeAssertion(pos token.Pos, x *operand, xtyp *Interface, } else { msg = "missing method " + method.name } - check.errorf(pos, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg) + check.errorf(at, _ImpossibleAssert, "%s cannot have dynamic type %s (%s)", x, T, msg) } func (check *Checker) singleValue(x *operand) { @@ -1616,7 +1622,7 @@ func (check *Checker) singleValue(x *operand) { // tuple types are never named - no need for underlying type below if t, ok := x.typ.(*Tuple); ok { assert(t.Len() != 1) - check.errorf(x.pos(), _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) + check.errorf(x, _TooManyValues, "%d-valued %s where single value is expected", t.Len(), x) x.mode = invalid } } @@ -1649,7 +1655,7 @@ func (check *Checker) multiExpr(x *operand, e ast.Expr) { msg = "%s is not an expression" code = _NotAnExpr } - check.errorf(x.pos(), code, msg, x) + check.errorf(x, code, msg, x) x.mode = invalid } @@ -1676,7 +1682,7 @@ func (check *Checker) exprWithHint(x *operand, e ast.Expr, hint Type) { msg = "%s is not an expression" code = _NotAnExpr } - check.errorf(x.pos(), code, msg, x) + check.errorf(x, code, msg, x) x.mode = invalid } @@ -1687,7 +1693,7 @@ func (check *Checker) exprOrType(x *operand, e ast.Expr) { check.rawExpr(x, e, nil) check.singleValue(x) if x.mode == novalue { - check.errorf(x.pos(), _NotAnExpr, "%s used as value or type", x) + check.errorf(x, _NotAnExpr, "%s used as value or type", x) x.mode = invalid } } diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index f770d8b8308..77a739c7c14 100644 --- a/src/go/types/initorder.go +++ b/src/go/types/initorder.go @@ -151,14 +151,14 @@ func findPath(objMap map[Object]*declInfo, from, to Object, seen map[Object]bool // reportCycle reports an error for the given cycle. func (check *Checker) reportCycle(cycle []Object) { obj := cycle[0] - check.errorf(obj.Pos(), _InvalidInitCycle, "initialization cycle for %s", obj.Name()) + check.errorf(obj, _InvalidInitCycle, "initialization cycle for %s", obj.Name()) // subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n for i := len(cycle) - 1; i >= 0; i-- { - check.errorf(obj.Pos(), _InvalidInitCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented + check.errorf(obj, _InvalidInitCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented obj = cycle[i] } // print cycle[0] again to close the cycle - check.errorf(obj.Pos(), _InvalidInitCycle, "\t%s", obj.Name()) + check.errorf(obj, _InvalidInitCycle, "\t%s", obj.Name()) } // ---------------------------------------------------------------------------- diff --git a/src/go/types/labels.go b/src/go/types/labels.go index 5a577c45d46..8cf6e63645e 100644 --- a/src/go/types/labels.go +++ b/src/go/types/labels.go @@ -32,13 +32,13 @@ func (check *Checker) labels(body *ast.BlockStmt) { msg = "label %s not declared" code = _UndeclaredLabel } - check.errorf(jmp.Label.Pos(), code, msg, name) + check.errorf(jmp.Label, code, msg, name) } // spec: "It is illegal to define a label that is never used." for _, obj := range all.elems { if lbl := obj.(*Label); !lbl.used { - check.softErrorf(lbl.pos, _UnusedLabel, "label %s declared but not used", lbl.name) + check.softErrorf(lbl, _UnusedLabel, "label %s declared but not used", lbl.name) } } } @@ -136,7 +136,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele if name := s.Label.Name; name != "_" { lbl := NewLabel(s.Label.Pos(), check.pkg, name) if alt := all.Insert(lbl); alt != nil { - check.softErrorf(lbl.pos, _DuplicateLabel, "label %s already declared", name) + check.softErrorf(lbl, _DuplicateLabel, "label %s already declared", name) check.reportAltDecl(alt) // ok to continue } else { @@ -152,7 +152,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele check.recordUse(jmp.Label, lbl) if jumpsOverVarDecl(jmp) { check.softErrorf( - jmp.Label.Pos(), + jmp.Label, _JumpOverDecl, "goto %s jumps over variable declaration at line %d", name, @@ -191,7 +191,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele } } if !valid { - check.errorf(s.Label.Pos(), _MisplacedLabel, "invalid break label %s", name) + check.errorf(s.Label, _MisplacedLabel, "invalid break label %s", name) return } @@ -206,7 +206,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele } } if !valid { - check.errorf(s.Label.Pos(), _MisplacedLabel, "invalid continue label %s", name) + check.errorf(s.Label, _MisplacedLabel, "invalid continue label %s", name) return } @@ -218,7 +218,7 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *ast.Labele } default: - check.invalidAST(s.Pos(), "branch statement: %s %s", s.Tok, name) + check.invalidAST(s, "branch statement: %s %s", s.Tok, name) return } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index 73b3be2655e..2d30dbd024c 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -59,10 +59,10 @@ type operand struct { id builtinId } -// pos returns the position of the expression corresponding to x. +// Pos returns the position of the expression corresponding to x. // If x is invalid the position is token.NoPos. // -func (x *operand) pos() token.Pos { +func (x *operand) Pos() token.Pos { // x.expr may not be set if x is invalid if x.expr == nil { return token.NoPos diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 05d24ef22d5..4092d55b4e5 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -60,22 +60,22 @@ func (check *Checker) arityMatch(s, init *ast.ValueSpec) { case init == nil && r == 0: // var decl w/o init expr if s.Type == nil { - check.errorf(s.Pos(), code, "missing type or init expr") + check.errorf(s, code, "missing type or init expr") } case l < r: if l < len(s.Values) { // init exprs from s n := s.Values[l] - check.errorf(n.Pos(), code, "extra init expr %s", n) + check.errorf(n, code, "extra init expr %s", n) // TODO(gri) avoid declared but not used error here } else { // init exprs "inherited" - check.errorf(s.Pos(), code, "extra init expr at %s", check.fset.Position(init.Pos())) + check.errorf(s, code, "extra init expr at %s", check.fset.Position(init.Pos())) // TODO(gri) avoid declared but not used error here } case l > r && (init != nil || r != 1): n := s.Names[r] - check.errorf(n.Pos(), code, "missing init expr for %s", n) + check.errorf(n, code, "missing init expr for %s", n) } } @@ -104,14 +104,14 @@ func (check *Checker) declarePkgObj(ident *ast.Ident, obj Object, d *declInfo) { // spec: "A package-scope or file-scope identifier with name init // may only be declared to be a function with this (func()) signature." if ident.Name == "init" { - check.errorf(ident.Pos(), _InvalidInitDecl, "cannot declare init - must be func") + check.errorf(ident, _InvalidInitDecl, "cannot declare init - must be func") return } // spec: "The main package must have package name main and declare // a function main that takes no arguments and returns no value." if ident.Name == "main" && check.pkg.name == "main" { - check.errorf(ident.Pos(), _InvalidMainDecl, "cannot declare main - must be func") + check.errorf(ident, _InvalidMainDecl, "cannot declare main - must be func") return } @@ -169,7 +169,7 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package { imp = nil // create fake package below } if err != nil { - check.errorf(pos, _BrokenImport, "could not import %s (%s)", path, err) + check.errorf(atPos(pos), _BrokenImport, "could not import %s (%s)", path, err) if imp == nil { // create a new fake package // come up with a sensible package name (heuristic) @@ -242,7 +242,7 @@ func (check *Checker) collectObjects() { // import package path, err := validatedImportPath(d.spec.Path.Value) if err != nil { - check.errorf(d.spec.Path.Pos(), _BadImportPath, "invalid import path (%s)", err) + check.errorf(d.spec.Path, _BadImportPath, "invalid import path (%s)", err) return } @@ -265,11 +265,11 @@ func (check *Checker) collectObjects() { name = d.spec.Name.Name if path == "C" { // match cmd/compile (not prescribed by spec) - check.errorf(d.spec.Name.Pos(), _ImportCRenamed, `cannot rename import "C"`) + check.errorf(d.spec.Name, _ImportCRenamed, `cannot rename import "C"`) return } if name == "init" { - check.errorf(d.spec.Name.Pos(), _InvalidInitDecl, "cannot declare init - must be func") + check.errorf(d.spec.Name, _InvalidInitDecl, "cannot declare init - must be func") return } } @@ -300,14 +300,14 @@ func (check *Checker) collectObjects() { // the object may be imported into more than one file scope // concurrently. See issue #32154.) if alt := fileScope.Insert(obj); alt != nil { - check.errorf(d.spec.Name.Pos(), _DuplicateDecl, "%s redeclared in this block", obj.Name()) + check.errorf(d.spec.Name, _DuplicateDecl, "%s redeclared in this block", obj.Name()) check.reportAltDecl(alt) } } } // add position to set of dot-import positions for this file // (this is only needed for "imported but not used" errors) - check.addUnusedDotImport(fileScope, imp, d.spec.Pos()) + check.addUnusedDotImport(fileScope, imp, d.spec) } else { // declare imported package object in file scope // (no need to provide s.Name since we called check.recordDef earlier) @@ -373,7 +373,7 @@ func (check *Checker) collectObjects() { check.recordDef(d.decl.Name, obj) // init functions must have a body if d.decl.Body == nil { - check.softErrorf(obj.pos, _MissingInitBody, "missing function body") + check.softErrorf(obj, _MissingInitBody, "missing function body") } } else { check.declare(pkg.scope, d.decl.Name, obj, token.NoPos) @@ -403,10 +403,10 @@ func (check *Checker) collectObjects() { for _, obj := range scope.elems { if alt := pkg.scope.Lookup(obj.Name()); alt != nil { if pkg, ok := obj.(*PkgName); ok { - check.errorf(alt.Pos(), _DuplicateDecl, "%s already declared through import of %s", alt.Name(), pkg.Imported()) + check.errorf(alt, _DuplicateDecl, "%s already declared through import of %s", alt.Name(), pkg.Imported()) check.reportAltDecl(pkg) } else { - check.errorf(alt.Pos(), _DuplicateDecl, "%s already declared through dot-import of %s", alt.Name(), obj.Pkg()) + check.errorf(alt, _DuplicateDecl, "%s already declared through dot-import of %s", alt.Name(), obj.Pkg()) // TODO(gri) dot-imported objects don't have a position; reportAltDecl won't print anything check.reportAltDecl(obj) } @@ -575,9 +575,9 @@ func (check *Checker) unusedImports() { path := obj.imported.path base := pkgName(path) if obj.name == base { - check.softErrorf(obj.pos, _UnusedImport, "%q imported but not used", path) + check.softErrorf(obj, _UnusedImport, "%q imported but not used", path) } else { - check.softErrorf(obj.pos, _UnusedImport, "%q imported but not used as %s", path, obj.name) + check.softErrorf(obj, _UnusedImport, "%q imported but not used as %s", path, obj.name) } } } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index cc98b07728d..b1ccbf0c65d 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -46,7 +46,7 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body } if sig.results.Len() > 0 && !check.isTerminating(body, "") { - check.error(body.Rbrace, _MissingReturn, "missing return") + check.error(atPos(body.Rbrace), _MissingReturn, "missing return") } // spec: "Implementation restriction: A compiler may make it illegal to @@ -65,7 +65,7 @@ func (check *Checker) usage(scope *Scope) { return unused[i].pos < unused[j].pos }) for _, v := range unused { - check.softErrorf(v.pos, _UnusedVar, "%s declared but not used", v.name) + check.softErrorf(v, _UnusedVar, "%s declared but not used", v.name) } for _, scope := range scope.children { @@ -135,11 +135,11 @@ func (check *Checker) multipleDefaults(list []ast.Stmt) { d = s } default: - check.invalidAST(s.Pos(), "case/communication clause expected") + check.invalidAST(s, "case/communication clause expected") } if d != nil { if first != nil { - check.errorf(d.Pos(), _DuplicateDefault, "multiple defaults (first at %s)", check.fset.Position(first.Pos())) + check.errorf(d, _DuplicateDefault, "multiple defaults (first at %s)", check.fset.Position(first.Pos())) } else { first = d } @@ -184,7 +184,7 @@ func (check *Checker) suspendedCall(keyword string, call *ast.CallExpr) { default: unreachable() } - check.errorf(x.pos(), code, "%s %s %s", keyword, msg, &x) + check.errorf(&x, code, "%s %s %s", keyword, msg, &x) } // goVal returns the Go value for val, or nil. @@ -256,17 +256,17 @@ L: // (quadratic algorithm, but these lists tend to be very short) for _, vt := range seen[val] { if check.identical(v.typ, vt.typ) { - check.errorf(v.pos(), _DuplicateCase, "duplicate case %s in expression switch", &v) - check.error(vt.pos, _DuplicateCase, "\tprevious case") // secondary error, \t indented + check.errorf(&v, _DuplicateCase, "duplicate case %s in expression switch", &v) + check.error(atPos(vt.pos), _DuplicateCase, "\tprevious case") // secondary error, \t indented continue L } } - seen[val] = append(seen[val], valueType{v.pos(), v.typ}) + seen[val] = append(seen[val], valueType{v.Pos(), v.typ}) } } } -func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]token.Pos) (T Type) { +func (check *Checker) caseTypes(x *operand, xtyp *Interface, types []ast.Expr, seen map[Type]ast.Expr) (T Type) { L: for _, e := range types { T = check.typOrNil(e) @@ -275,21 +275,21 @@ L: } // look for duplicate types // (quadratic algorithm, but type switches tend to be reasonably small) - for t, pos := range seen { + for t, other := range seen { if T == nil && t == nil || T != nil && t != nil && check.identical(T, t) { // talk about "case" rather than "type" because of nil case Ts := "nil" if T != nil { Ts = T.String() } - check.errorf(e.Pos(), _DuplicateCase, "duplicate case %s in type switch", Ts) - check.error(pos, _DuplicateCase, "\tprevious case") // secondary error, \t indented + check.errorf(e, _DuplicateCase, "duplicate case %s in type switch", Ts) + check.error(other, _DuplicateCase, "\tprevious case") // secondary error, \t indented continue L } } - seen[T] = e.Pos() + seen[T] = e if T != nil { - check.typeAssertion(e.Pos(), x, xtyp, T) + check.typeAssertion(e, x, xtyp, T) } } return @@ -345,7 +345,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { msg = "is not an expression" code = _NotAnExpr } - check.errorf(x.pos(), code, "%s %s", &x, msg) + check.errorf(&x, code, "%s %s", &x, msg) case *ast.SendStmt: var ch, x operand @@ -357,12 +357,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { tch, ok := ch.typ.Underlying().(*Chan) if !ok { - check.invalidOp(s.Arrow, _InvalidSend, "cannot send to non-chan type %s", ch.typ) + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to non-chan type %s", ch.typ) return } if tch.dir == RecvOnly { - check.invalidOp(s.Arrow, _InvalidSend, "cannot send to receive-only type %s", tch) + check.invalidOp(inNode(s, s.Arrow), _InvalidSend, "cannot send to receive-only type %s", tch) return } @@ -376,7 +376,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { case token.DEC: op = token.SUB default: - check.invalidAST(s.TokPos, "unknown inc/dec operation %s", s.Tok) + check.invalidAST(inNode(s, s.TokPos), "unknown inc/dec operation %s", s.Tok) return } @@ -386,7 +386,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { return } if !isNumeric(x.typ) { - check.invalidOp(s.X.Pos(), _NonNumericIncDec, "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ) + check.invalidOp(s.X, _NonNumericIncDec, "%s%s (non-numeric type %s)", s.X, s.Tok, x.typ) return } @@ -401,11 +401,11 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { switch s.Tok { case token.ASSIGN, token.DEFINE: if len(s.Lhs) == 0 { - check.invalidAST(s.Pos(), "missing lhs in assignment") + check.invalidAST(s, "missing lhs in assignment") return } if s.Tok == token.DEFINE { - check.shortVarDecl(s.TokPos, s.Lhs, s.Rhs) + check.shortVarDecl(inNode(s, s.TokPos), s.Lhs, s.Rhs) } else { // regular assignment check.assignVars(s.Lhs, s.Rhs) @@ -414,12 +414,12 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { default: // assignment operations if len(s.Lhs) != 1 || len(s.Rhs) != 1 { - check.errorf(s.TokPos, _MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Tok) + check.errorf(inNode(s, s.TokPos), _MultiValAssignOp, "assignment operation %s requires single-valued expressions", s.Tok) return } op := assignOp(s.Tok) if op == token.ILLEGAL { - check.invalidAST(s.TokPos, "unknown assignment operation %s", s.Tok) + check.invalidAST(atPos(s.TokPos), "unknown assignment operation %s", s.Tok) return } var x operand @@ -447,8 +447,8 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { // with the same name as a result parameter is in scope at the place of the return." for _, obj := range res.vars { if alt := check.lookup(obj.name); alt != nil && alt != obj { - check.errorf(s.Pos(), _OutOfScopeResult, "result parameter %s not in scope at return", obj.name) - check.errorf(alt.Pos(), _OutOfScopeResult, "\tinner declaration of %s", obj) + check.errorf(s, _OutOfScopeResult, "result parameter %s not in scope at return", obj.name) + check.errorf(alt, _OutOfScopeResult, "\tinner declaration of %s", obj) // ok to continue } } @@ -457,7 +457,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.initVars(res.vars, s.Results, s.Return) } } else if len(s.Results) > 0 { - check.error(s.Results[0].Pos(), _WrongResultCount, "no result values expected") + check.error(s.Results[0], _WrongResultCount, "no result values expected") check.use(s.Results...) } @@ -469,11 +469,11 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { switch s.Tok { case token.BREAK: if ctxt&breakOk == 0 { - check.error(s.Pos(), _MisplacedBreak, "break not in for, switch, or select statement") + check.error(s, _MisplacedBreak, "break not in for, switch, or select statement") } case token.CONTINUE: if ctxt&continueOk == 0 { - check.error(s.Pos(), _MisplacedContinue, "continue not in for statement") + check.error(s, _MisplacedContinue, "continue not in for statement") } case token.FALLTHROUGH: if ctxt&fallthroughOk == 0 { @@ -482,10 +482,10 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { if ctxt&finalSwitchCase != 0 { msg = "cannot fallthrough final case in switch" } - check.error(s.Pos(), code, msg) + check.error(s, code, msg) } default: - check.invalidAST(s.Pos(), "branch statement: %s", s.Tok) + check.invalidAST(s, "branch statement: %s", s.Tok) } case *ast.BlockStmt: @@ -502,7 +502,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { var x operand check.expr(&x, s.Cond) if x.mode != invalid && !isBoolean(x.typ) { - check.error(s.Cond.Pos(), _InvalidCond, "non-boolean condition in if statement") + check.error(s.Cond, _InvalidCond, "non-boolean condition in if statement") } check.stmt(inner, s.Body) // The parser produces a correct AST but if it was modified @@ -513,7 +513,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { case *ast.IfStmt, *ast.BlockStmt: check.stmt(inner, s.Else) default: - check.invalidAST(s.Else.Pos(), "invalid else branch in if statement") + check.invalidAST(s.Else, "invalid else branch in if statement") } case *ast.SwitchStmt: @@ -543,7 +543,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { for i, c := range s.Body.List { clause, _ := c.(*ast.CaseClause) if clause == nil { - check.invalidAST(c.Pos(), "incorrect expression switch case") + check.invalidAST(c, "incorrect expression switch case") continue } check.caseValues(&x, clause.List, seen) @@ -580,19 +580,19 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { rhs = guard.X case *ast.AssignStmt: if len(guard.Lhs) != 1 || guard.Tok != token.DEFINE || len(guard.Rhs) != 1 { - check.invalidAST(s.Pos(), "incorrect form of type switch guard") + check.invalidAST(s, "incorrect form of type switch guard") return } lhs, _ = guard.Lhs[0].(*ast.Ident) if lhs == nil { - check.invalidAST(s.Pos(), "incorrect form of type switch guard") + check.invalidAST(s, "incorrect form of type switch guard") return } if lhs.Name == "_" { // _ := x.(type) is an invalid short variable declaration - check.softErrorf(lhs.Pos(), _NoNewVar, "no new variable on left side of :=") + check.softErrorf(lhs, _NoNewVar, "no new variable on left side of :=") lhs = nil // avoid declared but not used error below } else { check.recordDef(lhs, nil) // lhs variable is implicitly declared in each cause clause @@ -601,14 +601,14 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { rhs = guard.Rhs[0] default: - check.invalidAST(s.Pos(), "incorrect form of type switch guard") + check.invalidAST(s, "incorrect form of type switch guard") return } // rhs must be of the form: expr.(type) and expr must be an interface expr, _ := rhs.(*ast.TypeAssertExpr) if expr == nil || expr.Type != nil { - check.invalidAST(s.Pos(), "incorrect form of type switch guard") + check.invalidAST(s, "incorrect form of type switch guard") return } var x operand @@ -618,18 +618,18 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { } xtyp, _ := x.typ.Underlying().(*Interface) if xtyp == nil { - check.errorf(x.pos(), _InvalidTypeSwitch, "%s is not an interface", &x) + check.errorf(&x, _InvalidTypeSwitch, "%s is not an interface", &x) return } check.multipleDefaults(s.Body.List) - var lhsVars []*Var // list of implicitly declared lhs variables - seen := make(map[Type]token.Pos) // map of seen types to positions + var lhsVars []*Var // list of implicitly declared lhs variables + seen := make(map[Type]ast.Expr) // map of seen types to positions for _, s := range s.Body.List { clause, _ := s.(*ast.CaseClause) if clause == nil { - check.invalidAST(s.Pos(), "incorrect type switch case") + check.invalidAST(s, "incorrect type switch case") continue } // Check each type in this type switch case. @@ -671,7 +671,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { v.used = true // avoid usage error when checking entire function } if !used { - check.softErrorf(lhs.Pos(), _UnusedVar, "%s declared but not used", lhs.Name) + check.softErrorf(lhs, _UnusedVar, "%s declared but not used", lhs.Name) } } @@ -708,7 +708,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { } if !valid { - check.error(clause.Comm.Pos(), _InvalidSelectCase, "select case must be send or receive (possibly with assignment)") + check.error(clause.Comm, _InvalidSelectCase, "select case must be send or receive (possibly with assignment)") continue } @@ -730,14 +730,14 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { var x operand check.expr(&x, s.Cond) if x.mode != invalid && !isBoolean(x.typ) { - check.error(s.Cond.Pos(), _InvalidCond, "non-boolean condition in for statement") + check.error(s.Cond, _InvalidCond, "non-boolean condition in for statement") } } check.simpleStmt(s.Post) // spec: "The init statement may be a short variable // declaration, but the post statement must not." if s, _ := s.Post.(*ast.AssignStmt); s != nil && s.Tok == token.DEFINE { - check.softErrorf(s.Pos(), _InvalidPostDecl, "cannot declare in post statement") + check.softErrorf(s, _InvalidPostDecl, "cannot declare in post statement") // Don't call useLHS here because we want to use the lhs in // this erroneous statement so that we don't get errors about // these lhs variables being declared but not used. @@ -781,18 +781,18 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { key = typ.elem val = Typ[Invalid] if typ.dir == SendOnly { - check.errorf(x.pos(), _InvalidChanRange, "cannot range over send-only channel %s", &x) + check.errorf(&x, _InvalidChanRange, "cannot range over send-only channel %s", &x) // ok to continue } if s.Value != nil { - check.errorf(s.Value.Pos(), _InvalidIterVar, "iteration over %s permits only one iteration variable", &x) + check.errorf(atPos(s.Value.Pos()), _InvalidIterVar, "iteration over %s permits only one iteration variable", &x) // ok to continue } } } if key == nil { - check.errorf(x.pos(), _InvalidRangeExpr, "cannot range over %s", &x) + check.errorf(&x, _InvalidRangeExpr, "cannot range over %s", &x) // ok to continue } @@ -825,7 +825,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { vars = append(vars, obj) } } else { - check.invalidAST(lhs.Pos(), "cannot declare %s", lhs) + check.invalidAST(lhs, "cannot declare %s", lhs) obj = NewVar(lhs.Pos(), check.pkg, "_", nil) // dummy variable } @@ -852,7 +852,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.declare(check.scope, nil /* recordDef already called */, obj, scopePos) } } else { - check.error(s.TokPos, _NoNewVar, "no new variables on left side of :=") + check.error(inNode(s, s.TokPos), _NoNewVar, "no new variables on left side of :=") } } else { // ordinary assignment @@ -872,6 +872,6 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.stmt(inner, s.Body) default: - check.invalidAST(s.Pos(), "invalid statement") + check.invalidAST(s, "invalid statement") } } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index b03870477d2..2b398010f4d 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -28,9 +28,9 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) scope, obj := check.scope.LookupParent(e.Name, check.pos) if obj == nil { if e.Name == "_" { - check.errorf(e.Pos(), _InvalidBlank, "cannot use _ as value or type") + check.errorf(e, _InvalidBlank, "cannot use _ as value or type") } else { - check.errorf(e.Pos(), _UndeclaredName, "undeclared name: %s", e.Name) + check.errorf(e, _UndeclaredName, "undeclared name: %s", e.Name) } return } @@ -61,7 +61,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) switch obj := obj.(type) { case *PkgName: - check.errorf(e.Pos(), _InvalidPkgUse, "use of package %s not in selector", obj.name) + check.errorf(e, _InvalidPkgUse, "use of package %s not in selector", obj.name) return case *Const: @@ -71,7 +71,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) } if obj == universeIota { if check.iota == nil { - check.errorf(e.Pos(), _InvalidIota, "cannot use iota outside constant declaration") + check.errorf(e, _InvalidIota, "cannot use iota outside constant declaration") return } x.val = check.iota @@ -159,11 +159,11 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast var recv *Var switch len(recvList) { case 0: - check.error(recvPar.Pos(), _BadRecv, "method is missing receiver") + check.error(recvPar, _BadRecv, "method is missing receiver") recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below default: // more than one receiver - check.error(recvList[len(recvList)-1].Pos(), _BadRecv, "method must have exactly one receiver") + check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver") fallthrough // continue with first receiver case 1: recv = recvList[0] @@ -194,7 +194,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast err = "basic or unnamed type" } if err != "" { - check.errorf(recv.pos, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err) + check.errorf(recv, _InvalidRecv, "invalid receiver %s (%s)", recv.typ, err) // ok to continue } } @@ -227,9 +227,9 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { case invalid: // ignore - error reported before case novalue: - check.errorf(x.pos(), _NotAType, "%s used as type", &x) + check.errorf(&x, _NotAType, "%s used as type", &x) default: - check.errorf(x.pos(), _NotAType, "%s is not a type", &x) + check.errorf(&x, _NotAType, "%s is not a type", &x) } case *ast.SelectorExpr: @@ -244,9 +244,9 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { case invalid: // ignore - error reported before case novalue: - check.errorf(x.pos(), _NotAType, "%s used as type", &x) + check.errorf(&x, _NotAType, "%s used as type", &x) default: - check.errorf(x.pos(), _NotAType, "%s is not a type", &x) + check.errorf(&x, _NotAType, "%s is not a type", &x) } case *ast.ParenExpr: @@ -306,7 +306,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { // it is safe to continue in any case (was issue 6667). check.atEnd(func() { if !Comparable(typ.key) { - check.errorf(e.Key.Pos(), _IncomparableMapKey, "incomparable map key type %s", typ.key) + check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s", typ.key) } }) @@ -325,7 +325,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { case ast.RECV: dir = RecvOnly default: - check.invalidAST(e.Pos(), "unknown channel direction %d", e.Dir) + check.invalidAST(e, "unknown channel direction %d", e.Dir) // ok to continue } @@ -334,7 +334,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { return typ default: - check.errorf(e.Pos(), _NotAType, "%s is not a type", e) + check.errorf(e, _NotAType, "%s is not a type", e) } typ := Typ[Invalid] @@ -353,7 +353,7 @@ func (check *Checker) typOrNil(e ast.Expr) Type { case invalid: // ignore - error reported before case novalue: - check.errorf(x.pos(), _NotAType, "%s used as type", &x) + check.errorf(&x, _NotAType, "%s used as type", &x) case typexpr: return x.typ case value: @@ -362,7 +362,7 @@ func (check *Checker) typOrNil(e ast.Expr) Type { } fallthrough default: - check.errorf(x.pos(), _NotAType, "%s is not a type", &x) + check.errorf(&x, _NotAType, "%s is not a type", &x) } return Typ[Invalid] } @@ -375,7 +375,7 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { check.expr(&x, e) if x.mode != constant_ { if x.mode != invalid { - check.errorf(x.pos(), _InvalidArrayLen, "array length %s must be constant", &x) + check.errorf(&x, _InvalidArrayLen, "array length %s must be constant", &x) } return -1 } @@ -385,12 +385,12 @@ func (check *Checker) arrayLength(e ast.Expr) int64 { if n, ok := constant.Int64Val(val); ok && n >= 0 { return n } - check.errorf(x.pos(), _InvalidArrayLen, "invalid array length %s", &x) + check.errorf(&x, _InvalidArrayLen, "invalid array length %s", &x) return -1 } } } - check.errorf(x.pos(), _InvalidArrayLen, "array length %s must be integer", &x) + check.errorf(&x, _InvalidArrayLen, "array length %s must be integer", &x) return -1 } @@ -407,7 +407,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO if variadicOk && i == len(list.List)-1 && len(field.Names) <= 1 { variadic = true } else { - check.softErrorf(t.Pos(), _MisplacedDotDotDot, "can only use ... with final parameter in list") + check.softErrorf(t, _MisplacedDotDotDot, "can only use ... with final parameter in list") // ignore ... and continue } } @@ -418,7 +418,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO // named parameter for _, name := range field.Names { if name.Name == "" { - check.invalidAST(name.Pos(), "anonymous parameter") + check.invalidAST(name, "anonymous parameter") // ok to continue } par := NewParam(name.Pos(), check.pkg, name.Name, typ) @@ -436,7 +436,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO } if named && anonymous { - check.invalidAST(list.Pos(), "list contains both named and anonymous parameters") + check.invalidAST(list, "list contains both named and anonymous parameters") // ok to continue } @@ -454,7 +454,7 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO func (check *Checker) declareInSet(oset *objset, pos token.Pos, obj Object) bool { if alt := oset.insert(obj); alt != nil { - check.errorf(pos, _DuplicateDecl, "%s redeclared", obj.Name()) + check.errorf(atPos(pos), _DuplicateDecl, "%s redeclared", obj.Name()) check.reportAltDecl(alt) return false } @@ -469,7 +469,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d // and we don't care if a constructed AST has more.) name := f.Names[0] if name.Name == "_" { - check.errorf(name.Pos(), _BlankIfaceMethod, "invalid method name _") + check.errorf(name, _BlankIfaceMethod, "invalid method name _") continue // ignore } @@ -477,7 +477,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d sig, _ := typ.(*Signature) if sig == nil { if typ != Typ[Invalid] { - check.invalidAST(f.Type.Pos(), "%s is not a method signature", typ) + check.invalidAST(f.Type, "%s is not a method signature", typ) } continue // ignore } @@ -501,7 +501,7 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d utyp := check.underlying(typ) if _, ok := utyp.(*Interface); !ok { if utyp != Typ[Invalid] { - check.errorf(f.Type.Pos(), _InvalidIfaceEmbed, "%s is not an interface", typ) + check.errorf(f.Type, _InvalidIfaceEmbed, "%s is not an interface", typ) } continue } @@ -575,14 +575,14 @@ func (check *Checker) completeInterface(ityp *Interface) { methods = append(methods, m) mpos[m] = pos case explicit: - check.errorf(pos, _DuplicateDecl, "duplicate method %s", m.name) - check.errorf(mpos[other.(*Func)], _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented + check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) + check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented default: // check method signatures after all types are computed (issue #33656) check.atEnd(func() { if !check.identical(m.typ, other.Type()) { - check.errorf(pos, _DuplicateDecl, "duplicate method %s", m.name) - check.errorf(mpos[other.(*Func)], _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented + check.errorf(atPos(pos), _DuplicateDecl, "duplicate method %s", m.name) + check.errorf(atPos(mpos[other.(*Func)]), _DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented } }) } @@ -641,7 +641,7 @@ func (check *Checker) tag(t *ast.BasicLit) string { return val } } - check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value) + check.invalidAST(t, "incorrect tag syntax: %q", t.Value) } return "" } @@ -704,7 +704,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { pos := f.Type.Pos() name := embeddedFieldIdent(f.Type) if name == nil { - check.invalidAST(pos, "embedded field type %s has no name", f.Type) + check.invalidAST(f.Type, "embedded field type %s has no name", f.Type) name = ast.NewIdent("_") name.NamePos = pos addInvalid(name, pos) @@ -723,19 +723,19 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) { // unsafe.Pointer is treated like a regular pointer if t.kind == UnsafePointer { - check.errorf(pos, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") + check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be unsafe.Pointer") addInvalid(name, pos) continue } case *Pointer: - check.errorf(pos, _InvalidPtrEmbed, "embedded field type cannot be a pointer") + check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer") addInvalid(name, pos) continue case *Interface: if isPtr { - check.errorf(pos, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") + check.errorf(f.Type, _InvalidPtrEmbed, "embedded field type cannot be a pointer to an interface") addInvalid(name, pos) continue } From 8e5778ed70ec3d371615a663520a586745fb7bee Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 5 Nov 2020 14:19:47 -0500 Subject: [PATCH 368/403] cmd/link: report error if builtin referenced but not defined When the compiler refers to a runtime builtin, it emits an indexed symbol reference in the object file via predetermined/preassigned ID within the PkgIdxBuiltin pseudo-package. At link time when the loader encounters these references, it redirects them to the corresponding defined symbol in the runtime package. This redirection process currently assumes that if a runtime builtin is referenced, we'll always have a definition for it. This assumption holds in most cases, however for the builtins "runtime.racefuncenter" and "runtime.racefuncexit", we'll only see definitions if the runtime package we're linking against was built with "-race". In the bug in question, build passes "-gcflags=-race" during compilation of the main package, but doesn't pass "-race" directly to 'go build', and as a result the final link combines a race-instrumented main with a non-race runtime; this results in R_CALL relocations with zero-valued target symbols, resulting in a panic during stack checking. This patch changes the loader's resolve method to detect situations where we're asking for builtin "runtime.X", but the runtime package read in doesn't contain a definition for X. Fixes #42396. Change-Id: Iafd38bd3b0f7f462868d120ccd4d7d1b88b27436 Reviewed-on: https://go-review.googlesource.com/c/go/+/267881 Trust: Than McIntosh Run-TryBot: Than McIntosh Reviewed-by: Jeremy Faller Reviewed-by: Cherry Zhang TryBot-Result: Go Bot --- src/cmd/link/internal/loader/loader.go | 29 +++++++++++++- src/cmd/link/link_test.go | 52 ++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index d861efcb13a..971cc432ff5 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -633,7 +633,11 @@ func (l *Loader) resolve(r *oReader, s goobj.SymRef) Sym { i := int(s.SymIdx) + r.ndef + r.nhashed64def + r.nhasheddef return r.syms[i] case goobj.PkgIdxBuiltin: - return l.builtinSyms[s.SymIdx] + if bi := l.builtinSyms[s.SymIdx]; bi != 0 { + return bi + } + l.reportMissingBuiltin(int(s.SymIdx), r.unit.Lib.Pkg) + return 0 case goobj.PkgIdxSelf: rr = r default: @@ -642,6 +646,29 @@ func (l *Loader) resolve(r *oReader, s goobj.SymRef) Sym { return l.toGlobal(rr, s.SymIdx) } +// reportMissingBuiltin issues an error in the case where we have a +// relocation against a runtime builtin whose definition is not found +// when the runtime package is built. The canonical example is +// "runtime.racefuncenter" -- currently if you do something like +// +// go build -gcflags=-race myprogram.go +// +// the compiler will insert calls to the builtin runtime.racefuncenter, +// but the version of the runtime used for linkage won't actually contain +// definitions of that symbol. See issue #42396 for details. +// +// As currently implemented, this is a fatal error. This has drawbacks +// in that if there are multiple missing builtins, the error will only +// cite the first one. On the plus side, terminating the link here has +// advantages in that we won't run the risk of panics or crashes later +// on in the linker due to R_CALL relocations with 0-valued target +// symbols. +func (l *Loader) reportMissingBuiltin(bsym int, reflib string) { + bname, _ := goobj.BuiltinName(bsym) + log.Fatalf("reference to undefined builtin %q from package %q", + bname, reflib) +} + // Look up a symbol by name, return global index, or 0 if not found. // This is more like Syms.ROLookup than Lookup -- it doesn't create // new symbol. diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 204410e9768..158c6707391 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -7,6 +7,7 @@ package main import ( "bufio" "bytes" + "cmd/internal/sys" "debug/macho" "internal/testenv" "io/ioutil" @@ -873,3 +874,54 @@ func TestIssue38554(t *testing.T) { t.Errorf("binary too big: got %d, want < %d", got, want) } } + +const testIssue42396src = ` +package main + +//go:noinline +//go:nosplit +func callee(x int) { +} + +func main() { + callee(9) +} +` + +func TestIssue42396(t *testing.T) { + testenv.MustHaveGoBuild(t) + + if !sys.RaceDetectorSupported(runtime.GOOS, runtime.GOARCH) { + t.Skip("no race detector support") + } + + t.Parallel() + + tmpdir, err := ioutil.TempDir("", "TestIssue42396") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmpdir) + + src := filepath.Join(tmpdir, "main.go") + err = ioutil.WriteFile(src, []byte(testIssue42396src), 0666) + if err != nil { + t.Fatalf("failed to write source file: %v", err) + } + exe := filepath.Join(tmpdir, "main.exe") + cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags=-race", "-o", exe, src) + out, err := cmd.CombinedOutput() + if err == nil { + t.Fatalf("build unexpectedly succeeded") + } + + // Check to make sure that we see a reasonable error message + // and not a panic. + if strings.Contains(string(out), "panic:") { + t.Fatalf("build should not fail with panic:\n%s", out) + } + const want = "reference to undefined builtin" + if !strings.Contains(string(out), want) { + t.Fatalf("error message incorrect: expected it to contain %q but instead got:\n%s\n", want, out) + } +} From ecc3f5112ebaf23c4b1ac4c5eedfa406d82ecc9a Mon Sep 17 00:00:00 2001 From: Jonathan Swinney Date: Wed, 4 Nov 2020 16:18:23 +0000 Subject: [PATCH 369/403] cmd/compile: improve atomic swap intrinsics on arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ARMv8.1 has added new instructions for atomic memory operations. This change builds on the previous change which added support for atomic add, 0a7ac93c27c9ade79fe0f66ae0bb81484c241ae5, to include similar support for atomic-compare-and-swap, atomic-swap, atomic-or, and atomic-and intrinsics. Since the new instructions are not guaranteed to be present, we guard their usages with a branch on a CPU feature. Peformance on an ARMv8.1 machine: name old time/op new time/op delta CompareAndSwap-16 37.9ns ±16% 24.1ns ± 4% -36.44% (p=0.000 n=10+9) CompareAndSwap64-16 38.6ns ±15% 24.1ns ± 3% -37.47% (p=0.000 n=10+10) name old time/op new time/op delta Swap-16 46.9ns ±32% 12.5ns ± 6% -73.40% (p=0.000 n=10+10) Swap64-16 53.4ns ± 1% 12.5ns ± 6% -76.56% (p=0.000 n=10+10) name old time/op new time/op delta Or8-16 8.81ns ± 0% 5.61ns ± 0% -36.32% (p=0.000 n=10+10) Or-16 7.21ns ± 0% 5.61ns ± 0% -22.19% (p=0.000 n=10+10) Or8Parallel-16 59.8ns ± 3% 12.5ns ± 2% -79.10% (p=0.000 n=10+10) OrParallel-16 51.7ns ± 3% 12.5ns ± 2% -75.84% (p=0.000 n=10+10) name old time/op new time/op delta And8-16 8.81ns ± 0% 5.61ns ± 0% -36.32% (p=0.000 n=10+10) And-16 7.21ns ± 0% 5.61ns ± 0% -22.19% (p=0.000 n=10+10) And8Parallel-16 59.1ns ± 6% 12.8ns ± 3% -78.33% (p=0.000 n=10+10) AndParallel-16 51.4ns ± 7% 12.8ns ± 3% -75.03% (p=0.000 n=10+10) Performance on an ARMv8.0 machine (no atomics instructions): name old time/op new time/op delta CompareAndSwap-16 61.3ns ± 0% 62.4ns ± 0% +1.70% (p=0.000 n=8+9) CompareAndSwap64-16 62.0ns ± 3% 61.3ns ± 2% ~ (p=0.093 n=10+10) name old time/op new time/op delta Swap-16 127ns ± 2% 131ns ± 2% +2.91% (p=0.001 n=10+10) Swap64-16 128ns ± 1% 131ns ± 2% +2.43% (p=0.001 n=10+10) name old time/op new time/op delta Or8-16 14.9ns ± 0% 15.3ns ± 0% +2.68% (p=0.000 n=10+10) Or-16 11.8ns ± 0% 12.3ns ± 0% +4.24% (p=0.000 n=10+10) Or8Parallel-16 137ns ± 1% 144ns ± 1% +4.97% (p=0.000 n=10+10) OrParallel-16 128ns ± 1% 136ns ± 1% +6.34% (p=0.000 n=10+10) name old time/op new time/op delta And8-16 14.9ns ± 0% 15.3ns ± 0% +2.68% (p=0.000 n=10+10) And-16 11.8ns ± 0% 12.3ns ± 0% +4.24% (p=0.000 n=10+10) And8Parallel-16 134ns ± 2% 141ns ± 1% +5.29% (p=0.000 n=10+10) AndParallel-16 125ns ± 2% 134ns ± 1% +7.10% (p=0.000 n=10+10) Fixes #39304 Change-Id: Idaca68701d4751650be6b4bedca3d57f51571712 Reviewed-on: https://go-review.googlesource.com/c/go/+/234217 Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Reviewed-by: Cherry Zhang Trust: fannie zhang --- src/cmd/compile/internal/arm64/ssa.go | 125 +++++++++++ src/cmd/compile/internal/gc/ssa.go | 133 ++++++++---- src/cmd/compile/internal/ssa/gen/ARM64.rules | 13 +- src/cmd/compile/internal/ssa/gen/ARM64Ops.go | 35 +++ .../compile/internal/ssa/gen/genericOps.go | 12 +- src/cmd/compile/internal/ssa/opGen.go | 200 ++++++++++++++++++ src/cmd/compile/internal/ssa/rewriteARM64.go | 96 +++++++++ src/runtime/internal/atomic/bench_test.go | 51 +++++ 8 files changed, 616 insertions(+), 49 deletions(-) diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 5c695ef84cb..22b28a9308b 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -581,6 +581,24 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p2.From.Reg = arm64.REGTMP p2.To.Type = obj.TYPE_BRANCH gc.Patch(p2, p) + case ssa.OpARM64LoweredAtomicExchange64Variant, + ssa.OpARM64LoweredAtomicExchange32Variant: + swap := arm64.ASWPALD + if v.Op == ssa.OpARM64LoweredAtomicExchange32Variant { + swap = arm64.ASWPALW + } + r0 := v.Args[0].Reg() + r1 := v.Args[1].Reg() + out := v.Reg0() + + // SWPALD Rarg1, (Rarg0), Rout + p := s.Prog(swap) + p.From.Type = obj.TYPE_REG + p.From.Reg = r1 + p.To.Type = obj.TYPE_MEM + p.To.Reg = r0 + p.RegTo2 = out + case ssa.OpARM64LoweredAtomicAdd64, ssa.OpARM64LoweredAtomicAdd32: // LDAXR (Rarg0), Rout @@ -687,6 +705,56 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p5.To.Type = obj.TYPE_REG p5.To.Reg = out gc.Patch(p2, p5) + case ssa.OpARM64LoweredAtomicCas64Variant, + ssa.OpARM64LoweredAtomicCas32Variant: + // Rarg0: ptr + // Rarg1: old + // Rarg2: new + // MOV Rarg1, Rtmp + // CASAL Rtmp, (Rarg0), Rarg2 + // CMP Rarg1, Rtmp + // CSET EQ, Rout + cas := arm64.ACASALD + cmp := arm64.ACMP + mov := arm64.AMOVD + if v.Op == ssa.OpARM64LoweredAtomicCas32Variant { + cas = arm64.ACASALW + cmp = arm64.ACMPW + mov = arm64.AMOVW + } + r0 := v.Args[0].Reg() + r1 := v.Args[1].Reg() + r2 := v.Args[2].Reg() + out := v.Reg0() + + // MOV Rarg1, Rtmp + p := s.Prog(mov) + p.From.Type = obj.TYPE_REG + p.From.Reg = r1 + p.To.Type = obj.TYPE_REG + p.To.Reg = arm64.REGTMP + + // CASAL Rtmp, (Rarg0), Rarg2 + p1 := s.Prog(cas) + p1.From.Type = obj.TYPE_REG + p1.From.Reg = arm64.REGTMP + p1.To.Type = obj.TYPE_MEM + p1.To.Reg = r0 + p1.RegTo2 = r2 + + // CMP Rarg1, Rtmp + p2 := s.Prog(cmp) + p2.From.Type = obj.TYPE_REG + p2.From.Reg = r1 + p2.Reg = arm64.REGTMP + + // CSET EQ, Rout + p3 := s.Prog(arm64.ACSET) + p3.From.Type = obj.TYPE_REG + p3.From.Reg = arm64.COND_EQ + p3.To.Type = obj.TYPE_REG + p3.To.Reg = out + case ssa.OpARM64LoweredAtomicAnd8, ssa.OpARM64LoweredAtomicAnd32, ssa.OpARM64LoweredAtomicOr8, @@ -725,6 +793,63 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p3.From.Reg = arm64.REGTMP p3.To.Type = obj.TYPE_BRANCH gc.Patch(p3, p) + case ssa.OpARM64LoweredAtomicAnd8Variant, + ssa.OpARM64LoweredAtomicAnd32Variant: + atomic_clear := arm64.ALDCLRALW + if v.Op == ssa.OpARM64LoweredAtomicAnd8Variant { + atomic_clear = arm64.ALDCLRALB + } + r0 := v.Args[0].Reg() + r1 := v.Args[1].Reg() + out := v.Reg0() + + // MNV Rarg1 Rtemp + p := s.Prog(arm64.AMVN) + p.From.Type = obj.TYPE_REG + p.From.Reg = r1 + p.To.Type = obj.TYPE_REG + p.To.Reg = arm64.REGTMP + + // LDCLRALW Rtemp, (Rarg0), Rout + p1 := s.Prog(atomic_clear) + p1.From.Type = obj.TYPE_REG + p1.From.Reg = arm64.REGTMP + p1.To.Type = obj.TYPE_MEM + p1.To.Reg = r0 + p1.RegTo2 = out + + // AND Rarg1, Rout + p2 := s.Prog(arm64.AAND) + p2.From.Type = obj.TYPE_REG + p2.From.Reg = r1 + p2.To.Type = obj.TYPE_REG + p2.To.Reg = out + + case ssa.OpARM64LoweredAtomicOr8Variant, + ssa.OpARM64LoweredAtomicOr32Variant: + atomic_or := arm64.ALDORALW + if v.Op == ssa.OpARM64LoweredAtomicOr8Variant { + atomic_or = arm64.ALDORALB + } + r0 := v.Args[0].Reg() + r1 := v.Args[1].Reg() + out := v.Reg0() + + // LDORALW Rarg1, (Rarg0), Rout + p := s.Prog(atomic_or) + p.From.Type = obj.TYPE_REG + p.From.Reg = r1 + p.To.Type = obj.TYPE_MEM + p.To.Reg = r0 + p.RegTo2 = out + + // ORR Rarg1, Rout + p2 := s.Prog(arm64.AORR) + p2.From.Type = obj.TYPE_REG + p2.From.Reg = r1 + p2.To.Type = obj.TYPE_REG + p2.To.Reg = out + case ssa.OpARM64MOVBreg, ssa.OpARM64MOVBUreg, ssa.OpARM64MOVHreg, diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 67484904a95..0b38e70cd2a 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -3458,14 +3458,64 @@ func init() { s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v) }, - sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) + sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Xchg64", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { v := s.newValue3(ssa.OpAtomicExchange64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], args[1], s.mem()) s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v) }, - sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) + sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) + + type atomicOpEmitter func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) + + makeAtomicGuardedIntrinsicARM64 := func(op0, op1 ssa.Op, typ, rtyp types.EType, emit atomicOpEmitter) intrinsicBuilder { + + return func(s *state, n *Node, args []*ssa.Value) *ssa.Value { + // Target Atomic feature is identified by dynamic detection + addr := s.entryNewValue1A(ssa.OpAddr, types.Types[TBOOL].PtrTo(), arm64HasATOMICS, s.sb) + v := s.load(types.Types[TBOOL], addr) + b := s.endBlock() + b.Kind = ssa.BlockIf + b.SetControl(v) + bTrue := s.f.NewBlock(ssa.BlockPlain) + bFalse := s.f.NewBlock(ssa.BlockPlain) + bEnd := s.f.NewBlock(ssa.BlockPlain) + b.AddEdgeTo(bTrue) + b.AddEdgeTo(bFalse) + b.Likely = ssa.BranchLikely + + // We have atomic instructions - use it directly. + s.startBlock(bTrue) + emit(s, n, args, op1, typ) + s.endBlock().AddEdgeTo(bEnd) + + // Use original instruction sequence. + s.startBlock(bFalse) + emit(s, n, args, op0, typ) + s.endBlock().AddEdgeTo(bEnd) + + // Merge results. + s.startBlock(bEnd) + if rtyp == TNIL { + return nil + } else { + return s.variable(n, types.Types[rtyp]) + } + } + } + + atomicXchgXaddEmitterARM64 := func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + v := s.newValue3(op, types.NewTuple(types.Types[typ], types.TypeMem), args[0], args[1], s.mem()) + s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) + s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v) + } + addF("runtime/internal/atomic", "Xchg", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange32, ssa.OpAtomicExchange32Variant, TUINT32, TUINT32, atomicXchgXaddEmitterARM64), + sys.ARM64) + addF("runtime/internal/atomic", "Xchg64", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicExchange64, ssa.OpAtomicExchange64Variant, TUINT64, TUINT64, atomicXchgXaddEmitterARM64), + sys.ARM64) addF("runtime/internal/atomic", "Xadd", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { @@ -3482,46 +3532,11 @@ func init() { }, sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) - makeXaddARM64 := func(op0 ssa.Op, op1 ssa.Op, ty types.EType) func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - return func(s *state, n *Node, args []*ssa.Value) *ssa.Value { - // Target Atomic feature is identified by dynamic detection - addr := s.entryNewValue1A(ssa.OpAddr, types.Types[TBOOL].PtrTo(), arm64HasATOMICS, s.sb) - v := s.load(types.Types[TBOOL], addr) - b := s.endBlock() - b.Kind = ssa.BlockIf - b.SetControl(v) - bTrue := s.f.NewBlock(ssa.BlockPlain) - bFalse := s.f.NewBlock(ssa.BlockPlain) - bEnd := s.f.NewBlock(ssa.BlockPlain) - b.AddEdgeTo(bTrue) - b.AddEdgeTo(bFalse) - b.Likely = ssa.BranchUnlikely // most machines don't have Atomics nowadays - - // We have atomic instructions - use it directly. - s.startBlock(bTrue) - v0 := s.newValue3(op1, types.NewTuple(types.Types[ty], types.TypeMem), args[0], args[1], s.mem()) - s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v0) - s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[ty], v0) - s.endBlock().AddEdgeTo(bEnd) - - // Use original instruction sequence. - s.startBlock(bFalse) - v1 := s.newValue3(op0, types.NewTuple(types.Types[ty], types.TypeMem), args[0], args[1], s.mem()) - s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v1) - s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[ty], v1) - s.endBlock().AddEdgeTo(bEnd) - - // Merge results. - s.startBlock(bEnd) - return s.variable(n, types.Types[ty]) - } - } - addF("runtime/internal/atomic", "Xadd", - makeXaddARM64(ssa.OpAtomicAdd32, ssa.OpAtomicAdd32Variant, TUINT32), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd32, ssa.OpAtomicAdd32Variant, TUINT32, TUINT32, atomicXchgXaddEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Xadd64", - makeXaddARM64(ssa.OpAtomicAdd64, ssa.OpAtomicAdd64Variant, TUINT64), + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAdd64, ssa.OpAtomicAdd64Variant, TUINT64, TUINT64, atomicXchgXaddEmitterARM64), sys.ARM64) addF("runtime/internal/atomic", "Cas", @@ -3530,14 +3545,14 @@ func init() { s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, types.Types[TBOOL], v) }, - sys.AMD64, sys.ARM64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) + sys.AMD64, sys.MIPS, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "Cas64", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { v := s.newValue4(ssa.OpAtomicCompareAndSwap64, types.NewTuple(types.Types[TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) return s.newValue1(ssa.OpSelect0, types.Types[TBOOL], v) }, - sys.AMD64, sys.ARM64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) + sys.AMD64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) addF("runtime/internal/atomic", "CasRel", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { v := s.newValue4(ssa.OpAtomicCompareAndSwap32, types.NewTuple(types.Types[TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) @@ -3546,18 +3561,31 @@ func init() { }, sys.PPC64) + atomicCasEmitterARM64 := func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + v := s.newValue4(op, types.NewTuple(types.Types[TBOOL], types.TypeMem), args[0], args[1], args[2], s.mem()) + s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v) + s.vars[n] = s.newValue1(ssa.OpSelect0, types.Types[typ], v) + } + + addF("runtime/internal/atomic", "Cas", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap32, ssa.OpAtomicCompareAndSwap32Variant, TUINT32, TBOOL, atomicCasEmitterARM64), + sys.ARM64) + addF("runtime/internal/atomic", "Cas64", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicCompareAndSwap64, ssa.OpAtomicCompareAndSwap64Variant, TUINT64, TBOOL, atomicCasEmitterARM64), + sys.ARM64) + addF("runtime/internal/atomic", "And8", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { s.vars[&memVar] = s.newValue3(ssa.OpAtomicAnd8, types.TypeMem, args[0], args[1], s.mem()) return nil }, - sys.AMD64, sys.ARM64, sys.MIPS, sys.PPC64, sys.S390X) + sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X) addF("runtime/internal/atomic", "And", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { s.vars[&memVar] = s.newValue3(ssa.OpAtomicAnd32, types.TypeMem, args[0], args[1], s.mem()) return nil }, - sys.AMD64, sys.ARM64, sys.MIPS, sys.PPC64, sys.S390X) + sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X) addF("runtime/internal/atomic", "Or8", func(s *state, n *Node, args []*ssa.Value) *ssa.Value { s.vars[&memVar] = s.newValue3(ssa.OpAtomicOr8, types.TypeMem, args[0], args[1], s.mem()) @@ -3569,7 +3597,24 @@ func init() { s.vars[&memVar] = s.newValue3(ssa.OpAtomicOr32, types.TypeMem, args[0], args[1], s.mem()) return nil }, - sys.AMD64, sys.ARM64, sys.MIPS, sys.PPC64, sys.S390X) + sys.AMD64, sys.MIPS, sys.PPC64, sys.S390X) + + atomicAndOrEmitterARM64 := func(s *state, n *Node, args []*ssa.Value, op ssa.Op, typ types.EType) { + s.vars[&memVar] = s.newValue3(op, types.TypeMem, args[0], args[1], s.mem()) + } + + addF("runtime/internal/atomic", "And8", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd8, ssa.OpAtomicAnd8Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + sys.ARM64) + addF("runtime/internal/atomic", "And", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicAnd32, ssa.OpAtomicAnd32Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + sys.ARM64) + addF("runtime/internal/atomic", "Or8", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr8, ssa.OpAtomicOr8Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + sys.ARM64) + addF("runtime/internal/atomic", "Or", + makeAtomicGuardedIntrinsicARM64(ssa.OpAtomicOr32, ssa.OpAtomicOr32Variant, TNIL, TNIL, atomicAndOrEmitterARM64), + sys.ARM64) alias("runtime/internal/atomic", "Loadint64", "runtime/internal/atomic", "Load64", all...) alias("runtime/internal/atomic", "Xaddint64", "runtime/internal/atomic", "Xadd64", all...) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules index 7e014fe0a8d..9edc0c94b00 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules @@ -543,17 +543,24 @@ (AtomicStore64 ...) => (STLR ...) (AtomicStorePtrNoWB ...) => (STLR ...) -(AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...) -(AtomicAdd(32|64) ...) => (LoweredAtomicAdd(32|64) ...) +(AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...) +(AtomicAdd(32|64) ...) => (LoweredAtomicAdd(32|64) ...) (AtomicCompareAndSwap(32|64) ...) => (LoweredAtomicCas(32|64) ...) +(AtomicAdd(32|64)Variant ...) => (LoweredAtomicAdd(32|64)Variant ...) +(AtomicExchange(32|64)Variant ...) => (LoweredAtomicExchange(32|64)Variant ...) +(AtomicCompareAndSwap(32|64)Variant ...) => (LoweredAtomicCas(32|64)Variant ...) + // Currently the updated value is not used, but we need a register to temporarily hold it. (AtomicAnd8 ptr val mem) => (Select1 (LoweredAtomicAnd8 ptr val mem)) (AtomicAnd32 ptr val mem) => (Select1 (LoweredAtomicAnd32 ptr val mem)) (AtomicOr8 ptr val mem) => (Select1 (LoweredAtomicOr8 ptr val mem)) (AtomicOr32 ptr val mem) => (Select1 (LoweredAtomicOr32 ptr val mem)) -(AtomicAdd(32|64)Variant ...) => (LoweredAtomicAdd(32|64)Variant ...) +(AtomicAnd8Variant ptr val mem) => (Select1 (LoweredAtomicAnd8Variant ptr val mem)) +(AtomicAnd32Variant ptr val mem) => (Select1 (LoweredAtomicAnd32Variant ptr val mem)) +(AtomicOr8Variant ptr val mem) => (Select1 (LoweredAtomicOr8Variant ptr val mem)) +(AtomicOr32Variant ptr val mem) => (Select1 (LoweredAtomicOr32Variant ptr val mem)) // Write barrier. (WB ...) => (LoweredWB ...) diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go index fe9edbf9333..87db2b7c9d9 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go +++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go @@ -621,6 +621,12 @@ func init() { {name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, {name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, + // atomic exchange variant. + // store arg1 to arg0. arg2=mem. returns . auxint must be zero. + // SWPALD Rarg1, (Rarg0), Rout + {name: "LoweredAtomicExchange64Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true}, + {name: "LoweredAtomicExchange32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true}, + // atomic add. // *arg0 += arg1. arg2=mem. returns . auxint must be zero. // LDAXR (Rarg0), Rout @@ -654,6 +660,21 @@ func init() { {name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, {name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, + // atomic compare and swap variant. + // arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero. + // if *arg0 == arg1 { + // *arg0 = arg2 + // return (true, memory) + // } else { + // return (false, memory) + // } + // MOV Rarg1, Rtmp + // CASAL Rtmp, (Rarg0), Rarg2 + // CMP Rarg1, Rtmp + // CSET EQ, Rout + {name: "LoweredAtomicCas64Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, + {name: "LoweredAtomicCas32Variant", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, + // atomic and/or. // *arg0 &= (|=) arg1. arg2=mem. returns . auxint must be zero. // LDAXR (Rarg0), Rout @@ -665,6 +686,20 @@ func init() { {name: "LoweredAtomicOr8", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, {name: "LoweredAtomicOr32", argLength: 3, reg: gpxchg, resultNotInArgs: true, asm: "ORR", typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, + // atomic and/or variant. + // *arg0 &= (|=) arg1. arg2=mem. returns . auxint must be zero. + // AND: + // MNV Rarg1, Rtemp + // LDANDALB Rtemp, (Rarg0), Rout + // AND Rarg1, Rout + // OR: + // LDORALB Rarg1, (Rarg0), Rout + // ORR Rarg1, Rout + {name: "LoweredAtomicAnd8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, + {name: "LoweredAtomicAnd32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true, unsafePoint: true}, + {name: "LoweredAtomicOr8Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt8,Mem)", faultOnNilArg0: true, hasSideEffects: true}, + {name: "LoweredAtomicOr32Variant", argLength: 3, reg: gpxchg, resultNotInArgs: true, typ: "(UInt32,Mem)", faultOnNilArg0: true, hasSideEffects: true}, + // LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier // It saves all GP registers if necessary, // but clobbers R30 (LR) because it's a call. diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go index db8d7ba0cf0..9565199d516 100644 --- a/src/cmd/compile/internal/ssa/gen/genericOps.go +++ b/src/cmd/compile/internal/ssa/gen/genericOps.go @@ -574,8 +574,16 @@ var genericOps = []opData{ // These variants have the same semantics as above atomic operations. // But they are used for generating more efficient code on certain modern machines, with run-time CPU feature detection. // Currently, they are used on ARM64 only. - {name: "AtomicAdd32Variant", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory. - {name: "AtomicAdd64Variant", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory. + {name: "AtomicAdd32Variant", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory. + {name: "AtomicAdd64Variant", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory. + {name: "AtomicExchange32Variant", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory. + {name: "AtomicExchange64Variant", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory. + {name: "AtomicCompareAndSwap32Variant", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory. + {name: "AtomicCompareAndSwap64Variant", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2. Returns true if store happens and new memory. + {name: "AtomicAnd8Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory. + {name: "AtomicAnd32Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 &= arg1. arg2=memory. Returns memory. + {name: "AtomicOr8Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory. + {name: "AtomicOr32Variant", argLength: 3, typ: "Mem", hasSideEffects: true}, // *arg0 |= arg1. arg2=memory. Returns memory. // Clobber experiment op {name: "Clobber", argLength: 0, typ: "Void", aux: "SymOff", symEffect: "None"}, // write an invalid pointer value to the given pointer slot of a stack variable diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 25c1df12eed..c0b663cd8f6 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -1581,16 +1581,24 @@ const ( OpARM64STLRW OpARM64LoweredAtomicExchange64 OpARM64LoweredAtomicExchange32 + OpARM64LoweredAtomicExchange64Variant + OpARM64LoweredAtomicExchange32Variant OpARM64LoweredAtomicAdd64 OpARM64LoweredAtomicAdd32 OpARM64LoweredAtomicAdd64Variant OpARM64LoweredAtomicAdd32Variant OpARM64LoweredAtomicCas64 OpARM64LoweredAtomicCas32 + OpARM64LoweredAtomicCas64Variant + OpARM64LoweredAtomicCas32Variant OpARM64LoweredAtomicAnd8 OpARM64LoweredAtomicAnd32 OpARM64LoweredAtomicOr8 OpARM64LoweredAtomicOr32 + OpARM64LoweredAtomicAnd8Variant + OpARM64LoweredAtomicAnd32Variant + OpARM64LoweredAtomicOr8Variant + OpARM64LoweredAtomicOr32Variant OpARM64LoweredWB OpARM64LoweredPanicBoundsA OpARM64LoweredPanicBoundsB @@ -2881,6 +2889,14 @@ const ( OpAtomicOr32 OpAtomicAdd32Variant OpAtomicAdd64Variant + OpAtomicExchange32Variant + OpAtomicExchange64Variant + OpAtomicCompareAndSwap32Variant + OpAtomicCompareAndSwap64Variant + OpAtomicAnd8Variant + OpAtomicAnd32Variant + OpAtomicOr8Variant + OpAtomicOr32Variant OpClobber ) @@ -20994,6 +21010,38 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "LoweredAtomicExchange64Variant", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "LoweredAtomicExchange32Variant", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "LoweredAtomicAdd64", argLen: 3, @@ -21098,6 +21146,44 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "LoweredAtomicCas64Variant", + argLen: 4, + resultNotInArgs: true, + clobberFlags: true, + faultOnNilArg0: true, + hasSideEffects: true, + unsafePoint: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "LoweredAtomicCas32Variant", + argLen: 4, + resultNotInArgs: true, + clobberFlags: true, + faultOnNilArg0: true, + hasSideEffects: true, + unsafePoint: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {2, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "LoweredAtomicAnd8", argLen: 3, @@ -21170,6 +21256,72 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "LoweredAtomicAnd8Variant", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + unsafePoint: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "LoweredAtomicAnd32Variant", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + unsafePoint: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "LoweredAtomicOr8Variant", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, + { + name: "LoweredAtomicOr32Variant", + argLen: 3, + resultNotInArgs: true, + faultOnNilArg0: true, + hasSideEffects: true, + reg: regInfo{ + inputs: []inputInfo{ + {1, 805044223}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 + {0, 9223372038733561855}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30 SP SB + }, + outputs: []outputInfo{ + {0, 670826495}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30 + }, + }, + }, { name: "LoweredWB", auxType: auxSym, @@ -35874,6 +36026,54 @@ var opcodeTable = [...]opInfo{ hasSideEffects: true, generic: true, }, + { + name: "AtomicExchange32Variant", + argLen: 3, + hasSideEffects: true, + generic: true, + }, + { + name: "AtomicExchange64Variant", + argLen: 3, + hasSideEffects: true, + generic: true, + }, + { + name: "AtomicCompareAndSwap32Variant", + argLen: 4, + hasSideEffects: true, + generic: true, + }, + { + name: "AtomicCompareAndSwap64Variant", + argLen: 4, + hasSideEffects: true, + generic: true, + }, + { + name: "AtomicAnd8Variant", + argLen: 3, + hasSideEffects: true, + generic: true, + }, + { + name: "AtomicAnd32Variant", + argLen: 3, + hasSideEffects: true, + generic: true, + }, + { + name: "AtomicOr8Variant", + argLen: 3, + hasSideEffects: true, + generic: true, + }, + { + name: "AtomicOr32Variant", + argLen: 3, + hasSideEffects: true, + generic: true, + }, { name: "Clobber", auxType: auxSymOff, diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go index 9a5e976deac..353696bf393 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM64.go +++ b/src/cmd/compile/internal/ssa/rewriteARM64.go @@ -426,20 +426,36 @@ func rewriteValueARM64(v *Value) bool { return true case OpAtomicAnd32: return rewriteValueARM64_OpAtomicAnd32(v) + case OpAtomicAnd32Variant: + return rewriteValueARM64_OpAtomicAnd32Variant(v) case OpAtomicAnd8: return rewriteValueARM64_OpAtomicAnd8(v) + case OpAtomicAnd8Variant: + return rewriteValueARM64_OpAtomicAnd8Variant(v) case OpAtomicCompareAndSwap32: v.Op = OpARM64LoweredAtomicCas32 return true + case OpAtomicCompareAndSwap32Variant: + v.Op = OpARM64LoweredAtomicCas32Variant + return true case OpAtomicCompareAndSwap64: v.Op = OpARM64LoweredAtomicCas64 return true + case OpAtomicCompareAndSwap64Variant: + v.Op = OpARM64LoweredAtomicCas64Variant + return true case OpAtomicExchange32: v.Op = OpARM64LoweredAtomicExchange32 return true + case OpAtomicExchange32Variant: + v.Op = OpARM64LoweredAtomicExchange32Variant + return true case OpAtomicExchange64: v.Op = OpARM64LoweredAtomicExchange64 return true + case OpAtomicExchange64Variant: + v.Op = OpARM64LoweredAtomicExchange64Variant + return true case OpAtomicLoad32: v.Op = OpARM64LDARW return true @@ -454,8 +470,12 @@ func rewriteValueARM64(v *Value) bool { return true case OpAtomicOr32: return rewriteValueARM64_OpAtomicOr32(v) + case OpAtomicOr32Variant: + return rewriteValueARM64_OpAtomicOr32Variant(v) case OpAtomicOr8: return rewriteValueARM64_OpAtomicOr8(v) + case OpAtomicOr8Variant: + return rewriteValueARM64_OpAtomicOr8Variant(v) case OpAtomicStore32: v.Op = OpARM64STLRW return true @@ -21363,6 +21383,25 @@ func rewriteValueARM64_OpAtomicAnd32(v *Value) bool { return true } } +func rewriteValueARM64_OpAtomicAnd32Variant(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicAnd32Variant ptr val mem) + // result: (Select1 (LoweredAtomicAnd32Variant ptr val mem)) + for { + ptr := v_0 + val := v_1 + mem := v_2 + v.reset(OpSelect1) + v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicAnd32Variant, types.NewTuple(typ.UInt32, types.TypeMem)) + v0.AddArg3(ptr, val, mem) + v.AddArg(v0) + return true + } +} func rewriteValueARM64_OpAtomicAnd8(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -21382,6 +21421,25 @@ func rewriteValueARM64_OpAtomicAnd8(v *Value) bool { return true } } +func rewriteValueARM64_OpAtomicAnd8Variant(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicAnd8Variant ptr val mem) + // result: (Select1 (LoweredAtomicAnd8Variant ptr val mem)) + for { + ptr := v_0 + val := v_1 + mem := v_2 + v.reset(OpSelect1) + v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicAnd8Variant, types.NewTuple(typ.UInt8, types.TypeMem)) + v0.AddArg3(ptr, val, mem) + v.AddArg(v0) + return true + } +} func rewriteValueARM64_OpAtomicOr32(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -21401,6 +21459,25 @@ func rewriteValueARM64_OpAtomicOr32(v *Value) bool { return true } } +func rewriteValueARM64_OpAtomicOr32Variant(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicOr32Variant ptr val mem) + // result: (Select1 (LoweredAtomicOr32Variant ptr val mem)) + for { + ptr := v_0 + val := v_1 + mem := v_2 + v.reset(OpSelect1) + v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicOr32Variant, types.NewTuple(typ.UInt32, types.TypeMem)) + v0.AddArg3(ptr, val, mem) + v.AddArg(v0) + return true + } +} func rewriteValueARM64_OpAtomicOr8(v *Value) bool { v_2 := v.Args[2] v_1 := v.Args[1] @@ -21420,6 +21497,25 @@ func rewriteValueARM64_OpAtomicOr8(v *Value) bool { return true } } +func rewriteValueARM64_OpAtomicOr8Variant(v *Value) bool { + v_2 := v.Args[2] + v_1 := v.Args[1] + v_0 := v.Args[0] + b := v.Block + typ := &b.Func.Config.Types + // match: (AtomicOr8Variant ptr val mem) + // result: (Select1 (LoweredAtomicOr8Variant ptr val mem)) + for { + ptr := v_0 + val := v_1 + mem := v_2 + v.reset(OpSelect1) + v0 := b.NewValue0(v.Pos, OpARM64LoweredAtomicOr8Variant, types.NewTuple(typ.UInt8, types.TypeMem)) + v0.AddArg3(ptr, val, mem) + v.AddArg(v0) + return true + } +} func rewriteValueARM64_OpAvg64u(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] diff --git a/src/runtime/internal/atomic/bench_test.go b/src/runtime/internal/atomic/bench_test.go index 434aa6d4340..2476c06c52a 100644 --- a/src/runtime/internal/atomic/bench_test.go +++ b/src/runtime/internal/atomic/bench_test.go @@ -142,3 +142,54 @@ func BenchmarkXadd64(b *testing.B) { } }) } + +func BenchmarkCas(b *testing.B) { + var x uint32 + x = 1 + ptr := &x + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + atomic.Cas(ptr, 1, 0) + atomic.Cas(ptr, 0, 1) + } + }) +} + +func BenchmarkCas64(b *testing.B) { + var x uint64 + x = 1 + ptr := &x + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + atomic.Cas64(ptr, 1, 0) + atomic.Cas64(ptr, 0, 1) + } + }) +} +func BenchmarkXchg(b *testing.B) { + var x uint32 + x = 1 + ptr := &x + b.RunParallel(func(pb *testing.PB) { + var y uint32 + y = 1 + for pb.Next() { + y = atomic.Xchg(ptr, y) + y += 1 + } + }) +} + +func BenchmarkXchg64(b *testing.B) { + var x uint64 + x = 1 + ptr := &x + b.RunParallel(func(pb *testing.PB) { + var y uint64 + y = 1 + for pb.Next() { + y = atomic.Xchg64(ptr, y) + y += 1 + } + }) +} From b7e0adfee28b516a0dcceb5ecf0e5a695b38c61f Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Thu, 5 Nov 2020 16:41:32 +1100 Subject: [PATCH 370/403] cmd/dist: remove openbsd/mips64 from incomplete ports Remove openbsd/mips64 from incomplete ports lists - all of the necessary code has landed and we want to run tests so we can see/deal with remaining failures. Update #40995 Change-Id: I5d4f89af82ff3abe57570a9a8abf889498093d32 Reviewed-on: https://go-review.googlesource.com/c/go/+/267606 Trust: Joel Sing Reviewed-by: Cherry Zhang --- src/cmd/dist/build.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go index 20cb04d797e..c8c3212d166 100644 --- a/src/cmd/dist/build.go +++ b/src/cmd/dist/build.go @@ -1580,8 +1580,7 @@ var cgoEnabled = map[string]bool{ // List of platforms which are supported but not complete yet. These get // filtered out of cgoEnabled for 'dist list'. See golang.org/issue/28944 var incomplete = map[string]bool{ - "linux/sparc64": true, - "openbsd/mips64": true, + "linux/sparc64": true, } func needCC() bool { From 854e892ce17e2555c59fce5b92f64bc505ba5d8c Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Mon, 11 May 2020 09:44:48 -0700 Subject: [PATCH 371/403] cmd/compile: optimize shift pairs and masks on s390x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimize combinations of left and right shifts by a constant value into a 'rotate then insert selected bits [into zero]' instruction. Use the same instruction for contiguous masks since it has some benefits over 'and immediate' (not restricted to 32-bits, does not overwrite source register). To keep the complexity of this change under control I've only implemented 64 bit operations for now. There are a lot more optimizations that can be done with this instruction family. However, since their function overlaps with other instructions we need to be somewhat careful not to break existing optimization rules by creating optimization dead ends. This is particularly true of the load/store merging rules which contain lots of zero extensions and shifts. This CL does interfere with the store merging rules when an operand is shifted left before it is stored: binary.BigEndian.PutUint64(b, x << 1) This is unfortunate but it's not critical and somewhat complex so I plan to fix that in a follow up CL. file before after Δ % addr2line 4117446 4117282 -164 -0.004% api 4945184 4942752 -2432 -0.049% asm 4998079 4991891 -6188 -0.124% buildid 2685158 2684074 -1084 -0.040% cgo 4553732 4553394 -338 -0.007% compile 19294446 19245070 -49376 -0.256% cover 4897105 4891319 -5786 -0.118% dist 3544389 3542785 -1604 -0.045% doc 3926795 3927617 +822 +0.021% fix 3302958 3293868 -9090 -0.275% link 6546274 6543456 -2818 -0.043% nm 4102021 4100825 -1196 -0.029% objdump 4542431 4548483 +6052 +0.133% pack 2482465 2416389 -66076 -2.662% pprof 13366541 13363915 -2626 -0.020% test2json 2829007 2761515 -67492 -2.386% trace 10216164 10219684 +3520 +0.034% vet 6773956 6773572 -384 -0.006% total 107124151 106917891 -206260 -0.193% Change-Id: I7591cce41e06867ba10a745daae9333513062746 Reviewed-on: https://go-review.googlesource.com/c/go/+/233317 Run-TryBot: Michael Munday TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Michael Munday --- src/cmd/compile/internal/s390x/ssa.go | 14 +- src/cmd/compile/internal/ssa/gen/S390X.rules | 162 +++- src/cmd/compile/internal/ssa/gen/S390XOps.go | 20 +- src/cmd/compile/internal/ssa/opGen.go | 31 +- src/cmd/compile/internal/ssa/rewriteS390X.go | 848 +++++++++++++------ src/cmd/internal/obj/s390x/rotate.go | 82 +- src/cmd/internal/obj/s390x/rotate_test.go | 122 +++ test/codegen/bitfield.go | 18 +- test/codegen/bits.go | 12 + test/codegen/mathbits.go | 2 +- test/codegen/rotate.go | 6 +- test/codegen/shift.go | 33 +- 12 files changed, 1012 insertions(+), 338 deletions(-) create mode 100644 src/cmd/internal/obj/s390x/rotate_test.go diff --git a/src/cmd/compile/internal/s390x/ssa.go b/src/cmd/compile/internal/s390x/ssa.go index 84b9f491e46..8037357131c 100644 --- a/src/cmd/compile/internal/s390x/ssa.go +++ b/src/cmd/compile/internal/s390x/ssa.go @@ -188,6 +188,18 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { {Type: obj.TYPE_REG, Reg: r2}, }) p.To = obj.Addr{Type: obj.TYPE_REG, Reg: r1} + case ssa.OpS390XRISBGZ: + r1 := v.Reg() + r2 := v.Args[0].Reg() + i := v.Aux.(s390x.RotateParams) + p := s.Prog(v.Op.Asm()) + p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(i.Start)} + p.SetRestArgs([]obj.Addr{ + {Type: obj.TYPE_CONST, Offset: int64(i.End)}, + {Type: obj.TYPE_CONST, Offset: int64(i.Amount)}, + {Type: obj.TYPE_REG, Reg: r2}, + }) + p.To = obj.Addr{Type: obj.TYPE_REG, Reg: r1} case ssa.OpS390XADD, ssa.OpS390XADDW, ssa.OpS390XSUB, ssa.OpS390XSUBW, ssa.OpS390XAND, ssa.OpS390XANDW, @@ -360,7 +372,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { case ssa.OpS390XSLDconst, ssa.OpS390XSLWconst, ssa.OpS390XSRDconst, ssa.OpS390XSRWconst, ssa.OpS390XSRADconst, ssa.OpS390XSRAWconst, - ssa.OpS390XRLLGconst, ssa.OpS390XRLLconst: + ssa.OpS390XRLLconst: p := s.Prog(v.Op.Asm()) p.From.Type = obj.TYPE_CONST p.From.Offset = v.AuxInt diff --git a/src/cmd/compile/internal/ssa/gen/S390X.rules b/src/cmd/compile/internal/ssa/gen/S390X.rules index 1b56361c00a..39949edbc2b 100644 --- a/src/cmd/compile/internal/ssa/gen/S390X.rules +++ b/src/cmd/compile/internal/ssa/gen/S390X.rules @@ -643,8 +643,18 @@ // equivalent to the leftmost 32 bits being set. // TODO(mundaym): modify the assembler to accept 64-bit values // and use isU32Bit(^c). -(AND x (MOVDconst [c])) && is32Bit(c) && c < 0 => (ANDconst [c] x) -(AND x (MOVDconst [c])) && is32Bit(c) && c >= 0 => (MOVWZreg (ANDWconst [int32(c)] x)) +(AND x (MOVDconst [c])) + && s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c)) != nil + => (RISBGZ x {*s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c))}) +(AND x (MOVDconst [c])) + && is32Bit(c) + && c < 0 + => (ANDconst [c] x) +(AND x (MOVDconst [c])) + && is32Bit(c) + && c >= 0 + => (MOVWZreg (ANDWconst [int32(c)] x)) + (ANDW x (MOVDconst [c])) => (ANDWconst [int32(c)] x) ((AND|ANDW)const [c] ((AND|ANDW)const [d] x)) => ((AND|ANDW)const [c&d] x) @@ -653,14 +663,20 @@ ((OR|XOR)W x (MOVDconst [c])) => ((OR|XOR)Wconst [int32(c)] x) // Constant shifts. -(S(LD|RD|RAD|LW|RW|RAW) x (MOVDconst [c])) - => (S(LD|RD|RAD|LW|RW|RAW)const x [int8(c&63)]) +(S(LD|RD|RAD) x (MOVDconst [c])) => (S(LD|RD|RAD)const x [int8(c&63)]) +(S(LW|RW|RAW) x (MOVDconst [c])) && c&32 == 0 => (S(LW|RW|RAW)const x [int8(c&31)]) +(S(LW|RW) _ (MOVDconst [c])) && c&32 != 0 => (MOVDconst [0]) +(SRAW x (MOVDconst [c])) && c&32 != 0 => (SRAWconst x [31]) // Shifts only use the rightmost 6 bits of the shift value. +(S(LD|RD|RAD|LW|RW|RAW) x (RISBGZ y {r})) + && r.Amount == 0 + && r.OutMask()&63 == 63 + => (S(LD|RD|RAD|LW|RW|RAW) x y) (S(LD|RD|RAD|LW|RW|RAW) x (AND (MOVDconst [c]) y)) - => (S(LD|RD|RAD|LW|RW|RAW) x (ANDWconst [int32(c&63)] y)) + => (S(LD|RD|RAD|LW|RW|RAW) x (ANDWconst [int32(c&63)] y)) (S(LD|RD|RAD|LW|RW|RAW) x (ANDWconst [c] y)) && c&63 == 63 - => (S(LD|RD|RAD|LW|RW|RAW) x y) + => (S(LD|RD|RAD|LW|RW|RAW) x y) (SLD x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SLD x y) (SRD x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRD x y) (SRAD x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRAD x y) @@ -668,17 +684,13 @@ (SRW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRW x y) (SRAW x (MOV(W|H|B|WZ|HZ|BZ)reg y)) => (SRAW x y) -// Constant rotate generation -(RLL x (MOVDconst [c])) => (RLLconst x [int8(c&31)]) -(RLLG x (MOVDconst [c])) => (RLLGconst x [int8(c&63)]) +// Match rotate by constant. +(RLLG x (MOVDconst [c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, int8(c&63))}) +(RLL x (MOVDconst [c])) => (RLLconst x [int8(c&31)]) -(ADD (SLDconst x [c]) (SRDconst x [d])) && d == 64-c => (RLLGconst [c] x) -( OR (SLDconst x [c]) (SRDconst x [d])) && d == 64-c => (RLLGconst [c] x) -(XOR (SLDconst x [c]) (SRDconst x [d])) && d == 64-c => (RLLGconst [c] x) - -(ADDW (SLWconst x [c]) (SRWconst x [d])) && d == 32-c => (RLLconst [c] x) -( ORW (SLWconst x [c]) (SRWconst x [d])) && d == 32-c => (RLLconst [c] x) -(XORW (SLWconst x [c]) (SRWconst x [d])) && d == 32-c => (RLLconst [c] x) +// Match rotate by constant pattern. +((ADD|OR|XOR) (SLDconst x [c]) (SRDconst x [64-c])) => (RISBGZ x {s390x.NewRotateParams(0, 63, c)}) +((ADD|OR|XOR)W (SLWconst x [c]) (SRWconst x [32-c])) => (RLLconst x [c]) // Signed 64-bit comparison with immediate. (CMP x (MOVDconst [c])) && is32Bit(c) => (CMPconst x [int32(c)]) @@ -692,15 +704,97 @@ (CMP(W|WU) x (MOVDconst [c])) => (CMP(W|WU)const x [int32(c)]) (CMP(W|WU) (MOVDconst [c]) x) => (InvertFlags (CMP(W|WU)const x [int32(c)])) +// Match (x >> c) << d to 'rotate then insert selected bits [into zero]'. +(SLDconst (SRDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(max8(0, c-d), 63-d, (d-c)&63)}) + +// Match (x << c) >> d to 'rotate then insert selected bits [into zero]'. +(SRDconst (SLDconst x [c]) [d]) => (RISBGZ x {s390x.NewRotateParams(d, min8(63, 63-c+d), (c-d)&63)}) + +// Absorb input zero extension into 'rotate then insert selected bits [into zero]'. +(RISBGZ (MOVWZreg x) {r}) && r.InMerge(0xffffffff) != nil => (RISBGZ x {*r.InMerge(0xffffffff)}) +(RISBGZ (MOVHZreg x) {r}) && r.InMerge(0x0000ffff) != nil => (RISBGZ x {*r.InMerge(0x0000ffff)}) +(RISBGZ (MOVBZreg x) {r}) && r.InMerge(0x000000ff) != nil => (RISBGZ x {*r.InMerge(0x000000ff)}) + +// Absorb 'rotate then insert selected bits [into zero]' into zero extension. +(MOVWZreg (RISBGZ x {r})) && r.OutMerge(0xffffffff) != nil => (RISBGZ x {*r.OutMerge(0xffffffff)}) +(MOVHZreg (RISBGZ x {r})) && r.OutMerge(0x0000ffff) != nil => (RISBGZ x {*r.OutMerge(0x0000ffff)}) +(MOVBZreg (RISBGZ x {r})) && r.OutMerge(0x000000ff) != nil => (RISBGZ x {*r.OutMerge(0x000000ff)}) + +// Absorb shift into 'rotate then insert selected bits [into zero]'. +// +// Any unsigned shift can be represented as a rotate and mask operation: +// +// x << c => RotateLeft64(x, c) & (^uint64(0) << c) +// x >> c => RotateLeft64(x, -c) & (^uint64(0) >> c) +// +// Therefore when a shift is used as the input to a rotate then insert +// selected bits instruction we can merge the two together. We just have +// to be careful that the resultant mask is representable (non-zero and +// contiguous). For example, assuming that x is variable and c, y and m +// are constants, a shift followed by a rotate then insert selected bits +// could be represented as: +// +// RotateLeft64(RotateLeft64(x, c) & (^uint64(0) << c), y) & m +// +// We can split the rotation by y into two, one rotate for x and one for +// the mask: +// +// RotateLeft64(RotateLeft64(x, c), y) & (RotateLeft64(^uint64(0) << c, y)) & m +// +// The rotations of x by c followed by y can then be combined: +// +// RotateLeft64(x, c+y) & (RotateLeft64(^uint64(0) << c, y)) & m +// ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +// rotate mask +// +// To perform this optimization we therefore just need to check that it +// is valid to merge the shift mask (^(uint64(0)< (RISBGZ x {(*r.InMerge(^uint64(0)<>c) != nil => (RISBGZ x {(*r.InMerge(^uint64(0)>>c)).RotateLeft(-c)}) + +// Absorb 'rotate then insert selected bits [into zero]' into left shift. +(SLDconst (RISBGZ x {r}) [c]) + && s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask()) != nil + => (RISBGZ x {(*s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask())).RotateLeft(r.Amount)}) + +// Absorb 'rotate then insert selected bits [into zero]' into right shift. +(SRDconst (RISBGZ x {r}) [c]) + && s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask()) != nil + => (RISBGZ x {(*s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask())).RotateLeft(r.Amount)}) + +// Merge 'rotate then insert selected bits [into zero]' instructions together. +(RISBGZ (RISBGZ x {y}) {z}) + && z.InMerge(y.OutMask()) != nil + => (RISBGZ x {(*z.InMerge(y.OutMask())).RotateLeft(y.Amount)}) + +// Convert RISBGZ into 64-bit shift (helps CSE). +(RISBGZ x {r}) && r.End == 63 && r.Start == -r.Amount&63 => (SRDconst x [-r.Amount&63]) +(RISBGZ x {r}) && r.Start == 0 && r.End == 63-r.Amount => (SLDconst x [r.Amount]) + +// Optimize single bit isolation when it is known to be equivalent to +// the most significant bit due to mask produced by arithmetic shift. +// Simply isolate the most significant bit itself and place it in the +// correct position. +// +// Example: (int64(x) >> 63) & 0x8 -> RISBGZ $60, $60, $4, Rsrc, Rdst +(RISBGZ (SRADconst x [c]) {r}) + && r.Start == r.End // single bit selected + && (r.Start+r.Amount)&63 <= c // equivalent to most significant bit of x + => (RISBGZ x {s390x.NewRotateParams(r.Start, r.Start, -r.Start&63)}) + // Canonicalize the order of arguments to comparisons - helps with CSE. ((CMP|CMPW|CMPU|CMPWU) x y) && x.ID > y.ID => (InvertFlags ((CMP|CMPW|CMPU|CMPWU) y x)) -// Using MOV{W,H,B}Zreg instead of AND is cheaper. -(AND x (MOVDconst [0xFF])) => (MOVBZreg x) -(AND x (MOVDconst [0xFFFF])) => (MOVHZreg x) -(AND x (MOVDconst [0xFFFFFFFF])) => (MOVWZreg x) -(ANDWconst [0xFF] x) => (MOVBZreg x) -(ANDWconst [0xFFFF] x) => (MOVHZreg x) +// Use sign/zero extend instead of RISBGZ. +(RISBGZ x {r}) && r == s390x.NewRotateParams(56, 63, 0) => (MOVBZreg x) +(RISBGZ x {r}) && r == s390x.NewRotateParams(48, 63, 0) => (MOVHZreg x) +(RISBGZ x {r}) && r == s390x.NewRotateParams(32, 63, 0) => (MOVWZreg x) + +// Use sign/zero extend instead of ANDW. +(ANDWconst [0x00ff] x) => (MOVBZreg x) +(ANDWconst [0xffff] x) => (MOVHZreg x) // Strength reduce multiplication to the sum (or difference) of two powers of two. // @@ -773,21 +867,22 @@ // detect attempts to set/clear the sign bit // may need to be reworked when NIHH/OIHH are added -(SRDconst [1] (SLDconst [1] (LGDR x))) => (LGDR (LPDFR x)) -(LDGR (SRDconst [1] (SLDconst [1] x))) => (LPDFR (LDGR x)) -(AND (MOVDconst [^(-1<<63)]) (LGDR x)) => (LGDR (LPDFR x)) -(LDGR (AND (MOVDconst [^(-1<<63)]) x)) => (LPDFR (LDGR x)) -(OR (MOVDconst [-1<<63]) (LGDR x)) => (LGDR (LNDFR x)) -(LDGR (OR (MOVDconst [-1<<63]) x)) => (LNDFR (LDGR x)) +(RISBGZ (LGDR x) {r}) && r == s390x.NewRotateParams(1, 63, 0) => (LGDR (LPDFR x)) +(LDGR (RISBGZ x {r})) && r == s390x.NewRotateParams(1, 63, 0) => (LPDFR (LDGR x)) +(OR (MOVDconst [-1<<63]) (LGDR x)) => (LGDR (LNDFR x)) +(LDGR (OR (MOVDconst [-1<<63]) x)) => (LNDFR (LDGR x)) // detect attempts to set the sign bit with load (LDGR x:(ORload [off] {sym} (MOVDconst [-1<<63]) ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (LNDFR (LDGR (MOVDload [off] {sym} ptr mem))) // detect copysign -(OR (SLDconst [63] (SRDconst [63] (LGDR x))) (LGDR (LPDFR y))) => (LGDR (CPSDR y x)) -(OR (SLDconst [63] (SRDconst [63] (LGDR x))) (MOVDconst [c])) && c & -1<<63 == 0 => (LGDR (CPSDR (FMOVDconst [math.Float64frombits(uint64(c))]) x)) -(OR (AND (MOVDconst [-1<<63]) (LGDR x)) (LGDR (LPDFR y))) => (LGDR (CPSDR y x)) -(OR (AND (MOVDconst [-1<<63]) (LGDR x)) (MOVDconst [c])) && c & -1<<63 == 0 => (LGDR (CPSDR (FMOVDconst [math.Float64frombits(uint64(c))]) x)) +(OR (RISBGZ (LGDR x) {r}) (LGDR (LPDFR y))) + && r == s390x.NewRotateParams(0, 0, 0) + => (LGDR (CPSDR y x)) +(OR (RISBGZ (LGDR x) {r}) (MOVDconst [c])) + && c >= 0 + && r == s390x.NewRotateParams(0, 0, 0) + => (LGDR (CPSDR (FMOVDconst [math.Float64frombits(uint64(c))]) x)) (CPSDR y (FMOVDconst [c])) && !math.Signbit(c) => (LPDFR y) (CPSDR y (FMOVDconst [c])) && math.Signbit(c) => (LNDFR y) @@ -966,6 +1061,9 @@ (CMPWconst (ANDWconst _ [m]) [n]) && int32(m) >= 0 && int32(m) < int32(n) => (FlagLT) (CMPWUconst (ANDWconst _ [m]) [n]) && uint32(m) < uint32(n) => (FlagLT) +(CMPconst (RISBGZ x {r}) [c]) && c > 0 && r.OutMask() < uint64(c) => (FlagLT) +(CMPUconst (RISBGZ x {r}) [c]) && r.OutMask() < uint64(uint32(c)) => (FlagLT) + // Constant compare-and-branch with immediate. (CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Equal != 0 && int64(x) == int64(y) => (First yes no) (CGIJ {c} (MOVDconst [x]) [y] yes no) && c&s390x.Less != 0 && int64(x) < int64(y) => (First yes no) diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go index 728cfb55088..f0cf2f2f6e6 100644 --- a/src/cmd/compile/internal/ssa/gen/S390XOps.go +++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go @@ -331,25 +331,26 @@ func init() { {name: "LTEBR", argLength: 1, reg: fp1flags, asm: "LTEBR", typ: "Flags"}, // arg0 compare to 0, f32 {name: "SLD", argLength: 2, reg: sh21, asm: "SLD"}, // arg0 << arg1, shift amount is mod 64 - {name: "SLW", argLength: 2, reg: sh21, asm: "SLW"}, // arg0 << arg1, shift amount is mod 32 + {name: "SLW", argLength: 2, reg: sh21, asm: "SLW"}, // arg0 << arg1, shift amount is mod 64 {name: "SLDconst", argLength: 1, reg: gp11, asm: "SLD", aux: "Int8"}, // arg0 << auxint, shift amount 0-63 {name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int8"}, // arg0 << auxint, shift amount 0-31 {name: "SRD", argLength: 2, reg: sh21, asm: "SRD"}, // unsigned arg0 >> arg1, shift amount is mod 64 - {name: "SRW", argLength: 2, reg: sh21, asm: "SRW"}, // unsigned uint32(arg0) >> arg1, shift amount is mod 32 + {name: "SRW", argLength: 2, reg: sh21, asm: "SRW"}, // unsigned uint32(arg0) >> arg1, shift amount is mod 64 {name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int8"}, // unsigned arg0 >> auxint, shift amount 0-63 {name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int8"}, // unsigned uint32(arg0) >> auxint, shift amount 0-31 // Arithmetic shifts clobber flags. {name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64 - {name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 32 + {name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 64 {name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "Int8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63 {name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int8", clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31 - {name: "RLLG", argLength: 2, reg: sh21, asm: "RLLG"}, // arg0 rotate left arg1, rotate amount 0-63 - {name: "RLL", argLength: 2, reg: sh21, asm: "RLL"}, // arg0 rotate left arg1, rotate amount 0-31 - {name: "RLLGconst", argLength: 1, reg: gp11, asm: "RLLG", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-63 - {name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-31 + // Rotate instructions. + // Note: no RLLGconst - use RISBGZ instead. + {name: "RLLG", argLength: 2, reg: sh21, asm: "RLLG"}, // arg0 rotate left arg1, rotate amount 0-63 + {name: "RLL", argLength: 2, reg: sh21, asm: "RLL"}, // arg0 rotate left arg1, rotate amount 0-31 + {name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-31 // Rotate then (and|or|xor|insert) selected bits instructions. // @@ -371,6 +372,7 @@ func init() { // +-------------+-------+-----+--------+-----------------------+-----------------------+-----------------------+ // {name: "RXSBG", argLength: 2, reg: gp21, asm: "RXSBG", resultInArg0: true, aux: "S390XRotateParams", clobberFlags: true}, // rotate then xor selected bits + {name: "RISBGZ", argLength: 1, reg: gp11, asm: "RISBGZ", aux: "S390XRotateParams", clobberFlags: true}, // rotate then insert selected bits [into zero] // unary ops {name: "NEG", argLength: 1, reg: gp11, asm: "NEG", clobberFlags: true}, // -arg0 @@ -547,9 +549,9 @@ func init() { // Atomic bitwise operations. // Note: 'floor' operations round the pointer down to the nearest word boundary // which reflects how they are used in the runtime. - {name: "LAN", argLength: 3, reg: gpstore, asm: "LAN", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *arg0 &= arg1. arg2 = mem. + {name: "LAN", argLength: 3, reg: gpstore, asm: "LAN", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *arg0 &= arg1. arg2 = mem. {name: "LANfloor", argLength: 3, reg: gpstorelab, asm: "LAN", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *(floor(arg0, 4)) &= arg1. arg2 = mem. - {name: "LAO", argLength: 3, reg: gpstore, asm: "LAO", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *arg0 |= arg1. arg2 = mem. + {name: "LAO", argLength: 3, reg: gpstore, asm: "LAO", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *arg0 |= arg1. arg2 = mem. {name: "LAOfloor", argLength: 3, reg: gpstorelab, asm: "LAO", typ: "Mem", clobberFlags: true, hasSideEffects: true}, // *(floor(arg0, 4)) |= arg1. arg2 = mem. // Compare and swap. diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index c0b663cd8f6..eceef1d91ad 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2285,9 +2285,9 @@ const ( OpS390XSRAWconst OpS390XRLLG OpS390XRLL - OpS390XRLLGconst OpS390XRLLconst OpS390XRXSBG + OpS390XRISBGZ OpS390XNEG OpS390XNEGW OpS390XNOT @@ -30739,20 +30739,6 @@ var opcodeTable = [...]opInfo{ }, }, }, - { - name: "RLLGconst", - auxType: auxInt8, - argLen: 1, - asm: s390x.ARLLG, - reg: regInfo{ - inputs: []inputInfo{ - {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 - }, - outputs: []outputInfo{ - {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 - }, - }, - }, { name: "RLLconst", auxType: auxInt8, @@ -30784,6 +30770,21 @@ var opcodeTable = [...]opInfo{ }, }, }, + { + name: "RISBGZ", + auxType: auxS390XRotateParams, + argLen: 1, + clobberFlags: true, + asm: s390x.ARISBGZ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 + }, + outputs: []outputInfo{ + {0, 23551}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R11 R12 R14 + }, + }, + }, { name: "NEG", argLen: 1, diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go index 8c3c61d584c..d66113d1118 100644 --- a/src/cmd/compile/internal/ssa/rewriteS390X.go +++ b/src/cmd/compile/internal/ssa/rewriteS390X.go @@ -699,6 +699,8 @@ func rewriteValueS390X(v *Value) bool { return rewriteValueS390X_OpS390XORconst(v) case OpS390XORload: return rewriteValueS390X_OpS390XORload(v) + case OpS390XRISBGZ: + return rewriteValueS390X_OpS390XRISBGZ(v) case OpS390XRLL: return rewriteValueS390X_OpS390XRLL(v) case OpS390XRLLG: @@ -5272,9 +5274,8 @@ func rewriteValueS390X_OpS390XADD(v *Value) bool { } break } - // match: (ADD (SLDconst x [c]) (SRDconst x [d])) - // cond: d == 64-c - // result: (RLLGconst [c] x) + // match: (ADD (SLDconst x [c]) (SRDconst x [64-c])) + // result: (RISBGZ x {s390x.NewRotateParams(0, 63, c)}) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpS390XSLDconst { @@ -5282,15 +5283,11 @@ func rewriteValueS390X_OpS390XADD(v *Value) bool { } c := auxIntToInt8(v_0.AuxInt) x := v_0.Args[0] - if v_1.Op != OpS390XSRDconst { + if v_1.Op != OpS390XSRDconst || auxIntToInt8(v_1.AuxInt) != 64-c || x != v_1.Args[0] { continue } - d := auxIntToInt8(v_1.AuxInt) - if x != v_1.Args[0] || !(d == 64-c) { - continue - } - v.reset(OpS390XRLLGconst) - v.AuxInt = int8ToAuxInt(c) + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, c)) v.AddArg(x) return true } @@ -5470,9 +5467,8 @@ func rewriteValueS390X_OpS390XADDW(v *Value) bool { } break } - // match: (ADDW (SLWconst x [c]) (SRWconst x [d])) - // cond: d == 32-c - // result: (RLLconst [c] x) + // match: (ADDW (SLWconst x [c]) (SRWconst x [32-c])) + // result: (RLLconst x [c]) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpS390XSLWconst { @@ -5480,11 +5476,7 @@ func rewriteValueS390X_OpS390XADDW(v *Value) bool { } c := auxIntToInt8(v_0.AuxInt) x := v_0.Args[0] - if v_1.Op != OpS390XSRWconst { - continue - } - d := auxIntToInt8(v_1.AuxInt) - if x != v_1.Args[0] || !(d == 32-c) { + if v_1.Op != OpS390XSRWconst || auxIntToInt8(v_1.AuxInt) != 32-c || x != v_1.Args[0] { continue } v.reset(OpS390XRLLconst) @@ -5844,6 +5836,26 @@ func rewriteValueS390X_OpS390XAND(v *Value) bool { b := v.Block typ := &b.Func.Config.Types // match: (AND x (MOVDconst [c])) + // cond: s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c)) != nil + // result: (RISBGZ x {*s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c))}) + for { + for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { + x := v_0 + if v_1.Op != OpS390XMOVDconst { + continue + } + c := auxIntToInt64(v_1.AuxInt) + if !(s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c)) != nil) { + continue + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(*s390x.NewRotateParams(0, 63, 0).OutMerge(uint64(c))) + v.AddArg(x) + return true + } + break + } + // match: (AND x (MOVDconst [c])) // cond: is32Bit(c) && c < 0 // result: (ANDconst [c] x) for { @@ -5885,66 +5897,6 @@ func rewriteValueS390X_OpS390XAND(v *Value) bool { } break } - // match: (AND x (MOVDconst [0xFF])) - // result: (MOVBZreg x) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpS390XMOVDconst || auxIntToInt64(v_1.AuxInt) != 0xFF { - continue - } - v.reset(OpS390XMOVBZreg) - v.AddArg(x) - return true - } - break - } - // match: (AND x (MOVDconst [0xFFFF])) - // result: (MOVHZreg x) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpS390XMOVDconst || auxIntToInt64(v_1.AuxInt) != 0xFFFF { - continue - } - v.reset(OpS390XMOVHZreg) - v.AddArg(x) - return true - } - break - } - // match: (AND x (MOVDconst [0xFFFFFFFF])) - // result: (MOVWZreg x) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - x := v_0 - if v_1.Op != OpS390XMOVDconst || auxIntToInt64(v_1.AuxInt) != 0xFFFFFFFF { - continue - } - v.reset(OpS390XMOVWZreg) - v.AddArg(x) - return true - } - break - } - // match: (AND (MOVDconst [^(-1<<63)]) (LGDR x)) - // result: (LGDR (LPDFR x)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0.AuxInt) != ^(-1<<63) || v_1.Op != OpS390XLGDR { - continue - } - t := v_1.Type - x := v_1.Args[0] - v.reset(OpS390XLGDR) - v.Type = t - v0 := b.NewValue0(v.Pos, OpS390XLPDFR, x.Type) - v0.AddArg(x) - v.AddArg(v0) - return true - } - break - } // match: (AND (MOVDconst [c]) (MOVDconst [d])) // result: (MOVDconst [c&d]) for { @@ -6103,10 +6055,10 @@ func rewriteValueS390X_OpS390XANDWconst(v *Value) bool { v.AddArg(x) return true } - // match: (ANDWconst [0xFF] x) + // match: (ANDWconst [0x00ff] x) // result: (MOVBZreg x) for { - if auxIntToInt32(v.AuxInt) != 0xFF { + if auxIntToInt32(v.AuxInt) != 0x00ff { break } x := v_0 @@ -6114,10 +6066,10 @@ func rewriteValueS390X_OpS390XANDWconst(v *Value) bool { v.AddArg(x) return true } - // match: (ANDWconst [0xFFFF] x) + // match: (ANDWconst [0xffff] x) // result: (MOVHZreg x) for { - if auxIntToInt32(v.AuxInt) != 0xFFFF { + if auxIntToInt32(v.AuxInt) != 0xffff { break } x := v_0 @@ -6515,6 +6467,21 @@ func rewriteValueS390X_OpS390XCMPUconst(v *Value) bool { v.reset(OpS390XFlagLT) return true } + // match: (CMPUconst (RISBGZ x {r}) [c]) + // cond: r.OutMask() < uint64(uint32(c)) + // result: (FlagLT) + for { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_0.Aux) + if !(r.OutMask() < uint64(uint32(c))) { + break + } + v.reset(OpS390XFlagLT) + return true + } // match: (CMPUconst (MOVWZreg x) [c]) // result: (CMPWUconst x [c]) for { @@ -7152,6 +7119,21 @@ func rewriteValueS390X_OpS390XCMPconst(v *Value) bool { v.reset(OpS390XFlagGT) return true } + // match: (CMPconst (RISBGZ x {r}) [c]) + // cond: c > 0 && r.OutMask() < uint64(c) + // result: (FlagLT) + for { + c := auxIntToInt32(v.AuxInt) + if v_0.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_0.Aux) + if !(c > 0 && r.OutMask() < uint64(c)) { + break + } + v.reset(OpS390XFlagLT) + return true + } // match: (CMPconst (MOVWreg x) [c]) // result: (CMPWconst x [c]) for { @@ -7684,47 +7666,25 @@ func rewriteValueS390X_OpS390XFNEGS(v *Value) bool { func rewriteValueS390X_OpS390XLDGR(v *Value) bool { v_0 := v.Args[0] b := v.Block - // match: (LDGR (SRDconst [1] (SLDconst [1] x))) + // match: (LDGR (RISBGZ x {r})) + // cond: r == s390x.NewRotateParams(1, 63, 0) // result: (LPDFR (LDGR x)) for { t := v.Type - if v_0.Op != OpS390XSRDconst || auxIntToInt8(v_0.AuxInt) != 1 { + if v_0.Op != OpS390XRISBGZ { break } - v_0_0 := v_0.Args[0] - if v_0_0.Op != OpS390XSLDconst || auxIntToInt8(v_0_0.AuxInt) != 1 { + r := auxToS390xRotateParams(v_0.Aux) + x := v_0.Args[0] + if !(r == s390x.NewRotateParams(1, 63, 0)) { break } - x := v_0_0.Args[0] v.reset(OpS390XLPDFR) v0 := b.NewValue0(v.Pos, OpS390XLDGR, t) v0.AddArg(x) v.AddArg(v0) return true } - // match: (LDGR (AND (MOVDconst [^(-1<<63)]) x)) - // result: (LPDFR (LDGR x)) - for { - t := v.Type - if v_0.Op != OpS390XAND { - break - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { - if v_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0.AuxInt) != ^(-1<<63) { - continue - } - x := v_0_1 - v.reset(OpS390XLPDFR) - v0 := b.NewValue0(v.Pos, OpS390XLDGR, t) - v0.AddArg(x) - v.AddArg(v0) - return true - } - break - } // match: (LDGR (OR (MOVDconst [-1<<63]) x)) // result: (LNDFR (LDGR x)) for { @@ -8309,6 +8269,23 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value) bool { v.copyOf(x) return true } + // match: (MOVBZreg (RISBGZ x {r})) + // cond: r.OutMerge(0x000000ff) != nil + // result: (RISBGZ x {*r.OutMerge(0x000000ff)}) + for { + if v_0.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_0.Aux) + x := v_0.Args[0] + if !(r.OutMerge(0x000000ff) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(*r.OutMerge(0x000000ff)) + v.AddArg(x) + return true + } // match: (MOVBZreg (ANDWconst [m] x)) // result: (MOVWZreg (ANDWconst [int32( uint8(m))] x)) for { @@ -9697,6 +9674,23 @@ func rewriteValueS390X_OpS390XMOVHZreg(v *Value) bool { v.AuxInt = int64ToAuxInt(int64(uint16(c))) return true } + // match: (MOVHZreg (RISBGZ x {r})) + // cond: r.OutMerge(0x0000ffff) != nil + // result: (RISBGZ x {*r.OutMerge(0x0000ffff)}) + for { + if v_0.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_0.Aux) + x := v_0.Args[0] + if !(r.OutMerge(0x0000ffff) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(*r.OutMerge(0x0000ffff)) + v.AddArg(x) + return true + } // match: (MOVHZreg (ANDWconst [m] x)) // result: (MOVWZreg (ANDWconst [int32(uint16(m))] x)) for { @@ -10547,6 +10541,23 @@ func rewriteValueS390X_OpS390XMOVWZreg(v *Value) bool { v.AuxInt = int64ToAuxInt(int64(uint32(c))) return true } + // match: (MOVWZreg (RISBGZ x {r})) + // cond: r.OutMerge(0xffffffff) != nil + // result: (RISBGZ x {*r.OutMerge(0xffffffff)}) + for { + if v_0.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_0.Aux) + x := v_0.Args[0] + if !(r.OutMerge(0xffffffff) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(*r.OutMerge(0xffffffff)) + v.AddArg(x) + return true + } return false } func rewriteValueS390X_OpS390XMOVWload(v *Value) bool { @@ -11622,9 +11633,8 @@ func rewriteValueS390X_OpS390XOR(v *Value) bool { } break } - // match: ( OR (SLDconst x [c]) (SRDconst x [d])) - // cond: d == 64-c - // result: (RLLGconst [c] x) + // match: (OR (SLDconst x [c]) (SRDconst x [64-c])) + // result: (RISBGZ x {s390x.NewRotateParams(0, 63, c)}) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpS390XSLDconst { @@ -11632,15 +11642,11 @@ func rewriteValueS390X_OpS390XOR(v *Value) bool { } c := auxIntToInt8(v_0.AuxInt) x := v_0.Args[0] - if v_1.Op != OpS390XSRDconst { + if v_1.Op != OpS390XSRDconst || auxIntToInt8(v_1.AuxInt) != 64-c || x != v_1.Args[0] { continue } - d := auxIntToInt8(v_1.AuxInt) - if x != v_1.Args[0] || !(d == 64-c) { - continue - } - v.reset(OpS390XRLLGconst) - v.AuxInt = int8ToAuxInt(c) + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, c)) v.AddArg(x) return true } @@ -11664,22 +11670,20 @@ func rewriteValueS390X_OpS390XOR(v *Value) bool { } break } - // match: (OR (SLDconst [63] (SRDconst [63] (LGDR x))) (LGDR (LPDFR y))) + // match: (OR (RISBGZ (LGDR x) {r}) (LGDR (LPDFR y))) + // cond: r == s390x.NewRotateParams(0, 0, 0) // result: (LGDR (CPSDR y x)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpS390XSLDconst || auxIntToInt8(v_0.AuxInt) != 63 { + if v_0.Op != OpS390XRISBGZ { continue } + r := auxToS390xRotateParams(v_0.Aux) v_0_0 := v_0.Args[0] - if v_0_0.Op != OpS390XSRDconst || auxIntToInt8(v_0_0.AuxInt) != 63 { + if v_0_0.Op != OpS390XLGDR { continue } - v_0_0_0 := v_0_0.Args[0] - if v_0_0_0.Op != OpS390XLGDR { - continue - } - x := v_0_0_0.Args[0] + x := v_0_0.Args[0] if v_1.Op != OpS390XLGDR { continue } @@ -11689,6 +11693,9 @@ func rewriteValueS390X_OpS390XOR(v *Value) bool { } t := v_1_0.Type y := v_1_0.Args[0] + if !(r == s390x.NewRotateParams(0, 0, 0)) { + continue + } v.reset(OpS390XLGDR) v0 := b.NewValue0(v.Pos, OpS390XCPSDR, t) v0.AddArg2(y, x) @@ -11697,28 +11704,25 @@ func rewriteValueS390X_OpS390XOR(v *Value) bool { } break } - // match: (OR (SLDconst [63] (SRDconst [63] (LGDR x))) (MOVDconst [c])) - // cond: c & -1<<63 == 0 + // match: (OR (RISBGZ (LGDR x) {r}) (MOVDconst [c])) + // cond: c >= 0 && r == s390x.NewRotateParams(0, 0, 0) // result: (LGDR (CPSDR (FMOVDconst [math.Float64frombits(uint64(c))]) x)) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpS390XSLDconst || auxIntToInt8(v_0.AuxInt) != 63 { + if v_0.Op != OpS390XRISBGZ { continue } + r := auxToS390xRotateParams(v_0.Aux) v_0_0 := v_0.Args[0] - if v_0_0.Op != OpS390XSRDconst || auxIntToInt8(v_0_0.AuxInt) != 63 { + if v_0_0.Op != OpS390XLGDR { continue } - v_0_0_0 := v_0_0.Args[0] - if v_0_0_0.Op != OpS390XLGDR { - continue - } - x := v_0_0_0.Args[0] + x := v_0_0.Args[0] if v_1.Op != OpS390XMOVDconst { continue } c := auxIntToInt64(v_1.AuxInt) - if !(c&-1<<63 == 0) { + if !(c >= 0 && r == s390x.NewRotateParams(0, 0, 0)) { continue } v.reset(OpS390XLGDR) @@ -11731,73 +11735,6 @@ func rewriteValueS390X_OpS390XOR(v *Value) bool { } break } - // match: (OR (AND (MOVDconst [-1<<63]) (LGDR x)) (LGDR (LPDFR y))) - // result: (LGDR (CPSDR y x)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpS390XAND { - continue - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 { - if v_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0.AuxInt) != -1<<63 || v_0_1.Op != OpS390XLGDR { - continue - } - x := v_0_1.Args[0] - if v_1.Op != OpS390XLGDR { - continue - } - v_1_0 := v_1.Args[0] - if v_1_0.Op != OpS390XLPDFR { - continue - } - t := v_1_0.Type - y := v_1_0.Args[0] - v.reset(OpS390XLGDR) - v0 := b.NewValue0(v.Pos, OpS390XCPSDR, t) - v0.AddArg2(y, x) - v.AddArg(v0) - return true - } - } - break - } - // match: (OR (AND (MOVDconst [-1<<63]) (LGDR x)) (MOVDconst [c])) - // cond: c & -1<<63 == 0 - // result: (LGDR (CPSDR (FMOVDconst [math.Float64frombits(uint64(c))]) x)) - for { - for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { - if v_0.Op != OpS390XAND { - continue - } - _ = v_0.Args[1] - v_0_0 := v_0.Args[0] - v_0_1 := v_0.Args[1] - for _i1 := 0; _i1 <= 1; _i1, v_0_0, v_0_1 = _i1+1, v_0_1, v_0_0 { - if v_0_0.Op != OpS390XMOVDconst || auxIntToInt64(v_0_0.AuxInt) != -1<<63 || v_0_1.Op != OpS390XLGDR { - continue - } - x := v_0_1.Args[0] - if v_1.Op != OpS390XMOVDconst { - continue - } - c := auxIntToInt64(v_1.AuxInt) - if !(c&-1<<63 == 0) { - continue - } - v.reset(OpS390XLGDR) - v0 := b.NewValue0(v.Pos, OpS390XCPSDR, x.Type) - v1 := b.NewValue0(v.Pos, OpS390XFMOVDconst, x.Type) - v1.AuxInt = float64ToAuxInt(math.Float64frombits(uint64(c))) - v0.AddArg2(v1, x) - v.AddArg(v0) - return true - } - } - break - } // match: (OR (MOVDconst [c]) (MOVDconst [d])) // result: (MOVDconst [c|d]) for { @@ -12394,9 +12331,8 @@ func rewriteValueS390X_OpS390XORW(v *Value) bool { } break } - // match: ( ORW (SLWconst x [c]) (SRWconst x [d])) - // cond: d == 32-c - // result: (RLLconst [c] x) + // match: (ORW (SLWconst x [c]) (SRWconst x [32-c])) + // result: (RLLconst x [c]) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpS390XSLWconst { @@ -12404,11 +12340,7 @@ func rewriteValueS390X_OpS390XORW(v *Value) bool { } c := auxIntToInt8(v_0.AuxInt) x := v_0.Args[0] - if v_1.Op != OpS390XSRWconst { - continue - } - d := auxIntToInt8(v_1.AuxInt) - if x != v_1.Args[0] || !(d == 32-c) { + if v_1.Op != OpS390XSRWconst || auxIntToInt8(v_1.AuxInt) != 32-c || x != v_1.Args[0] { continue } v.reset(OpS390XRLLconst) @@ -12980,6 +12912,221 @@ func rewriteValueS390X_OpS390XORload(v *Value) bool { } return false } +func rewriteValueS390X_OpS390XRISBGZ(v *Value) bool { + v_0 := v.Args[0] + b := v.Block + // match: (RISBGZ (MOVWZreg x) {r}) + // cond: r.InMerge(0xffffffff) != nil + // result: (RISBGZ x {*r.InMerge(0xffffffff)}) + for { + r := auxToS390xRotateParams(v.Aux) + if v_0.Op != OpS390XMOVWZreg { + break + } + x := v_0.Args[0] + if !(r.InMerge(0xffffffff) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(*r.InMerge(0xffffffff)) + v.AddArg(x) + return true + } + // match: (RISBGZ (MOVHZreg x) {r}) + // cond: r.InMerge(0x0000ffff) != nil + // result: (RISBGZ x {*r.InMerge(0x0000ffff)}) + for { + r := auxToS390xRotateParams(v.Aux) + if v_0.Op != OpS390XMOVHZreg { + break + } + x := v_0.Args[0] + if !(r.InMerge(0x0000ffff) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(*r.InMerge(0x0000ffff)) + v.AddArg(x) + return true + } + // match: (RISBGZ (MOVBZreg x) {r}) + // cond: r.InMerge(0x000000ff) != nil + // result: (RISBGZ x {*r.InMerge(0x000000ff)}) + for { + r := auxToS390xRotateParams(v.Aux) + if v_0.Op != OpS390XMOVBZreg { + break + } + x := v_0.Args[0] + if !(r.InMerge(0x000000ff) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(*r.InMerge(0x000000ff)) + v.AddArg(x) + return true + } + // match: (RISBGZ (SLDconst x [c]) {r}) + // cond: r.InMerge(^uint64(0)<>c) != nil + // result: (RISBGZ x {(*r.InMerge(^uint64(0)>>c)).RotateLeft(-c)}) + for { + r := auxToS390xRotateParams(v.Aux) + if v_0.Op != OpS390XSRDconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + x := v_0.Args[0] + if !(r.InMerge(^uint64(0)>>c) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux((*r.InMerge(^uint64(0) >> c)).RotateLeft(-c)) + v.AddArg(x) + return true + } + // match: (RISBGZ (RISBGZ x {y}) {z}) + // cond: z.InMerge(y.OutMask()) != nil + // result: (RISBGZ x {(*z.InMerge(y.OutMask())).RotateLeft(y.Amount)}) + for { + z := auxToS390xRotateParams(v.Aux) + if v_0.Op != OpS390XRISBGZ { + break + } + y := auxToS390xRotateParams(v_0.Aux) + x := v_0.Args[0] + if !(z.InMerge(y.OutMask()) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux((*z.InMerge(y.OutMask())).RotateLeft(y.Amount)) + v.AddArg(x) + return true + } + // match: (RISBGZ x {r}) + // cond: r.End == 63 && r.Start == -r.Amount&63 + // result: (SRDconst x [-r.Amount&63]) + for { + r := auxToS390xRotateParams(v.Aux) + x := v_0 + if !(r.End == 63 && r.Start == -r.Amount&63) { + break + } + v.reset(OpS390XSRDconst) + v.AuxInt = int8ToAuxInt(-r.Amount & 63) + v.AddArg(x) + return true + } + // match: (RISBGZ x {r}) + // cond: r.Start == 0 && r.End == 63-r.Amount + // result: (SLDconst x [r.Amount]) + for { + r := auxToS390xRotateParams(v.Aux) + x := v_0 + if !(r.Start == 0 && r.End == 63-r.Amount) { + break + } + v.reset(OpS390XSLDconst) + v.AuxInt = int8ToAuxInt(r.Amount) + v.AddArg(x) + return true + } + // match: (RISBGZ (SRADconst x [c]) {r}) + // cond: r.Start == r.End && (r.Start+r.Amount)&63 <= c + // result: (RISBGZ x {s390x.NewRotateParams(r.Start, r.Start, -r.Start&63)}) + for { + r := auxToS390xRotateParams(v.Aux) + if v_0.Op != OpS390XSRADconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + x := v_0.Args[0] + if !(r.Start == r.End && (r.Start+r.Amount)&63 <= c) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(r.Start, r.Start, -r.Start&63)) + v.AddArg(x) + return true + } + // match: (RISBGZ x {r}) + // cond: r == s390x.NewRotateParams(56, 63, 0) + // result: (MOVBZreg x) + for { + r := auxToS390xRotateParams(v.Aux) + x := v_0 + if !(r == s390x.NewRotateParams(56, 63, 0)) { + break + } + v.reset(OpS390XMOVBZreg) + v.AddArg(x) + return true + } + // match: (RISBGZ x {r}) + // cond: r == s390x.NewRotateParams(48, 63, 0) + // result: (MOVHZreg x) + for { + r := auxToS390xRotateParams(v.Aux) + x := v_0 + if !(r == s390x.NewRotateParams(48, 63, 0)) { + break + } + v.reset(OpS390XMOVHZreg) + v.AddArg(x) + return true + } + // match: (RISBGZ x {r}) + // cond: r == s390x.NewRotateParams(32, 63, 0) + // result: (MOVWZreg x) + for { + r := auxToS390xRotateParams(v.Aux) + x := v_0 + if !(r == s390x.NewRotateParams(32, 63, 0)) { + break + } + v.reset(OpS390XMOVWZreg) + v.AddArg(x) + return true + } + // match: (RISBGZ (LGDR x) {r}) + // cond: r == s390x.NewRotateParams(1, 63, 0) + // result: (LGDR (LPDFR x)) + for { + r := auxToS390xRotateParams(v.Aux) + if v_0.Op != OpS390XLGDR { + break + } + t := v_0.Type + x := v_0.Args[0] + if !(r == s390x.NewRotateParams(1, 63, 0)) { + break + } + v.reset(OpS390XLGDR) + v.Type = t + v0 := b.NewValue0(v.Pos, OpS390XLPDFR, x.Type) + v0.AddArg(x) + v.AddArg(v0) + return true + } + return false +} func rewriteValueS390X_OpS390XRLL(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] @@ -13002,15 +13149,15 @@ func rewriteValueS390X_OpS390XRLLG(v *Value) bool { v_1 := v.Args[1] v_0 := v.Args[0] // match: (RLLG x (MOVDconst [c])) - // result: (RLLGconst x [int8(c&63)]) + // result: (RISBGZ x {s390x.NewRotateParams(0, 63, int8(c&63))}) for { x := v_0 if v_1.Op != OpS390XMOVDconst { break } c := auxIntToInt64(v_1.AuxInt) - v.reset(OpS390XRLLGconst) - v.AuxInt = int8ToAuxInt(int8(c & 63)) + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, int8(c&63))) v.AddArg(x) return true } @@ -13034,6 +13181,23 @@ func rewriteValueS390X_OpS390XSLD(v *Value) bool { v.AddArg(x) return true } + // match: (SLD x (RISBGZ y {r})) + // cond: r.Amount == 0 && r.OutMask()&63 == 63 + // result: (SLD x y) + for { + x := v_0 + if v_1.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_1.Aux) + y := v_1.Args[0] + if !(r.Amount == 0 && r.OutMask()&63 == 63) { + break + } + v.reset(OpS390XSLD) + v.AddArg2(x, y) + return true + } // match: (SLD x (AND (MOVDconst [c]) y)) // result: (SLD x (ANDWconst [int32(c&63)] y)) for { @@ -13152,6 +13316,38 @@ func rewriteValueS390X_OpS390XSLD(v *Value) bool { } func rewriteValueS390X_OpS390XSLDconst(v *Value) bool { v_0 := v.Args[0] + // match: (SLDconst (SRDconst x [c]) [d]) + // result: (RISBGZ x {s390x.NewRotateParams(max8(0, c-d), 63-d, (d-c)&63)}) + for { + d := auxIntToInt8(v.AuxInt) + if v_0.Op != OpS390XSRDconst { + break + } + c := auxIntToInt8(v_0.AuxInt) + x := v_0.Args[0] + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(max8(0, c-d), 63-d, (d-c)&63)) + v.AddArg(x) + return true + } + // match: (SLDconst (RISBGZ x {r}) [c]) + // cond: s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask()) != nil + // result: (RISBGZ x {(*s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask())).RotateLeft(r.Amount)}) + for { + c := auxIntToInt8(v.AuxInt) + if v_0.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_0.Aux) + x := v_0.Args[0] + if !(s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask()) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux((*s390x.NewRotateParams(0, 63-c, c).InMerge(r.OutMask())).RotateLeft(r.Amount)) + v.AddArg(x) + return true + } // match: (SLDconst x [0]) // result: x for { @@ -13170,18 +13366,54 @@ func rewriteValueS390X_OpS390XSLW(v *Value) bool { b := v.Block typ := &b.Func.Config.Types // match: (SLW x (MOVDconst [c])) - // result: (SLWconst x [int8(c&63)]) + // cond: c&32 == 0 + // result: (SLWconst x [int8(c&31)]) for { x := v_0 if v_1.Op != OpS390XMOVDconst { break } c := auxIntToInt64(v_1.AuxInt) + if !(c&32 == 0) { + break + } v.reset(OpS390XSLWconst) - v.AuxInt = int8ToAuxInt(int8(c & 63)) + v.AuxInt = int8ToAuxInt(int8(c & 31)) v.AddArg(x) return true } + // match: (SLW _ (MOVDconst [c])) + // cond: c&32 != 0 + // result: (MOVDconst [0]) + for { + if v_1.Op != OpS390XMOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + if !(c&32 != 0) { + break + } + v.reset(OpS390XMOVDconst) + v.AuxInt = int64ToAuxInt(0) + return true + } + // match: (SLW x (RISBGZ y {r})) + // cond: r.Amount == 0 && r.OutMask()&63 == 63 + // result: (SLW x y) + for { + x := v_0 + if v_1.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_1.Aux) + y := v_1.Args[0] + if !(r.Amount == 0 && r.OutMask()&63 == 63) { + break + } + v.reset(OpS390XSLW) + v.AddArg2(x, y) + return true + } // match: (SLW x (AND (MOVDconst [c]) y)) // result: (SLW x (ANDWconst [int32(c&63)] y)) for { @@ -13330,6 +13562,23 @@ func rewriteValueS390X_OpS390XSRAD(v *Value) bool { v.AddArg(x) return true } + // match: (SRAD x (RISBGZ y {r})) + // cond: r.Amount == 0 && r.OutMask()&63 == 63 + // result: (SRAD x y) + for { + x := v_0 + if v_1.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_1.Aux) + y := v_1.Args[0] + if !(r.Amount == 0 && r.OutMask()&63 == 63) { + break + } + v.reset(OpS390XSRAD) + v.AddArg2(x, y) + return true + } // match: (SRAD x (AND (MOVDconst [c]) y)) // result: (SRAD x (ANDWconst [int32(c&63)] y)) for { @@ -13478,18 +13727,56 @@ func rewriteValueS390X_OpS390XSRAW(v *Value) bool { b := v.Block typ := &b.Func.Config.Types // match: (SRAW x (MOVDconst [c])) - // result: (SRAWconst x [int8(c&63)]) + // cond: c&32 == 0 + // result: (SRAWconst x [int8(c&31)]) for { x := v_0 if v_1.Op != OpS390XMOVDconst { break } c := auxIntToInt64(v_1.AuxInt) + if !(c&32 == 0) { + break + } v.reset(OpS390XSRAWconst) - v.AuxInt = int8ToAuxInt(int8(c & 63)) + v.AuxInt = int8ToAuxInt(int8(c & 31)) v.AddArg(x) return true } + // match: (SRAW x (MOVDconst [c])) + // cond: c&32 != 0 + // result: (SRAWconst x [31]) + for { + x := v_0 + if v_1.Op != OpS390XMOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + if !(c&32 != 0) { + break + } + v.reset(OpS390XSRAWconst) + v.AuxInt = int8ToAuxInt(31) + v.AddArg(x) + return true + } + // match: (SRAW x (RISBGZ y {r})) + // cond: r.Amount == 0 && r.OutMask()&63 == 63 + // result: (SRAW x y) + for { + x := v_0 + if v_1.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_1.Aux) + y := v_1.Args[0] + if !(r.Amount == 0 && r.OutMask()&63 == 63) { + break + } + v.reset(OpS390XSRAW) + v.AddArg2(x, y) + return true + } // match: (SRAW x (AND (MOVDconst [c]) y)) // result: (SRAW x (ANDWconst [int32(c&63)] y)) for { @@ -13650,6 +13937,23 @@ func rewriteValueS390X_OpS390XSRD(v *Value) bool { v.AddArg(x) return true } + // match: (SRD x (RISBGZ y {r})) + // cond: r.Amount == 0 && r.OutMask()&63 == 63 + // result: (SRD x y) + for { + x := v_0 + if v_1.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_1.Aux) + y := v_1.Args[0] + if !(r.Amount == 0 && r.OutMask()&63 == 63) { + break + } + v.reset(OpS390XSRD) + v.AddArg2(x, y) + return true + } // match: (SRD x (AND (MOVDconst [c]) y)) // result: (SRD x (ANDWconst [int32(c&63)] y)) for { @@ -13768,24 +14072,36 @@ func rewriteValueS390X_OpS390XSRD(v *Value) bool { } func rewriteValueS390X_OpS390XSRDconst(v *Value) bool { v_0 := v.Args[0] - b := v.Block - // match: (SRDconst [1] (SLDconst [1] (LGDR x))) - // result: (LGDR (LPDFR x)) + // match: (SRDconst (SLDconst x [c]) [d]) + // result: (RISBGZ x {s390x.NewRotateParams(d, min8(63, 63-c+d), (c-d)&63)}) for { - if auxIntToInt8(v.AuxInt) != 1 || v_0.Op != OpS390XSLDconst || auxIntToInt8(v_0.AuxInt) != 1 { + d := auxIntToInt8(v.AuxInt) + if v_0.Op != OpS390XSLDconst { break } - v_0_0 := v_0.Args[0] - if v_0_0.Op != OpS390XLGDR { + c := auxIntToInt8(v_0.AuxInt) + x := v_0.Args[0] + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(d, min8(63, 63-c+d), (c-d)&63)) + v.AddArg(x) + return true + } + // match: (SRDconst (RISBGZ x {r}) [c]) + // cond: s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask()) != nil + // result: (RISBGZ x {(*s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask())).RotateLeft(r.Amount)}) + for { + c := auxIntToInt8(v.AuxInt) + if v_0.Op != OpS390XRISBGZ { break } - t := v_0_0.Type - x := v_0_0.Args[0] - v.reset(OpS390XLGDR) - v.Type = t - v0 := b.NewValue0(v.Pos, OpS390XLPDFR, x.Type) - v0.AddArg(x) - v.AddArg(v0) + r := auxToS390xRotateParams(v_0.Aux) + x := v_0.Args[0] + if !(s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask()) != nil) { + break + } + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux((*s390x.NewRotateParams(c, 63, -c&63).InMerge(r.OutMask())).RotateLeft(r.Amount)) + v.AddArg(x) return true } // match: (SRDconst x [0]) @@ -13806,18 +14122,54 @@ func rewriteValueS390X_OpS390XSRW(v *Value) bool { b := v.Block typ := &b.Func.Config.Types // match: (SRW x (MOVDconst [c])) - // result: (SRWconst x [int8(c&63)]) + // cond: c&32 == 0 + // result: (SRWconst x [int8(c&31)]) for { x := v_0 if v_1.Op != OpS390XMOVDconst { break } c := auxIntToInt64(v_1.AuxInt) + if !(c&32 == 0) { + break + } v.reset(OpS390XSRWconst) - v.AuxInt = int8ToAuxInt(int8(c & 63)) + v.AuxInt = int8ToAuxInt(int8(c & 31)) v.AddArg(x) return true } + // match: (SRW _ (MOVDconst [c])) + // cond: c&32 != 0 + // result: (MOVDconst [0]) + for { + if v_1.Op != OpS390XMOVDconst { + break + } + c := auxIntToInt64(v_1.AuxInt) + if !(c&32 != 0) { + break + } + v.reset(OpS390XMOVDconst) + v.AuxInt = int64ToAuxInt(0) + return true + } + // match: (SRW x (RISBGZ y {r})) + // cond: r.Amount == 0 && r.OutMask()&63 == 63 + // result: (SRW x y) + for { + x := v_0 + if v_1.Op != OpS390XRISBGZ { + break + } + r := auxToS390xRotateParams(v_1.Aux) + y := v_1.Args[0] + if !(r.Amount == 0 && r.OutMask()&63 == 63) { + break + } + v.reset(OpS390XSRW) + v.AddArg2(x, y) + return true + } // match: (SRW x (AND (MOVDconst [c]) y)) // result: (SRW x (ANDWconst [int32(c&63)] y)) for { @@ -14564,9 +14916,8 @@ func rewriteValueS390X_OpS390XXOR(v *Value) bool { } break } - // match: (XOR (SLDconst x [c]) (SRDconst x [d])) - // cond: d == 64-c - // result: (RLLGconst [c] x) + // match: (XOR (SLDconst x [c]) (SRDconst x [64-c])) + // result: (RISBGZ x {s390x.NewRotateParams(0, 63, c)}) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpS390XSLDconst { @@ -14574,15 +14925,11 @@ func rewriteValueS390X_OpS390XXOR(v *Value) bool { } c := auxIntToInt8(v_0.AuxInt) x := v_0.Args[0] - if v_1.Op != OpS390XSRDconst { + if v_1.Op != OpS390XSRDconst || auxIntToInt8(v_1.AuxInt) != 64-c || x != v_1.Args[0] { continue } - d := auxIntToInt8(v_1.AuxInt) - if x != v_1.Args[0] || !(d == 64-c) { - continue - } - v.reset(OpS390XRLLGconst) - v.AuxInt = int8ToAuxInt(c) + v.reset(OpS390XRISBGZ) + v.Aux = s390xRotateParamsToAux(s390x.NewRotateParams(0, 63, c)) v.AddArg(x) return true } @@ -14665,9 +15012,8 @@ func rewriteValueS390X_OpS390XXORW(v *Value) bool { } break } - // match: (XORW (SLWconst x [c]) (SRWconst x [d])) - // cond: d == 32-c - // result: (RLLconst [c] x) + // match: (XORW (SLWconst x [c]) (SRWconst x [32-c])) + // result: (RLLconst x [c]) for { for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 { if v_0.Op != OpS390XSLWconst { @@ -14675,11 +15021,7 @@ func rewriteValueS390X_OpS390XXORW(v *Value) bool { } c := auxIntToInt8(v_0.AuxInt) x := v_0.Args[0] - if v_1.Op != OpS390XSRWconst { - continue - } - d := auxIntToInt8(v_1.AuxInt) - if x != v_1.Args[0] || !(d == 32-c) { + if v_1.Op != OpS390XSRWconst || auxIntToInt8(v_1.AuxInt) != 32-c || x != v_1.Args[0] { continue } v.reset(OpS390XRLLconst) diff --git a/src/cmd/internal/obj/s390x/rotate.go b/src/cmd/internal/obj/s390x/rotate.go index fd2d5482dba..7dbc45e6489 100644 --- a/src/cmd/internal/obj/s390x/rotate.go +++ b/src/cmd/internal/obj/s390x/rotate.go @@ -4,6 +4,10 @@ package s390x +import ( + "math/bits" +) + // RotateParams represents the immediates required for a "rotate // then ... selected bits instruction". // @@ -24,12 +28,18 @@ package s390x // input left by. Note that this rotation is performed // before the masked region is used. type RotateParams struct { - Start uint8 // big-endian start bit index [0..63] - End uint8 // big-endian end bit index [0..63] - Amount uint8 // amount to rotate left + Start int8 // big-endian start bit index [0..63] + End int8 // big-endian end bit index [0..63] + Amount int8 // amount to rotate left } -func NewRotateParams(start, end, amount int64) RotateParams { +// NewRotateParams creates a set of parameters representing a +// rotation left by the amount provided and a selection of the bits +// between the provided start and end indexes (inclusive). +// +// The start and end indexes and the rotation amount must all +// be in the range 0-63 inclusive or this function will panic. +func NewRotateParams(start, end, amount int8) RotateParams { if start&^63 != 0 { panic("start out of bounds") } @@ -40,8 +50,66 @@ func NewRotateParams(start, end, amount int64) RotateParams { panic("amount out of bounds") } return RotateParams{ - Start: uint8(start), - End: uint8(end), - Amount: uint8(amount), + Start: start, + End: end, + Amount: amount, } } + +// RotateLeft generates a new set of parameters with the rotation amount +// increased by the given value. The selected bits are left unchanged. +func (r RotateParams) RotateLeft(amount int8) RotateParams { + r.Amount += amount + r.Amount &= 63 + return r +} + +// OutMask provides a mask representing the selected bits. +func (r RotateParams) OutMask() uint64 { + // Note: z must be unsigned for bootstrap compiler + z := uint8(63-r.End+r.Start) & 63 // number of zero bits in mask + return bits.RotateLeft64(^uint64(0)<> 1, outMask: ^uint64(0) >> 1}, + {start: 0, end: 62, amount: 0, inMask: ^uint64(1), outMask: ^uint64(1)}, + {start: 1, end: 62, amount: 0, inMask: ^uint64(3) >> 1, outMask: ^uint64(3) >> 1}, + + // end before start, no rotation + {start: 63, end: 0, amount: 0, inMask: 1<<63 | 1, outMask: 1<<63 | 1}, + {start: 62, end: 0, amount: 0, inMask: 1<<63 | 3, outMask: 1<<63 | 3}, + {start: 63, end: 1, amount: 0, inMask: 3<<62 | 1, outMask: 3<<62 | 1}, + {start: 62, end: 1, amount: 0, inMask: 3<<62 | 3, outMask: 3<<62 | 3}, + + // rotation + {start: 32, end: 63, amount: 32, inMask: 0xffffffff00000000, outMask: 0x00000000ffffffff}, + {start: 48, end: 15, amount: 16, inMask: 0xffffffff00000000, outMask: 0xffff00000000ffff}, + {start: 0, end: 7, amount: -8 & 63, inMask: 0xff, outMask: 0xff << 56}, + } + for i, test := range tests { + r := NewRotateParams(test.start, test.end, test.amount) + if m := r.OutMask(); m != test.outMask { + t.Errorf("out mask %v: want %#x, got %#x", i, test.outMask, m) + } + if m := r.InMask(); m != test.inMask { + t.Errorf("in mask %v: want %#x, got %#x", i, test.inMask, m) + } + } +} + +func TestRotateParamsMerge(t *testing.T) { + tests := []struct { + // inputs + src RotateParams + mask uint64 + + // results + in *RotateParams + out *RotateParams + }{ + { + src: RotateParams{Start: 48, End: 15, Amount: 16}, + mask: 0xffffffffffffffff, + in: &RotateParams{Start: 48, End: 15, Amount: 16}, + out: &RotateParams{Start: 48, End: 15, Amount: 16}, + }, + { + src: RotateParams{Start: 16, End: 47, Amount: 0}, + mask: 0x00000000ffffffff, + in: &RotateParams{Start: 32, End: 47, Amount: 0}, + out: &RotateParams{Start: 32, End: 47, Amount: 0}, + }, + { + src: RotateParams{Start: 16, End: 47, Amount: 0}, + mask: 0xffff00000000ffff, + in: nil, + out: nil, + }, + { + src: RotateParams{Start: 0, End: 63, Amount: 0}, + mask: 0xf7f0000000000000, + in: nil, + out: nil, + }, + { + src: RotateParams{Start: 0, End: 63, Amount: 1}, + mask: 0x000000000000ff00, + in: &RotateParams{Start: 47, End: 54, Amount: 1}, + out: &RotateParams{Start: 48, End: 55, Amount: 1}, + }, + { + src: RotateParams{Start: 32, End: 63, Amount: 32}, + mask: 0xffff00000000ffff, + in: &RotateParams{Start: 32, End: 47, Amount: 32}, + out: &RotateParams{Start: 48, End: 63, Amount: 32}, + }, + { + src: RotateParams{Start: 0, End: 31, Amount: 32}, + mask: 0x8000000000000000, + in: nil, + out: &RotateParams{Start: 0, End: 0, Amount: 32}, + }, + { + src: RotateParams{Start: 0, End: 31, Amount: 32}, + mask: 0x0000000080000000, + in: &RotateParams{Start: 0, End: 0, Amount: 32}, + out: nil, + }, + } + + eq := func(x, y *RotateParams) bool { + if x == nil && y == nil { + return true + } + if x == nil || y == nil { + return false + } + return *x == *y + } + + for _, test := range tests { + if r := test.src.InMerge(test.mask); !eq(r, test.in) { + t.Errorf("%v merged with %#x (input): want %v, got %v", test.src, test.mask, test.in, r) + } + if r := test.src.OutMerge(test.mask); !eq(r, test.out) { + t.Errorf("%v merged with %#x (output): want %v, got %v", test.src, test.mask, test.out, r) + } + } +} diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go index 08788f14471..7abc1c2783e 100644 --- a/test/codegen/bitfield.go +++ b/test/codegen/bitfield.go @@ -127,11 +127,13 @@ func sbfx6(x int32) int32 { // ubfiz func ubfiz1(x uint64) uint64 { // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]12",-"LSL",-"AND" + // s390x:"RISBGZ\t[$]49, [$]60, [$]3,",-"SLD",-"AND" return (x & 0xfff) << 3 } func ubfiz2(x uint64) uint64 { // arm64:"UBFIZ\t[$]4, R[0-9]+, [$]12",-"LSL",-"AND" + // s390x:"RISBGZ\t[$]48, [$]59, [$]4,",-"SLD",-"AND" return (x << 4) & 0xfff0 } @@ -149,6 +151,7 @@ func ubfiz5(x uint8) uint64 { func ubfiz6(x uint64) uint64 { // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]60",-"LSL",-"LSR" + // s390x:"RISBGZ\t[$]3, [$]62, [$]1, ",-"SLD",-"SRD" return (x << 4) >> 3 } @@ -159,6 +162,7 @@ func ubfiz7(x uint32) uint32 { func ubfiz8(x uint64) uint64 { // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]20",-"LSL",-"LSR" + // s390x:"RISBGZ\t[$]43, [$]62, [$]1, ",-"SLD",-"SRD",-"AND" return ((x & 0xfffff) << 4) >> 3 } @@ -169,17 +173,20 @@ func ubfiz9(x uint64) uint64 { func ubfiz10(x uint64) uint64 { // arm64:"UBFIZ\t[$]7, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND" + // s390x:"RISBGZ\t[$]45, [$]56, [$]7, ",-"SLD",-"SRD",-"AND" return ((x << 5) & (0xfff << 5)) << 2 } // ubfx func ubfx1(x uint64) uint64 { // arm64:"UBFX\t[$]25, R[0-9]+, [$]10",-"LSR",-"AND" + // s390x:"RISBGZ\t[$]54, [$]63, [$]39, ",-"SRD",-"AND" return (x >> 25) & 1023 } func ubfx2(x uint64) uint64 { // arm64:"UBFX\t[$]4, R[0-9]+, [$]8",-"LSR",-"AND" + // s390x:"RISBGZ\t[$]56, [$]63, [$]60, ",-"SRD",-"AND" return (x & 0x0ff0) >> 4 } @@ -196,30 +203,37 @@ func ubfx5(x uint8) uint64 { } func ubfx6(x uint64) uint64 { - return (x << 1) >> 2 // arm64:"UBFX\t[$]1, R[0-9]+, [$]62",-"LSL",-"LSR" + // arm64:"UBFX\t[$]1, R[0-9]+, [$]62",-"LSL",-"LSR" + // s390x:"RISBGZ\t[$]2, [$]63, [$]63,",-"SLD",-"SRD" + return (x << 1) >> 2 } func ubfx7(x uint32) uint32 { - return (x << 1) >> 2 // arm64:"UBFX\t[$]1, R[0-9]+, [$]30",-"LSL",-"LSR" + // arm64:"UBFX\t[$]1, R[0-9]+, [$]30",-"LSL",-"LSR" + return (x << 1) >> 2 } func ubfx8(x uint64) uint64 { // arm64:"UBFX\t[$]1, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND" + // s390x:"RISBGZ\t[$]52, [$]63, [$]63,",-"SLD",-"SRD",-"AND" return ((x << 1) >> 2) & 0xfff } func ubfx9(x uint64) uint64 { // arm64:"UBFX\t[$]4, R[0-9]+, [$]11",-"LSL",-"LSR",-"AND" + // s390x:"RISBGZ\t[$]53, [$]63, [$]60, ",-"SLD",-"SRD",-"AND" return ((x >> 3) & 0xfff) >> 1 } func ubfx10(x uint64) uint64 { // arm64:"UBFX\t[$]5, R[0-9]+, [$]56",-"LSL",-"LSR" + // s390x:"RISBGZ\t[$]8, [$]63, [$]59, ",-"SLD",-"SRD" return ((x >> 2) << 5) >> 8 } func ubfx11(x uint64) uint64 { // arm64:"UBFX\t[$]1, R[0-9]+, [$]19",-"LSL",-"LSR" + // s390x:"RISBGZ\t[$]45, [$]63, [$]63, ",-"SLD",-"SRD",-"AND" return ((x & 0xfffff) << 3) >> 4 } diff --git a/test/codegen/bits.go b/test/codegen/bits.go index 398dd84e9e0..56e0f3474e1 100644 --- a/test/codegen/bits.go +++ b/test/codegen/bits.go @@ -340,3 +340,15 @@ func bitSetTest(x int) bool { // amd64:"CMPQ\tAX, [$]9" return x&9 == 9 } + +// mask contiguous one bits +func cont1Mask64U(x uint64) uint64 { + // s390x:"RISBGZ\t[$]16, [$]47, [$]0," + return x&0x0000ffffffff0000 +} + +// mask contiguous zero bits +func cont0Mask64U(x uint64) uint64 { + // s390x:"RISBGZ\t[$]48, [$]15, [$]0," + return x&0xffff00000000ffff +} diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go index 4c35f26997c..fff6639546e 100644 --- a/test/codegen/mathbits.go +++ b/test/codegen/mathbits.go @@ -213,7 +213,7 @@ func RotateLeft64(n uint64) uint64 { // arm64:"ROR" // ppc64:"ROTL" // ppc64le:"ROTL" - // s390x:"RLLG" + // s390x:"RISBGZ\t[$]0, [$]63, [$]37, " // wasm:"I64Rotl" return bits.RotateLeft64(n, 37) } diff --git a/test/codegen/rotate.go b/test/codegen/rotate.go index 0c8b0309703..e0bcd0abbcc 100644 --- a/test/codegen/rotate.go +++ b/test/codegen/rotate.go @@ -17,21 +17,21 @@ func rot64(x uint64) uint64 { // amd64:"ROLQ\t[$]7" // arm64:"ROR\t[$]57" - // s390x:"RLLG\t[$]7" + // s390x:"RISBGZ\t[$]0, [$]63, [$]7, " // ppc64:"ROTL\t[$]7" // ppc64le:"ROTL\t[$]7" a += x<<7 | x>>57 // amd64:"ROLQ\t[$]8" // arm64:"ROR\t[$]56" - // s390x:"RLLG\t[$]8" + // s390x:"RISBGZ\t[$]0, [$]63, [$]8, " // ppc64:"ROTL\t[$]8" // ppc64le:"ROTL\t[$]8" a += x<<8 + x>>56 // amd64:"ROLQ\t[$]9" // arm64:"ROR\t[$]55" - // s390x:"RLLG\t[$]9" + // s390x:"RISBGZ\t[$]0, [$]63, [$]9, " // ppc64:"ROTL\t[$]9" // ppc64le:"ROTL\t[$]9" a += x<<9 ^ x>>55 diff --git a/test/codegen/shift.go b/test/codegen/shift.go index a45f27c9cff..d19a1984c19 100644 --- a/test/codegen/shift.go +++ b/test/codegen/shift.go @@ -11,84 +11,84 @@ package codegen // ------------------ // func lshMask64x64(v int64, s uint64) int64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" return v << (s & 63) } func rshMask64Ux64(v uint64, s uint64) uint64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" return v >> (s & 63) } func rshMask64x64(v int64, s uint64) int64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" return v >> (s & 63) } func lshMask32x64(v int32, s uint64) int32 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ISEL",-"ORN" // ppc64:"ISEL",-"ORN" return v << (s & 63) } func rshMask32Ux64(v uint32, s uint64) uint32 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ISEL",-"ORN" // ppc64:"ISEL",-"ORN" return v >> (s & 63) } func rshMask32x64(v int32, s uint64) int32 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ISEL",-"ORN" // ppc64:"ISEL",-"ORN" return v >> (s & 63) } func lshMask64x32(v int64, s uint32) int64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN" // ppc64:"ANDCC",-"ORN" return v << (s & 63) } func rshMask64Ux32(v uint64, s uint32) uint64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN" // ppc64:"ANDCC",-"ORN" return v >> (s & 63) } func rshMask64x32(v int64, s uint32) int64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" return v >> (s & 63) } func lshMask64x32Ext(v int64, s int32) int64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" return v << uint(s&63) } func rshMask64Ux32Ext(v uint64, s int32) uint64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" return v >> uint(s&63) } func rshMask64x32Ext(v int64, s int32) int64 { - // s390x:-".*AND",-".*MOVDGE" + // s390x:-"RISBGZ",-"AND",-"LOCGR" // ppc64le:"ANDCC",-"ORN",-"ISEL" // ppc64:"ANDCC",-"ORN",-"ISEL" return v >> uint(s&63) @@ -128,7 +128,8 @@ func lshSignedMasked(v8 int8, v16 int16, v32 int32, v64 int64, x int) { func rshGuarded64(v int64, s uint) int64 { if s < 64 { - // s390x:-".*AND",-".*MOVDGE" wasm:-"Select",-".*LtU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" + // wasm:-"Select",-".*LtU" return v >> s } panic("shift too large") @@ -136,7 +137,8 @@ func rshGuarded64(v int64, s uint) int64 { func rshGuarded64U(v uint64, s uint) uint64 { if s < 64 { - // s390x:-".*AND",-".*MOVDGE" wasm:-"Select",-".*LtU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" + // wasm:-"Select",-".*LtU" return v >> s } panic("shift too large") @@ -144,7 +146,8 @@ func rshGuarded64U(v uint64, s uint) uint64 { func lshGuarded64(v int64, s uint) int64 { if s < 64 { - // s390x:-".*AND",-".*MOVDGE" wasm:-"Select",-".*LtU" + // s390x:-"RISBGZ",-"AND",-"LOCGR" + // wasm:-"Select",-".*LtU" return v << s } panic("shift too large") From d21af00dd22d478d0026797c91961168ba83aff9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 29 Oct 2020 12:20:53 -0400 Subject: [PATCH 372/403] path/filepath: add WalkDir WalkDir is like Walk but can use ReadDir to read directories, instead of Readdirnames + Lstat on every entry, which is usually a significant performance improvement. (The Lstat can still happen if the walk function calls d.Info.) Fixes #42027. [Replay of CL 266240 after it was reverted due to accidentally enabling on Windows a test that does not work on Windows. The original code only ran the test on os.Getuid() > 0. The rolled-back CL skipped the test on os.Getuid() == 0. But on Windows, os.Getuid(), it turns out, always returns -1. So what looked like a test for root was also excluding Windows. This CL revises the test to skip Windows explicitly.] Change-Id: I9b3661013d6449b7486532445d934ae91e5393ef Reviewed-on: https://go-review.googlesource.com/c/go/+/267887 Trust: Russ Cox Run-TryBot: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/path/filepath/export_test.go | 2 + src/path/filepath/path.go | 213 +++++++++++++++++++++++++++---- src/path/filepath/path_test.go | 92 ++++++++----- 3 files changed, 253 insertions(+), 54 deletions(-) diff --git a/src/path/filepath/export_test.go b/src/path/filepath/export_test.go index 0cf9e3bca11..e7ad7dd01a1 100644 --- a/src/path/filepath/export_test.go +++ b/src/path/filepath/export_test.go @@ -5,3 +5,5 @@ package filepath var LstatP = &lstat + +type DirEntryFromInfo = dirEntryFromInfo diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go index dffd27db146..3f7e5c713dc 100644 --- a/src/path/filepath/path.go +++ b/src/path/filepath/path.go @@ -336,25 +336,130 @@ func Rel(basepath, targpath string) (string, error) { // as an error by any function. var SkipDir = errors.New("skip this directory") -// WalkFunc is the type of the function called for each file or directory -// visited by Walk. The path argument contains the argument to Walk as a -// prefix; that is, if Walk is called with "dir", which is a directory -// containing the file "a", the walk function will be called with argument -// "dir/a". The info argument is the fs.FileInfo for the named path. +// WalkDirFunc is the type of the function called by WalkDir to visit +// each each file or directory. // -// If there was a problem walking to the file or directory named by path, the -// incoming error will describe the problem and the function can decide how -// to handle that error (and Walk will not descend into that directory). In the -// case of an error, the info argument will be nil. If an error is returned, -// processing stops. The sole exception is when the function returns the special -// value SkipDir. If the function returns SkipDir when invoked on a directory, -// Walk skips the directory's contents entirely. If the function returns SkipDir -// when invoked on a non-directory file, Walk skips the remaining files in the -// containing directory. +// The path argument contains the argument to Walk as a prefix. +// That is, if Walk is called with root argument "dir" and finds a file +// named "a" in that directory, the walk function will be called with +// argument "dir/a". +// +// The directory and file are joined with Join, which may clean the +// directory name: if Walk is called with the root argument "x/../dir" +// and finds a file named "a" in that directory, the walk function will +// be called with argument "dir/a", not "x/../dir/a". +// +// The d argument is the fs.DirEntry for the named path. +// +// The error result returned by the function controls how WalkDir +// continues. If the function returns the special value SkipDir, WalkDir +// skips the current directory (path if d.IsDir() is true, otherwise +// path's parent directory). Otherwise, if the function returns a non-nil +// error, WalkDir stops entirely and returns that error. +// +// The err argument reports an error related to path, signaling that +// WalkDir will not walk into that directory. The function can decide how +// to handle that error; as described earlier, returning the error will +// cause WalkDir to stop walking the entire tree. +// +// WalkDir calls the function with a non-nil err argument in two cases. +// +// First, if the initial os.Lstat on the root directory fails, WalkDir +// calls the function with path set to root, d set to nil, and err set to +// the error from os.Lstat. +// +// Second, if a directory's ReadDir method fails, WalkDir calls the +// function with path set to the directory's path, d set to an +// fs.DirEntry describing the directory, and err set to the error from +// ReadDir. In this second case, the function is called twice with the +// path of the directory: the first call is before the directory read is +// attempted and has err set to nil, giving the function a chance to +// return SkipDir and avoid the ReadDir entirely. The second call is +// after a failed ReadDir and reports the error from ReadDir. +// (If ReadDir succeeds, there is no second call.) +// +// The differences between WalkDirFunc compared to WalkFunc are: +// +// - The second argument has type fs.DirEntry instead of fs.FileInfo. +// - The function is called before reading a directory, to allow SkipDir +// to bypass the directory read entirely. +// - If a directory read fails, the function is called a second time +// for that directory to report the error. +// +type WalkDirFunc func(path string, d fs.DirEntry, err error) error + +// WalkFunc is the type of the function called by Walk to visit each each +// file or directory. +// +// The path argument contains the argument to Walk as a prefix. +// That is, if Walk is called with root argument "dir" and finds a file +// named "a" in that directory, the walk function will be called with +// argument "dir/a". +// +// The directory and file are joined with Join, which may clean the +// directory name: if Walk is called with the root argument "x/../dir" +// and finds a file named "a" in that directory, the walk function will +// be called with argument "dir/a", not "x/../dir/a". +// +// The info argument is the fs.FileInfo for the named path. +// +// The error result returned by the function controls how Walk continues. +// If the function returns the special value SkipDir, Walk skips the +// current directory (path if info.IsDir() is true, otherwise path's +// parent directory). Otherwise, if the function returns a non-nil error, +// Walk stops entirely and returns that error. +// +// The err argument reports an error related to path, signaling that Walk +// will not walk into that directory. The function can decide how to +// handle that error; as described earlier, returning the error will +// cause Walk to stop walking the entire tree. +// +// Walk calls the function with a non-nil err argument in two cases. +// +// First, if an os.Lstat on the root directory or any directory or file +// in the tree fails, Walk calls the function with path set to that +// directory or file's path, info set to nil, and err set to the error +// from os.Lstat. +// +// Second, if a directory's Readdirnames method fails, Walk calls the +// function with path set to the directory's path, info, set to an +// fs.FileInfo describing the directory, and err set to the error from +// Readdirnames. type WalkFunc func(path string, info fs.FileInfo, err error) error var lstat = os.Lstat // for testing +// walkDir recursively descends path, calling walkDirFn. +func walkDir(path string, d fs.DirEntry, walkDirFn WalkDirFunc) error { + if err := walkDirFn(path, d, nil); err != nil || !d.IsDir() { + if err == SkipDir && d.IsDir() { + // Successfully skipped directory. + err = nil + } + return err + } + + dirs, err := readDir(path) + if err != nil { + // Second call, to report ReadDir error. + err = walkDirFn(path, d, err) + if err != nil { + return err + } + } + + for _, d1 := range dirs { + path1 := Join(path, d1.Name()) + if err := walkDir(path1, d1, walkDirFn); err != nil { + if err == SkipDir { + break + } + return err + } + } + return nil +} + // walk recursively descends path, calling walkFn. func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { if !info.IsDir() { @@ -393,18 +498,23 @@ func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { return nil } -// Walk walks the file tree rooted at root, calling walkFn for each file or -// directory in the tree, including root. All errors that arise visiting files -// and directories are filtered by walkFn. The files are walked in lexical -// order, which makes the output deterministic but means that for very -// large directories Walk can be inefficient. -// Walk does not follow symbolic links. -func Walk(root string, walkFn WalkFunc) error { +// WalkDir walks the file tree rooted at root, calling fn for each file or +// directory in the tree, including root. +// +// All errors that arise visiting files and directories are filtered by fn: +// see the WalkDirFunc documentation for details. +// +// The files are walked in lexical order, which makes the output deterministic +// but requires WalkDir to read an entire directory into memory before proceeding +// to walk that directory. +// +// WalkDir does not follow symbolic links. +func WalkDir(root string, fn WalkDirFunc) error { info, err := os.Lstat(root) if err != nil { - err = walkFn(root, nil, err) + err = fn(root, nil, err) } else { - err = walk(root, info, walkFn) + err = walkDir(root, &dirEntryFromInfo{info}, fn) } if err == SkipDir { return nil @@ -412,8 +522,63 @@ func Walk(root string, walkFn WalkFunc) error { return err } -// readDirNames reads the directory named by dirname and returns +type dirEntryFromInfo struct { + fs.FileInfo +} + +func (e *dirEntryFromInfo) Type() fs.FileMode { + return e.Mode().Type() +} + +func (e *dirEntryFromInfo) Info() (fs.FileInfo, error) { + return e.FileInfo, nil +} + +// Walk walks the file tree rooted at root, calling fn for each file or +// directory in the tree, including root. +// +// All errors that arise visiting files and directories are filtered by fn: +// see the WalkFunc documentation for details. +// +// The files are walked in lexical order, which makes the output deterministic +// but requires Walk to read an entire directory into memory before proceeding +// to walk that directory. +// +// Walk does not follow symbolic links. +// +// Walk is less efficient than WalkDir, introduced in Go 1.16, +// which avoids calling os.Lstat on every visited file or directory. +func Walk(root string, fn WalkFunc) error { + info, err := os.Lstat(root) + if err != nil { + err = fn(root, nil, err) + } else { + err = walk(root, info, fn) + } + if err == SkipDir { + return nil + } + return err +} + +// readDir reads the directory named by dirname and returns // a sorted list of directory entries. +func readDir(dirname string) ([]fs.DirEntry, error) { + f, err := os.Open(dirname) + if err != nil { + return nil, err + } + dirs, err := f.ReadDir(-1) + f.Close() + if err != nil { + return nil, err + } + sort.Slice(dirs, func(i, j int) bool { return dirs[i].Name() < dirs[j].Name() }) + return dirs, nil +} + +// readDirNames reads the directory named by dirname and returns +// a sorted list of directory entry names. func readDirNames(dirname string) ([]string, error) { f, err := os.Open(dirname) if err != nil { diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index 7dc8b60c28c..ec6f8f2de9b 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -394,8 +394,8 @@ func checkMarks(t *testing.T, report bool) { // Assumes that each node name is unique. Good enough for a test. // If clear is true, any incoming error is cleared before return. The errors // are always accumulated, though. -func mark(info fs.FileInfo, err error, errors *[]error, clear bool) error { - name := info.Name() +func mark(d fs.DirEntry, err error, errors *[]error, clear bool) error { + name := d.Name() walkTree(tree, tree.name, func(path string, n *Node) { if n.name == name { n.mark++ @@ -432,6 +432,19 @@ func chtmpdir(t *testing.T) (restore func()) { } func TestWalk(t *testing.T) { + walk := func(root string, fn filepath.WalkDirFunc) error { + return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { + return fn(path, &filepath.DirEntryFromInfo{info}, err) + }) + } + testWalk(t, walk, 1) +} + +func TestWalkDir(t *testing.T) { + testWalk(t, filepath.WalkDir, 2) +} + +func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVisit int) { if runtime.GOOS == "ios" { restore := chtmpdir(t) defer restore() @@ -455,11 +468,11 @@ func TestWalk(t *testing.T) { makeTree(t) errors := make([]error, 0, 10) clear := true - markFn := func(path string, info fs.FileInfo, err error) error { - return mark(info, err, &errors, clear) + markFn := func(path string, d fs.DirEntry, err error) error { + return mark(d, err, &errors, clear) } // Expect no errors. - err = filepath.Walk(tree.name, markFn) + err = walk(tree.name, markFn) if err != nil { t.Fatalf("no error expected, found: %s", err) } @@ -469,10 +482,20 @@ func TestWalk(t *testing.T) { checkMarks(t, true) errors = errors[0:0] - // Test permission errors. Only possible if we're not root - // and only on some file systems (AFS, FAT). To avoid errors during - // all.bash on those file systems, skip during go test -short. - if os.Getuid() > 0 && !testing.Short() { + t.Run("PermErr", func(t *testing.T) { + // Test permission errors. Only possible if we're not root + // and only on some file systems (AFS, FAT). To avoid errors during + // all.bash on those file systems, skip during go test -short. + if runtime.GOOS == "windows" { + t.Skip("skipping on Windows") + } + if os.Getuid() == 0 { + t.Skip("skipping as root") + } + if testing.Short() { + t.Skip("skipping in short mode") + } + // introduce 2 errors: chmod top-level directories to 0 os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0) @@ -482,9 +505,9 @@ func TestWalk(t *testing.T) { markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself - tree.entries[1].mark-- - tree.entries[3].mark-- - err := filepath.Walk(tree.name, markFn) + tree.entries[1].mark -= errVisit + tree.entries[3].mark -= errVisit + err := walk(tree.name, markFn) if err != nil { t.Fatalf("expected no error return from Walk, got %s", err) } @@ -500,10 +523,10 @@ func TestWalk(t *testing.T) { markTree(tree.entries[1]) markTree(tree.entries[3]) // correct double-marking of directory itself - tree.entries[1].mark-- - tree.entries[3].mark-- + tree.entries[1].mark -= errVisit + tree.entries[3].mark -= errVisit clear = false // error will stop processing - err = filepath.Walk(tree.name, markFn) + err = walk(tree.name, markFn) if err == nil { t.Fatalf("expected error return from Walk") } @@ -517,7 +540,7 @@ func TestWalk(t *testing.T) { // restore permissions os.Chmod(filepath.Join(tree.name, tree.entries[1].name), 0770) os.Chmod(filepath.Join(tree.name, tree.entries[3].name), 0770) - } + }) } func touch(t *testing.T, name string) { @@ -544,7 +567,7 @@ func TestWalkSkipDirOnFile(t *testing.T) { touch(t, filepath.Join(td, "dir/foo2")) sawFoo2 := false - walker := func(path string, info fs.FileInfo, err error) error { + walker := func(path string) error { if strings.HasSuffix(path, "foo2") { sawFoo2 = true } @@ -553,22 +576,31 @@ func TestWalkSkipDirOnFile(t *testing.T) { } return nil } + walkFn := func(path string, _ fs.FileInfo, _ error) error { return walker(path) } + walkDirFn := func(path string, _ fs.DirEntry, _ error) error { return walker(path) } - err = filepath.Walk(td, walker) - if err != nil { - t.Fatal(err) - } - if sawFoo2 { - t.Errorf("SkipDir on file foo1 did not block processing of foo2") + check := func(t *testing.T, walk func(root string) error, root string) { + t.Helper() + sawFoo2 = false + err = walk(root) + if err != nil { + t.Fatal(err) + } + if sawFoo2 { + t.Errorf("SkipDir on file foo1 did not block processing of foo2") + } } - err = filepath.Walk(filepath.Join(td, "dir"), walker) - if err != nil { - t.Fatal(err) - } - if sawFoo2 { - t.Errorf("SkipDir on file foo1 did not block processing of foo2") - } + t.Run("Walk", func(t *testing.T) { + Walk := func(root string) error { return filepath.Walk(td, walkFn) } + check(t, Walk, td) + check(t, Walk, filepath.Join(td, "dir")) + }) + t.Run("WalkDir", func(t *testing.T) { + WalkDir := func(root string) error { return filepath.WalkDir(td, walkDirFn) } + check(t, WalkDir, td) + check(t, WalkDir, filepath.Join(td, "dir")) + }) } func TestWalkFileError(t *testing.T) { From 362d25f2c82980860cb4eb5bfd0648116504788d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jul 2020 01:31:05 -0400 Subject: [PATCH 373/403] io/fs: add WalkDir This commit is a copy of filepath.WalkDir adapted to use fs.FS instead of the native OS file system. It is the last implementation piece of the io/fs proposal. The original io/fs proposal was to adopt filepath.Walk, but we have since introduced the more efficient filepath.WalkDir (#42027), so this CL adopts that more efficient option instead. (The changes in path/filepath bring the two copies more in line with each other. The main change is unembedding the field in statDirEntry, so that the fs.DirEntry passed to the WalkDirFunc for the root of the tree does not have any extra methods.) For #41190. Change-Id: I9359dfcc110338c0ec64535f22cafb38d0b613a6 Reviewed-on: https://go-review.googlesource.com/c/go/+/243916 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Rob Pike --- src/io/fs/walk.go | 132 ++++++++++++++++++++++++++ src/io/fs/walk_test.go | 155 +++++++++++++++++++++++++++++++ src/path/filepath/export_test.go | 2 - src/path/filepath/path.go | 77 +++------------ src/path/filepath/path_test.go | 15 ++- 5 files changed, 310 insertions(+), 71 deletions(-) create mode 100644 src/io/fs/walk.go create mode 100644 src/io/fs/walk_test.go diff --git a/src/io/fs/walk.go b/src/io/fs/walk.go new file mode 100644 index 00000000000..e50c1bb15ce --- /dev/null +++ b/src/io/fs/walk.go @@ -0,0 +1,132 @@ +// Copyright 2020 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 fs + +import ( + "errors" + "path" +) + +// SkipDir is used as a return value from WalkFuncs to indicate that +// the directory named in the call is to be skipped. It is not returned +// as an error by any function. +var SkipDir = errors.New("skip this directory") + +// WalkDirFunc is the type of the function called by WalkDir to visit +// each each file or directory. +// +// The path argument contains the argument to Walk as a prefix. +// That is, if Walk is called with root argument "dir" and finds a file +// named "a" in that directory, the walk function will be called with +// argument "dir/a". +// +// The directory and file are joined with Join, which may clean the +// directory name: if Walk is called with the root argument "x/../dir" +// and finds a file named "a" in that directory, the walk function will +// be called with argument "dir/a", not "x/../dir/a". +// +// The d argument is the fs.DirEntry for the named path. +// +// The error result returned by the function controls how WalkDir +// continues. If the function returns the special value SkipDir, WalkDir +// skips the current directory (path if d.IsDir() is true, otherwise +// path's parent directory). Otherwise, if the function returns a non-nil +// error, WalkDir stops entirely and returns that error. +// +// The err argument reports an error related to path, signaling that +// WalkDir will not walk into that directory. The function can decide how +// to handle that error; as described earlier, returning the error will +// cause WalkDir to stop walking the entire tree. +// +// WalkDir calls the function with a non-nil err argument in two cases. +// +// First, if the initial os.Lstat on the root directory fails, WalkDir +// calls the function with path set to root, d set to nil, and err set to +// the error from os.Lstat. +// +// Second, if a directory's ReadDir method fails, WalkDir calls the +// function with path set to the directory's path, d set to an +// fs.DirEntry describing the directory, and err set to the error from +// ReadDir. In this second case, the function is called twice with the +// path of the directory: the first call is before the directory read is +// attempted and has err set to nil, giving the function a chance to +// return SkipDir and avoid the ReadDir entirely. The second call is +// after a failed ReadDir and reports the error from ReadDir. +// (If ReadDir succeeds, there is no second call.) +// +// The differences between WalkDirFunc compared to WalkFunc are: +// +// - The second argument has type fs.DirEntry instead of fs.FileInfo. +// - The function is called before reading a directory, to allow SkipDir +// to bypass the directory read entirely. +// - If a directory read fails, the function is called a second time +// for that directory to report the error. +// +type WalkDirFunc func(path string, entry DirEntry, err error) error + +// walkDir recursively descends path, calling walkDirFn. +func walkDir(fsys FS, name string, d DirEntry, walkDirFn WalkDirFunc) error { + if err := walkDirFn(name, d, nil); err != nil || !d.IsDir() { + if err == SkipDir && d.IsDir() { + // Successfully skipped directory. + err = nil + } + return err + } + + dirs, err := ReadDir(fsys, name) + if err != nil { + // Second call, to report ReadDir error. + err = walkDirFn(name, d, err) + if err != nil { + return err + } + } + + for _, d1 := range dirs { + name1 := path.Join(name, d1.Name()) + if err := walkDir(fsys, name1, d1, walkDirFn); err != nil { + if err == SkipDir { + break + } + return err + } + } + return nil +} + +// WalkDir walks the file tree rooted at root, calling fn for each file or +// directory in the tree, including root. +// +// All errors that arise visiting files and directories are filtered by fn: +// see the fs.WalkDirFunc documentation for details. +// +// The files are walked in lexical order, which makes the output deterministic +// but requires WalkDir to read an entire directory into memory before proceeding +// to walk that directory. +// +// WalkDir does not follow symbolic links found in directories, +// but if root itself is a symbolic link, its target will be walked. +func WalkDir(fsys FS, root string, fn WalkDirFunc) error { + info, err := Stat(fsys, root) + if err != nil { + err = fn(root, nil, err) + } else { + err = walkDir(fsys, root, &statDirEntry{info}, fn) + } + if err == SkipDir { + return nil + } + return err +} + +type statDirEntry struct { + info FileInfo +} + +func (d *statDirEntry) Name() string { return d.info.Name() } +func (d *statDirEntry) IsDir() bool { return d.info.IsDir() } +func (d *statDirEntry) Type() FileMode { return d.info.Mode().Type() } +func (d *statDirEntry) Info() (FileInfo, error) { return d.info, nil } diff --git a/src/io/fs/walk_test.go b/src/io/fs/walk_test.go new file mode 100644 index 00000000000..395471e2e8a --- /dev/null +++ b/src/io/fs/walk_test.go @@ -0,0 +1,155 @@ +// Copyright 2020 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 fs_test + +import ( + . "io/fs" + "io/ioutil" + "os" + pathpkg "path" + "runtime" + "testing" + "testing/fstest" +) + +type Node struct { + name string + entries []*Node // nil if the entry is a file + mark int +} + +var tree = &Node{ + "testdata", + []*Node{ + {"a", nil, 0}, + {"b", []*Node{}, 0}, + {"c", nil, 0}, + { + "d", + []*Node{ + {"x", nil, 0}, + {"y", []*Node{}, 0}, + { + "z", + []*Node{ + {"u", nil, 0}, + {"v", nil, 0}, + }, + 0, + }, + }, + 0, + }, + }, + 0, +} + +func walkTree(n *Node, path string, f func(path string, n *Node)) { + f(path, n) + for _, e := range n.entries { + walkTree(e, pathpkg.Join(path, e.name), f) + } +} + +func makeTree(t *testing.T) FS { + fsys := fstest.MapFS{} + walkTree(tree, tree.name, func(path string, n *Node) { + if n.entries == nil { + fsys[path] = &fstest.MapFile{} + } else { + fsys[path] = &fstest.MapFile{Mode: ModeDir} + } + }) + return fsys +} + +func markTree(n *Node) { walkTree(n, "", func(path string, n *Node) { n.mark++ }) } + +func checkMarks(t *testing.T, report bool) { + walkTree(tree, tree.name, func(path string, n *Node) { + if n.mark != 1 && report { + t.Errorf("node %s mark = %d; expected 1", path, n.mark) + } + n.mark = 0 + }) +} + +// Assumes that each node name is unique. Good enough for a test. +// If clear is true, any incoming error is cleared before return. The errors +// are always accumulated, though. +func mark(entry DirEntry, err error, errors *[]error, clear bool) error { + name := entry.Name() + walkTree(tree, tree.name, func(path string, n *Node) { + if n.name == name { + n.mark++ + } + }) + if err != nil { + *errors = append(*errors, err) + if clear { + return nil + } + return err + } + return nil +} + +func chtmpdir(t *testing.T) (restore func()) { + oldwd, err := os.Getwd() + if err != nil { + t.Fatalf("chtmpdir: %v", err) + } + d, err := ioutil.TempDir("", "test") + if err != nil { + t.Fatalf("chtmpdir: %v", err) + } + if err := os.Chdir(d); err != nil { + t.Fatalf("chtmpdir: %v", err) + } + return func() { + if err := os.Chdir(oldwd); err != nil { + t.Fatalf("chtmpdir: %v", err) + } + os.RemoveAll(d) + } +} + +func TestWalkDir(t *testing.T) { + if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" { + restore := chtmpdir(t) + defer restore() + } + + tmpDir, err := ioutil.TempDir("", "TestWalk") + if err != nil { + t.Fatal("creating temp dir:", err) + } + defer os.RemoveAll(tmpDir) + + origDir, err := os.Getwd() + if err != nil { + t.Fatal("finding working dir:", err) + } + if err = os.Chdir(tmpDir); err != nil { + t.Fatal("entering temp dir:", err) + } + defer os.Chdir(origDir) + + fsys := makeTree(t) + errors := make([]error, 0, 10) + clear := true + markFn := func(path string, entry DirEntry, err error) error { + return mark(entry, err, &errors, clear) + } + // Expect no errors. + err = WalkDir(fsys, ".", markFn) + if err != nil { + t.Fatalf("no error expected, found: %s", err) + } + if len(errors) != 0 { + t.Fatalf("unexpected errors: %s", errors) + } + checkMarks(t, true) +} diff --git a/src/path/filepath/export_test.go b/src/path/filepath/export_test.go index e7ad7dd01a1..0cf9e3bca11 100644 --- a/src/path/filepath/export_test.go +++ b/src/path/filepath/export_test.go @@ -5,5 +5,3 @@ package filepath var LstatP = &lstat - -type DirEntryFromInfo = dirEntryFromInfo diff --git a/src/path/filepath/path.go b/src/path/filepath/path.go index 3f7e5c713dc..2e7b439355a 100644 --- a/src/path/filepath/path.go +++ b/src/path/filepath/path.go @@ -334,59 +334,7 @@ func Rel(basepath, targpath string) (string, error) { // SkipDir is used as a return value from WalkFuncs to indicate that // the directory named in the call is to be skipped. It is not returned // as an error by any function. -var SkipDir = errors.New("skip this directory") - -// WalkDirFunc is the type of the function called by WalkDir to visit -// each each file or directory. -// -// The path argument contains the argument to Walk as a prefix. -// That is, if Walk is called with root argument "dir" and finds a file -// named "a" in that directory, the walk function will be called with -// argument "dir/a". -// -// The directory and file are joined with Join, which may clean the -// directory name: if Walk is called with the root argument "x/../dir" -// and finds a file named "a" in that directory, the walk function will -// be called with argument "dir/a", not "x/../dir/a". -// -// The d argument is the fs.DirEntry for the named path. -// -// The error result returned by the function controls how WalkDir -// continues. If the function returns the special value SkipDir, WalkDir -// skips the current directory (path if d.IsDir() is true, otherwise -// path's parent directory). Otherwise, if the function returns a non-nil -// error, WalkDir stops entirely and returns that error. -// -// The err argument reports an error related to path, signaling that -// WalkDir will not walk into that directory. The function can decide how -// to handle that error; as described earlier, returning the error will -// cause WalkDir to stop walking the entire tree. -// -// WalkDir calls the function with a non-nil err argument in two cases. -// -// First, if the initial os.Lstat on the root directory fails, WalkDir -// calls the function with path set to root, d set to nil, and err set to -// the error from os.Lstat. -// -// Second, if a directory's ReadDir method fails, WalkDir calls the -// function with path set to the directory's path, d set to an -// fs.DirEntry describing the directory, and err set to the error from -// ReadDir. In this second case, the function is called twice with the -// path of the directory: the first call is before the directory read is -// attempted and has err set to nil, giving the function a chance to -// return SkipDir and avoid the ReadDir entirely. The second call is -// after a failed ReadDir and reports the error from ReadDir. -// (If ReadDir succeeds, there is no second call.) -// -// The differences between WalkDirFunc compared to WalkFunc are: -// -// - The second argument has type fs.DirEntry instead of fs.FileInfo. -// - The function is called before reading a directory, to allow SkipDir -// to bypass the directory read entirely. -// - If a directory read fails, the function is called a second time -// for that directory to report the error. -// -type WalkDirFunc func(path string, d fs.DirEntry, err error) error +var SkipDir error = fs.SkipDir // WalkFunc is the type of the function called by Walk to visit each each // file or directory. @@ -430,7 +378,7 @@ type WalkFunc func(path string, info fs.FileInfo, err error) error var lstat = os.Lstat // for testing // walkDir recursively descends path, calling walkDirFn. -func walkDir(path string, d fs.DirEntry, walkDirFn WalkDirFunc) error { +func walkDir(path string, d fs.DirEntry, walkDirFn fs.WalkDirFunc) error { if err := walkDirFn(path, d, nil); err != nil || !d.IsDir() { if err == SkipDir && d.IsDir() { // Successfully skipped directory. @@ -502,19 +450,19 @@ func walk(path string, info fs.FileInfo, walkFn WalkFunc) error { // directory in the tree, including root. // // All errors that arise visiting files and directories are filtered by fn: -// see the WalkDirFunc documentation for details. +// see the fs.WalkDirFunc documentation for details. // // The files are walked in lexical order, which makes the output deterministic // but requires WalkDir to read an entire directory into memory before proceeding // to walk that directory. // // WalkDir does not follow symbolic links. -func WalkDir(root string, fn WalkDirFunc) error { +func WalkDir(root string, fn fs.WalkDirFunc) error { info, err := os.Lstat(root) if err != nil { err = fn(root, nil, err) } else { - err = walkDir(root, &dirEntryFromInfo{info}, fn) + err = walkDir(root, &statDirEntry{info}, fn) } if err == SkipDir { return nil @@ -522,17 +470,14 @@ func WalkDir(root string, fn WalkDirFunc) error { return err } -type dirEntryFromInfo struct { - fs.FileInfo +type statDirEntry struct { + info fs.FileInfo } -func (e *dirEntryFromInfo) Type() fs.FileMode { - return e.Mode().Type() -} - -func (e *dirEntryFromInfo) Info() (fs.FileInfo, error) { - return e.FileInfo, nil -} +func (d *statDirEntry) Name() string { return d.info.Name() } +func (d *statDirEntry) IsDir() bool { return d.info.IsDir() } +func (d *statDirEntry) Type() fs.FileMode { return d.info.Mode().Type() } +func (d *statDirEntry) Info() (fs.FileInfo, error) { return d.info, nil } // Walk walks the file tree rooted at root, calling fn for each file or // directory in the tree, including root. diff --git a/src/path/filepath/path_test.go b/src/path/filepath/path_test.go index ec6f8f2de9b..d760530e260 100644 --- a/src/path/filepath/path_test.go +++ b/src/path/filepath/path_test.go @@ -432,19 +432,28 @@ func chtmpdir(t *testing.T) (restore func()) { } func TestWalk(t *testing.T) { - walk := func(root string, fn filepath.WalkDirFunc) error { + walk := func(root string, fn fs.WalkDirFunc) error { return filepath.Walk(root, func(path string, info fs.FileInfo, err error) error { - return fn(path, &filepath.DirEntryFromInfo{info}, err) + return fn(path, &statDirEntry{info}, err) }) } testWalk(t, walk, 1) } +type statDirEntry struct { + info fs.FileInfo +} + +func (d *statDirEntry) Name() string { return d.info.Name() } +func (d *statDirEntry) IsDir() bool { return d.info.IsDir() } +func (d *statDirEntry) Type() fs.FileMode { return d.info.Mode().Type() } +func (d *statDirEntry) Info() (fs.FileInfo, error) { return d.info, nil } + func TestWalkDir(t *testing.T) { testWalk(t, filepath.WalkDir, 2) } -func testWalk(t *testing.T, walk func(string, filepath.WalkDirFunc) error, errVisit int) { +func testWalk(t *testing.T, walk func(string, fs.WalkDirFunc) error, errVisit int) { if runtime.GOOS == "ios" { restore := chtmpdir(t) defer restore() From 5736eb0013cb8c9b67432c98b08f68e9f370810c Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 29 Oct 2020 01:13:16 -0700 Subject: [PATCH 374/403] cmd/compile: support inlining of type switches This CL adds support for inlining type switches, including exporting and importing them. Type switches are represented mostly the same as expression switches. However, if the type switch guard includes a short variable declaration, then there are two differences: (1) there's an ONONAME (in the OTYPESW's Left) to represent the overall pseudo declaration; and (2) there's an ONAME (in each OCASE's Rlist) to represent the per-case variables. For simplicity, this CL simply writes out each variable separately using iimport/iiexport's normal Vargen mechanism for disambiguating identically named variables within a function. This could be improved somewhat, but inlinable type switches are probably too uncommon to merit the complexity. While here, remove "case OCASE" from typecheck1. We only type check "case" clauses as part of a "select" or "switch" statement, never as standalone statements. Fixes #37837 Change-Id: I8f42f6c9afdd821d6202af4a6bf1dbcbba0ef424 Reviewed-on: https://go-review.googlesource.com/c/go/+/266203 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Matthew Dempsky --- src/cmd/compile/internal/gc/iexport.go | 40 +++++++++++++++++++---- src/cmd/compile/internal/gc/iimport.go | 41 +++++++++++++++++++----- src/cmd/compile/internal/gc/inl.go | 4 --- src/cmd/compile/internal/gc/typecheck.go | 5 --- test/fixedbugs/issue37837.dir/a.go | 33 +++++++++++++++++++ test/fixedbugs/issue37837.dir/b.go | 32 ++++++++++++++++++ test/fixedbugs/issue37837.go | 7 ++++ test/inline.go | 3 +- 8 files changed, 140 insertions(+), 25 deletions(-) create mode 100644 test/fixedbugs/issue37837.dir/a.go create mode 100644 test/fixedbugs/issue37837.dir/b.go create mode 100644 test/fixedbugs/issue37837.go diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go index 9bc1f64600d..1f53d8ca7dc 100644 --- a/src/cmd/compile/internal/gc/iexport.go +++ b/src/cmd/compile/internal/gc/iexport.go @@ -1138,13 +1138,10 @@ func (w *exportWriter) stmt(n *Node) { w.pos(n.Pos) w.stmtList(n.Ninit) w.exprsOrNil(n.Left, nil) - w.stmtList(n.List) + w.caseList(n) - case OCASE: - w.op(OCASE) - w.pos(n.Pos) - w.stmtList(n.List) - w.stmtList(n.Nbody) + // case OCASE: + // handled by caseList case OFALL: w.op(OFALL) @@ -1168,6 +1165,24 @@ func (w *exportWriter) stmt(n *Node) { } } +func (w *exportWriter) caseList(sw *Node) { + namedTypeSwitch := sw.Op == OSWITCH && sw.Left != nil && sw.Left.Op == OTYPESW && sw.Left.Left != nil + + cases := sw.List.Slice() + w.uint64(uint64(len(cases))) + for _, cas := range cases { + if cas.Op != OCASE { + Fatalf("expected OCASE, got %v", cas) + } + w.pos(cas.Pos) + w.stmtList(cas.List) + if namedTypeSwitch { + w.localName(cas.Rlist.First()) + } + w.stmtList(cas.Nbody) + } +} + func (w *exportWriter) exprList(list Nodes) { for _, n := range list.Slice() { w.expr(n) @@ -1232,6 +1247,19 @@ func (w *exportWriter) expr(n *Node) { w.op(OTYPE) w.typ(n.Type) + case OTYPESW: + w.op(OTYPESW) + w.pos(n.Pos) + var s *types.Sym + if n.Left != nil { + if n.Left.Op != ONONAME { + Fatalf("expected ONONAME, got %v", n.Left) + } + s = n.Left.Sym + } + w.localIdent(s, 0) // declared pseudo-variable, if any + w.exprsOrNil(n.Right, nil) + // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: // should have been resolved by typechecking - handled by default case diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go index 7f2b05f288f..c0114d0e53b 100644 --- a/src/cmd/compile/internal/gc/iimport.go +++ b/src/cmd/compile/internal/gc/iimport.go @@ -784,6 +784,28 @@ func (r *importReader) stmtList() []*Node { return list } +func (r *importReader) caseList(sw *Node) []*Node { + namedTypeSwitch := sw.Op == OSWITCH && sw.Left != nil && sw.Left.Op == OTYPESW && sw.Left.Left != nil + + cases := make([]*Node, r.uint64()) + for i := range cases { + cas := nodl(r.pos(), OCASE, nil, nil) + cas.List.Set(r.stmtList()) + if namedTypeSwitch { + // Note: per-case variables will have distinct, dotted + // names after import. That's okay: swt.go only needs + // Sym for diagnostics anyway. + caseVar := newnamel(cas.Pos, r.ident()) + declare(caseVar, dclcontext) + cas.Rlist.Set1(caseVar) + caseVar.Name.Defn = sw.Left + } + cas.Nbody.Set(r.stmtList()) + cases[i] = cas + } + return cases +} + func (r *importReader) exprList() []*Node { var list []*Node for { @@ -831,6 +853,14 @@ func (r *importReader) node() *Node { case OTYPE: return typenod(r.typ()) + case OTYPESW: + n := nodl(r.pos(), OTYPESW, nil, nil) + if s := r.ident(); s != nil { + n.Left = npos(n.Pos, newnoname(s)) + } + n.Right, _ = r.exprsOrNil() + return n + // case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC: // unreachable - should have been resolved by typechecking @@ -1025,16 +1055,11 @@ func (r *importReader) node() *Node { n := nodl(r.pos(), op, nil, nil) n.Ninit.Set(r.stmtList()) n.Left, _ = r.exprsOrNil() - n.List.Set(r.stmtList()) + n.List.Set(r.caseList(n)) return n - case OCASE: - n := nodl(r.pos(), OCASE, nil, nil) - n.List.Set(r.exprList()) - // TODO(gri) eventually we must declare variables for type switch - // statements (type switch statements are not yet exported) - n.Nbody.Set(r.stmtList()) - return n + // case OCASE: + // handled by caseList case OFALL: n := nodl(r.pos(), OFALL, nil, nil) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 253036fea64..139572f652e 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -392,13 +392,9 @@ func (v *hairyVisitor) visit(n *Node) bool { v.reason = "call to recover" return true - case OCALLPART: - // OCALLPART is inlineable, but no extra cost to the budget - case OCLOSURE, ORANGE, OSELECT, - OTYPESW, OGO, ODEFER, ODCLTYPE, // can't print yet diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 8ebeaf1330c..cbba5ff79cc 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -2065,11 +2065,6 @@ func typecheck1(n *Node, top int) (res *Node) { n.Type = nil return n - case OCASE: - ok |= ctxStmt - typecheckslice(n.List.Slice(), ctxExpr) - typecheckslice(n.Nbody.Slice(), ctxStmt) - case ODCLFUNC: ok |= ctxStmt typecheckfunc(n) diff --git a/test/fixedbugs/issue37837.dir/a.go b/test/fixedbugs/issue37837.dir/a.go new file mode 100644 index 00000000000..49d830ffbc7 --- /dev/null +++ b/test/fixedbugs/issue37837.dir/a.go @@ -0,0 +1,33 @@ +// Copyright 2020 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 a + +func F(i interface{}) int { // ERROR "can inline F" "i does not escape" + switch i.(type) { + case nil: + return 0 + case int: + return 1 + case float64: + return 2 + default: + return 3 + } +} + +func G(i interface{}) interface{} { // ERROR "can inline G" "leaking param: i" + switch i := i.(type) { + case nil: // ERROR "moved to heap: i" + return &i + case int: // ERROR "moved to heap: i" + return &i + case float64: // ERROR "moved to heap: i" + return &i + case string, []byte: // ERROR "moved to heap: i" + return &i + default: // ERROR "moved to heap: i" + return &i + } +} diff --git a/test/fixedbugs/issue37837.dir/b.go b/test/fixedbugs/issue37837.dir/b.go new file mode 100644 index 00000000000..461f5c7a553 --- /dev/null +++ b/test/fixedbugs/issue37837.dir/b.go @@ -0,0 +1,32 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "./a" + +func main() { + // Test that inlined type switches without short variable + // declarations work correctly. + check(0, a.F(nil)) // ERROR "inlining call to a.F" + check(1, a.F(0)) // ERROR "inlining call to a.F" "does not escape" + check(2, a.F(0.0)) // ERROR "inlining call to a.F" "does not escape" + check(3, a.F("")) // ERROR "inlining call to a.F" "does not escape" + + // Test that inlined type switches with short variable + // declarations work correctly. + _ = a.G(nil).(*interface{}) // ERROR "inlining call to a.G" + _ = a.G(1).(*int) // ERROR "inlining call to a.G" "does not escape" + _ = a.G(2.0).(*float64) // ERROR "inlining call to a.G" "does not escape" + _ = (*a.G("").(*interface{})).(string) // ERROR "inlining call to a.G" "does not escape" + _ = (*a.G(([]byte)(nil)).(*interface{})).([]byte) // ERROR "inlining call to a.G" "does not escape" + _ = (*a.G(true).(*interface{})).(bool) // ERROR "inlining call to a.G" "does not escape" +} + +//go:noinline +func check(want, got int) { + if want != got { + println("want", want, "but got", got) + } +} diff --git a/test/fixedbugs/issue37837.go b/test/fixedbugs/issue37837.go new file mode 100644 index 00000000000..2e8abc5f057 --- /dev/null +++ b/test/fixedbugs/issue37837.go @@ -0,0 +1,7 @@ +// errorcheckandrundir -0 -m + +// Copyright 2020 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 ignored diff --git a/test/inline.go b/test/inline.go index 470414f883a..d754f06e034 100644 --- a/test/inline.go +++ b/test/inline.go @@ -152,8 +152,7 @@ func switchBreak(x, y int) int { return n } -// can't currently inline functions with a type switch -func switchType(x interface{}) int { // ERROR "x does not escape" +func switchType(x interface{}) int { // ERROR "can inline switchType" "x does not escape" switch x.(type) { case int: return x.(int) From 3a81338622eb5c8b94f11001855e2a68a9e36bed Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Sat, 18 Feb 2017 03:03:32 -0700 Subject: [PATCH 375/403] runtime: make stack traces of endless recursion print only top and bottom 50 This CL makes it so that instead of printing massive stack traces during endless recursion, which spams users and aren't useful, it now prints out the top and bottom 50 frames. If the number of frames <= 100 (_TracebackMaxFrames), we'll just print all the frames out. Modified gentraceback to return counts of: * ntotalframes * nregularframes which allows us to get accurate counts of the various kinds of frames. While here, also fixed a bug that resulted from CL 37222, in which we no longer accounted for decrementing requested frame skips, and assumed that when printing, that skip would always be 0. The fix is instead to add precondition that we'll only print if skip <= 0, but also decrement skip as we iterate. Fixes #7181. Fixes #24628. Change-Id: Ie31ec6413fdfbe43827b254fef7d99ea26a5277f Reviewed-on: https://go-review.googlesource.com/c/go/+/37222 Run-TryBot: Emmanuel Odeke TryBot-Result: Go Bot Reviewed-by: Keith Randall Trust: Emmanuel Odeke --- src/runtime/crash_test.go | 126 ++++++++++++++++ src/runtime/testdata/testprog/deadlock.go | 13 ++ src/runtime/traceback.go | 173 ++++++++++++++++------ 3 files changed, 265 insertions(+), 47 deletions(-) diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 5e22b7593ec..66822e5cde6 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -240,6 +240,132 @@ func TestStackOverflow(t *testing.T) { } } +func TestStackOverflowTopAndBottomTraces(t *testing.T) { + output := runTestProg(t, "testprog", "StackOverflowTopAndBottomTraces") + + // 1. First things first, we expect to traverse from + // runtime: goroutine stack exceeds 10000-byte limit + // and down to the very end until we see: + // runtime.goexit() + mustHaves := []string{ + // Top half expectations + "\\s*runtime: goroutine stack exceeds 10000-byte limit\n", + "\\s*fatal error: stack overflow\n", + "\\s*runtime stack:\n", + "\\s*runtime.throw[^\n]+\n\t.+:\\d+ [^\n]+", + "\\s+runtime\\.newstack[^\n]+\n\t.+:\\d+ [^\n]+", + "\\s+runtime.morestack[^\n]+\n\t.+:\\d+ [^\n]+", + "\\s+goroutine 1 \\[running\\]:", + + // Bottom half expectations + "\\s*main.main\\(\\)\n", + "\\s*runtime.main\\(\\)\n", + "\\s*runtime.goexit\\(\\)\n", + } + + for _, pat := range mustHaves { + reg := regexp.MustCompile(pat) + match := reg.FindAllString(output, -1) + if len(match) == 0 { + t.Errorf("Failed to find pattern %q", pat) + } + } + + // 2. Split top and bottom halves by the "... ({n} stack frames omitted)" message + regHalving := regexp.MustCompile("\\.{3} \\(\\d+ stack frames omitted\\)") + halverMatches := regHalving.FindAllString(output, -1) + if len(halverMatches) != 1 { + t.Fatal("Failed to find the `stack frames omitted` pattern") + } + str := string(output) + halver := halverMatches[0] + midIndex := strings.Index(str, halver) + topHalf, bottomHalf := str[:midIndex], str[midIndex+len(halver):] + // 2.1. Sanity check, len(topHalf) >= halver || len(bottomHalf) >= halver + if len(topHalf) < len(halver) || len(bottomHalf) < len(halver) { + t.Fatalf("Sanity check len(topHalf) = %d len(bottomHalf) = %d; both must be >= len(halver) %d", + len(topHalf), len(bottomHalf), len(halver)) + } + + // 3. In each of the halves, we should have an equal number + // of stacktraces before and after the "omitted frames" message. + regStackTraces := regexp.MustCompile("\n[^\n]+\n\t.+:\\d+ .+ fp=0x.+ sp=0x.+ pc=0x.+") + topHalfStackTraces := regStackTraces.FindAllString(topHalf, -1) + bottomHalfStackTraces := regStackTraces.FindAllString(bottomHalf, -1) + nTopHalf, nBottomHalf := len(topHalfStackTraces), len(bottomHalfStackTraces) + if nTopHalf == 0 || nBottomHalf == 0 { + t.Fatal("Both lengths of stack-halves should be non-zero") + } + // The bottom half will always have the 50 non-runtime frames along with these 3 frames: + // * main.main() + // * "runtime.main" + // * "runtime.goexit" + // hence we need to decrement 3 counted lines. + if nTopHalf != nBottomHalf-3 { + t.Errorf("len(topHalfStackTraces)=%d len(bottomHalfStackTraces)-3=%d yet must be equal\n", nTopHalf, nBottomHalf-3) + } + + // 4. Next, prune out the: + // func... + // line... + // pairs in both of the halves. + prunes := []struct { + src *string + matches []string + }{ + {src: &topHalf, matches: topHalfStackTraces}, + {src: &bottomHalf, matches: bottomHalfStackTraces}, + } + + for _, prune := range prunes { + str := *prune.src + for _, match := range prune.matches { + index := strings.Index(str, match) + str = str[:index] + str[index+len(match):] + } + *prune.src = str + } + + // 5. Now match and prune out the remaining patterns in the top and bottom halves. + // We aren't touching the bottom stack since its patterns are already matched + // by the: + // func... + // line... + // pairs + topPartPrunables := []string{ + "^\\s*runtime: goroutine stack exceeds 10000-byte limit\n", + "\\s*fatal error: stack overflow\n", + "\\s*runtime stack:\n", + "\\s*runtime.throw[^\n]+\n\t.+:\\d+ [^\n]+", + "\\s+runtime\\.newstack[^\n]+\n\t.+:\\d+ [^\n]+", + "\\s+runtime.morestack[^\n]+\n\t.+:\\d+ [^\n]+", + "\\s+goroutine 1 \\[running\\]:", + } + + for _, pat := range topPartPrunables { + reg := regexp.MustCompile(pat) + matches := reg.FindAllString(topHalf, -1) + if len(matches) == 0 { + t.Errorf("top stack traces do not contain pattern: %q", reg) + } else if len(matches) != 1 { + t.Errorf("inconsistent state got %d matches want only 1", len(matches)) + } else { + match := matches[0] + idx := strings.Index(topHalf, match) + topHalf = topHalf[:idx] + topHalf[idx+len(match):] + } + } + + // 6. At the end we should only be left with + // newlines in both the top and bottom halves. + topHalf = strings.TrimSpace(topHalf) + bottomHalf = strings.TrimSpace(bottomHalf) + if topHalf != "" && bottomHalf != "" { + t.Fatalf("len(topHalf)=%d len(bottomHalf)=%d\ntopHalf=\n%s\n\nbottomHalf=\n%s", + len(topHalf), len(bottomHalf), topHalf, bottomHalf) + } +} + func TestThreadExhaustion(t *testing.T) { output := runTestProg(t, "testprog", "ThreadExhaustion") want := "runtime: program exceeds 10-thread limit\nfatal error: thread exhaustion" diff --git a/src/runtime/testdata/testprog/deadlock.go b/src/runtime/testdata/testprog/deadlock.go index 105d6a5faae..0ee1557b13d 100644 --- a/src/runtime/testdata/testprog/deadlock.go +++ b/src/runtime/testdata/testprog/deadlock.go @@ -20,6 +20,7 @@ func init() { register("LockedDeadlock2", LockedDeadlock2) register("GoexitDeadlock", GoexitDeadlock) register("StackOverflow", StackOverflow) + register("StackOverflowTopAndBottomTraces", StackOverflowTopAndBottomTraces) register("ThreadExhaustion", ThreadExhaustion) register("RecursivePanic", RecursivePanic) register("RecursivePanic2", RecursivePanic2) @@ -85,6 +86,18 @@ func StackOverflow() { f() } +func StackOverflowTopAndBottomTraces() { + var fi, gi func() + fi = func() { + gi() + } + gi = func() { + fi() + } + debug.SetMaxStack(10000) + fi() +} + func ThreadExhaustion() { debug.SetMaxThreads(10) c := make(chan int) diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index f3df152535a..389ae871853 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -73,17 +73,34 @@ func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v uns const sizeofSkipFunction = 256 -// Generic traceback. Handles runtime stack prints (pcbuf == nil), +// Generic traceback. Handles runtime stack prints (pcbuf == nil && callback == nil), // the runtime.Callers function (pcbuf != nil), as well as the garbage // collector (callback != nil). A little clunky to merge these, but avoids // duplicating the code and all its subtlety. // -// The skip argument is only valid with pcbuf != nil and counts the number -// of logical frames to skip rather than physical frames (with inlining, a -// PC in pcbuf can represent multiple calls). If a PC is partially skipped -// and max > 1, pcbuf[1] will be runtime.skipPleaseUseCallersFrames+N where -// N indicates the number of logical frames to skip in pcbuf[0]. +// The skip argument counts the number of logical frames to skip rather +// than physical frames (with inlining, a PC in pcbuf can represent multiple calls). func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max int, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer, flags uint) int { + var op operation = traversing + if pcbuf == nil && callback == nil { + op = printing + } + n, _ := ggentraceback(pc0, sp0, lr0, gp, skip, pcbuf, max, op, callback, v, flags) + return n +} + +type operation int8 + +const ( + traversing operation = 1 << iota + countingframes + printing +) + +// n always returns the number of total frames <= max. +// nregularframes is the count of non-runtime frames. +// nregularframes is only valid if op == countingframes. +func ggentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max int, op operation, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer, flags uint) (ntotalframes, nregularframes int) { if skip > 0 && callback != nil { throw("gentraceback callback cannot be used with non-zero skip") } @@ -135,7 +152,6 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } waspanic := false cgoCtxt := gp.cgoCtxt - printing := pcbuf == nil && callback == nil // If the PC is zero, it's likely a nil function call. // Start in the caller's frame. @@ -149,6 +165,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } } + printing := op == printing f := findfunc(frame.pc) if !f.valid() { if callback != nil || printing { @@ -158,15 +175,14 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in if callback != nil { throw("unknown pc") } - return 0 + return 0, 0 } frame.fn = f var cache pcvalueCache lastFuncID := funcID_normal - n := 0 - for n < max { + for ntotalframes < max { // Typically: // pc is the PC of the running function. // sp is the stack pointer at that program counter. @@ -229,7 +245,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } else { var lrPtr uintptr if usesLR { - if n == 0 && frame.sp < frame.fp || frame.lr == 0 { + if ntotalframes == 0 && frame.sp < frame.fp || frame.lr == 0 { lrPtr = frame.sp frame.lr = *(*uintptr)(unsafe.Pointer(lrPtr)) } @@ -320,11 +336,15 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in if callback != nil { if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) { - return n + return } } - if pcbuf != nil { + if pcbuf == nil && skip > 0 { + // In this case we are printing and we still need to count + // the number of frames. See https://golang.org/issues/24628. + skip-- + } else if pcbuf != nil { pc := frame.pc // backup to CALL instruction to read inlining info (same logic as below) tracepc := pc @@ -339,7 +359,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // See issue 34123. // The pc can be at function entry when the frame is initialized without // actually running code, like runtime.mstart. - if (n == 0 && flags&_TraceTrap != 0) || waspanic || pc == f.entry { + if (ntotalframes == 0 && flags&_TraceTrap != 0) || waspanic || pc == f.entry { pc++ } else { tracepc-- @@ -357,9 +377,9 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // ignore wrappers } else if skip > 0 { skip-- - } else if n < max { - (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = pc - n++ + } else if ntotalframes < max { + (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[ntotalframes] = pc + ntotalframes++ } lastFuncID = inltree[ix].funcID // Back up to an instruction in the "caller". @@ -372,17 +392,15 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // Ignore wrapper functions (except when they trigger panics). } else if skip > 0 { skip-- - } else if n < max { - (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = pc - n++ + } else if ntotalframes < max { + (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[ntotalframes] = pc + ntotalframes++ } lastFuncID = f.funcID - n-- // offset n++ below + ntotalframes-- // offset ntotalframes++ below } - if printing { - // assume skip=0 for printing. - // + if printing && skip <= 0 { // Never elide wrappers if we haven't printed // any frames. And don't elide wrappers that // called panic rather than the wrapped @@ -390,7 +408,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // backup to CALL instruction to read inlining info (same logic as below) tracepc := frame.pc - if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic { + if (ntotalframes > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic { tracepc-- } // If there is inlining info, print the inner frames. @@ -448,7 +466,14 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } lastFuncID = f.funcID } - n++ + + if op == countingframes { + name := fullfuncname(f, frame.pc) + if len(name) < len("runtime.") || name[:len("runtime.")] != "runtime." { + nregularframes++ + } + } + ntotalframes++ if f.funcID == funcID_cgocallback && len(cgoCtxt) > 0 { ctxt := cgoCtxt[len(cgoCtxt)-1] @@ -458,7 +483,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // callback != nil only used when we only care // about Go frames. if skip == 0 && callback == nil { - n = tracebackCgoContext(pcbuf, printing, ctxt, n, max) + ntotalframes = tracebackCgoContext(pcbuf, printing, ctxt, ntotalframes, max) } } @@ -498,7 +523,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in } if printing { - n = nprint + ntotalframes = nprint } // Note that panic != nil is okay here: there can be leftover panics, @@ -541,13 +566,13 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in // At other times, such as when gathering a stack for a profiling signal // or when printing a traceback during a crash, everything may not be // stopped nicely, and the stack walk may not be able to complete. - if callback != nil && n < max && frame.sp != gp.stktopsp { + if callback != nil && ntotalframes < max && frame.sp != gp.stktopsp { print("runtime: g", gp.goid, ": frame.sp=", hex(frame.sp), " top=", hex(gp.stktopsp), "\n") - print("\tstack=[", hex(gp.stack.lo), "-", hex(gp.stack.hi), "] n=", n, " max=", max, "\n") + print("\tstack=[", hex(gp.stack.lo), "-", hex(gp.stack.hi), "] n=", ntotalframes, " max=", max, "\n") throw("traceback did not unwind completely") } - return n + return } // reflectMethodValue is a partial duplicate of reflect.makeFuncImpl @@ -712,24 +737,15 @@ func traceback1(pc, sp, lr uintptr, gp *g, flags uint) { printCgoTraceback(&cgoCallers) } - var n int if readgstatus(gp)&^_Gscan == _Gsyscall { // Override registers if blocked in system call. pc = gp.syscallpc sp = gp.syscallsp flags &^= _TraceTrap } - // Print traceback. By default, omits runtime frames. - // If that means we print nothing at all, repeat forcing all frames printed. - n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags) - if n == 0 && (flags&_TraceRuntimeFrames) == 0 { - n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags|_TraceRuntimeFrames) - } - if n == _TracebackMaxFrames { - print("...additional frames elided...\n") - } - printcreatedby(gp) + printtraceback(pc, sp, lr, gp, flags) + printcreatedby(gp) if gp.ancestors == nil { return } @@ -738,6 +754,62 @@ func traceback1(pc, sp, lr uintptr, gp *g, flags uint) { } } +// countframes traverses the current stacktrace from the top of pc0 to its bottom, excluding runtime frames. +// If flags&_TraceRuntimeframes != 0, it'll include the number of runtime frames in the count. +func countframes(pc0, sp0, lr0 uintptr, gp *g, flags uint) (nframes int) { + ntotalframes, nregularframes := ggentraceback(pc0, sp0, lr0, gp, 0, nil, 1<<31-1, countingframes, nil, nil, flags) + nframes = nregularframes + if flags&_TraceRuntimeFrames != 0 { + nframes = ntotalframes + } + return nframes +} + +func printtraceback(pc, sp, lr uintptr, gp *g, flags uint) { + // We'd like to print: + // * top nMaxFramesPerPrint frames + // * bottom nMaxFramesPerPrint frames. + // See https://golang.org/issue/7181. + + nMaxFramesPerPrint := _TracebackMaxFrames / 2 + nTop := gentraceback(pc, sp, lr, gp, 0, nil, nMaxFramesPerPrint, nil, nil, flags) + if nTop < nMaxFramesPerPrint { + // The common case, in which the traceback has less than nMaxFramesPerPrint. + // By default, omits runtime frames. + // If nTop == 0, it means we printed nothing at all, so repeat, + // and this time force all frames to be printed. + if nTop == 0 && (flags&_TraceRuntimeFrames) == 0 { + // Try again to print the frames, but this time with _TraceRuntimeFrames. + printtraceback(pc, sp, lr, gp, flags|_TraceRuntimeFrames) + } + return + } + + // Figure out the stack size in order to print the bottom max(nMaxFramesPerPrint) frames. + // + // TODO(odeke-em, iant, khr): perhaps investigate and revise the solution in + // https://go-review.googlesource.com/c/go/+/37222/9/src/runtime/traceback.go + // so that we'll always only need 1 stack walk, instead of 2 as in this worst case. + nframes := countframes(pc, sp, lr, gp, flags) + + if nframes <= _TracebackMaxFrames { + // In this case, we'll just print out from where we left off until the end. + gentraceback(pc, sp, lr, gp, nMaxFramesPerPrint /* skip */, nil, 1<<31-1, nil, nil, flags) + return + } + + // Otherwise, now skip until the bottom last nMaxFramesPerPrint. + + // Calculate the number of stack frames to elide since we + // are printing top and bottom each of nMaxFramesPerPrint. + if elide := nframes - _TracebackMaxFrames; elide > 0 { + print("\n... (") + println(elide, "stack frames omitted)\n") + } + skip := nframes - nMaxFramesPerPrint + _ = gentraceback(pc, sp, lr, gp, skip, nil, 1<<31-1 /* max int32 as the biggest frame number */, nil, nil, flags) +} + // printAncestorTraceback prints the traceback of the given ancestor. // TODO: Unify this with gentraceback and CallersFrames. func printAncestorTraceback(ancestor ancestorInfo) { @@ -758,11 +830,9 @@ func printAncestorTraceback(ancestor ancestorInfo) { } } -// printAncestorTraceback prints the given function info at a given pc -// within an ancestor traceback. The precision of this info is reduced -// due to only have access to the pcs at the time of the caller -// goroutine being created. -func printAncestorTracebackFuncInfo(f funcInfo, pc uintptr) { +// fullfuncname retrieves the name for a funcInfo, but if perhaps it was inlined, it'll retrieve +// unwind and retrieve the original name. +func fullfuncname(f funcInfo, pc uintptr) string { name := funcname(f) if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil { inltree := (*[1 << 20]inlinedCall)(inldata) @@ -771,6 +841,15 @@ func printAncestorTracebackFuncInfo(f funcInfo, pc uintptr) { name = funcnameFromNameoff(f, inltree[ix].func_) } } + return name +} + +// printAncestorTraceback prints the given function info at a given pc +// within an ancestor traceback. The precision of this info is reduced +// due to only have access to the pcs at the time of the caller +// goroutine being created. +func printAncestorTracebackFuncInfo(f funcInfo, pc uintptr) { + name := fullfuncname(f, pc) file, line := funcline(f, pc) if name == "runtime.gopanic" { name = "panic" From f7ef5ca54a103ed67425e1efe6d39d3bc8067bad Mon Sep 17 00:00:00 2001 From: Pantelis Sampaziotis Date: Wed, 14 Oct 2020 19:42:13 +0000 Subject: [PATCH 376/403] crypto/x509: add Unwrap to SystemRootsError This change modifies Go to add the Unwrap method to SystemRootsError Updates #30322 Change-Id: Ibe63d1d0bc832fc0607f09053908d55275a6f350 GitHub-Last-Rev: 9a95bc66019d25f02a0a5f92a87e9405a52802e4 GitHub-Pull-Request: golang/go#41981 Reviewed-on: https://go-review.googlesource.com/c/go/+/262343 Reviewed-by: Damien Neil Reviewed-by: Filippo Valsorda Trust: Damien Neil Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot --- src/crypto/x509/verify.go | 2 ++ src/crypto/x509/verify_test.go | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index cb8d8f872dd..5fdd4cb9fe1 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -187,6 +187,8 @@ func (se SystemRootsError) Error() string { return msg } +func (se SystemRootsError) Unwrap() error { return se.Err } + // errNotParsed is returned when a certificate without ASN.1 contents is // verified. Platform-specific verification needs the ASN.1 contents. var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate") diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index c7a715bbcbb..9cc17c7b3d8 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -2005,3 +2005,11 @@ func TestSystemRootsError(t *testing.T) { t.Errorf("error was not SystemRootsError: %v", err) } } + +func TestSystemRootsErrorUnwrap(t *testing.T) { + var err1 = errors.New("err1") + err := SystemRootsError{Err: err1} + if !errors.Is(err, err1) { + t.Error("errors.Is failed, wanted success") + } +} From c9b9cd73bb7a7828d34f4a7844f16c3fbc0674dd Mon Sep 17 00:00:00 2001 From: Katie Hockman Date: Wed, 28 Oct 2020 15:13:33 -0400 Subject: [PATCH 377/403] crypto/tls: set Deadline before sending close notify alert This change also documents the need to set a Deadline before calling Read or Write. Fixes #31224 Change-Id: I89d6fe3ecb0a0076b4c61765f61c88056f951406 Reviewed-on: https://go-review.googlesource.com/c/go/+/266037 Trust: Katie Hockman Run-TryBot: Katie Hockman TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda --- doc/go1.16.html | 10 ++++++++-- src/crypto/tls/conn.go | 22 ++++++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 99e8e3c980d..a97c3698855 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -237,12 +237,18 @@ Do not send CLs removing the interior tags from such phrases.

I/O operations on closing or closed TLS connections can now be detected using - the new ErrClosed error. A typical use - would be errors.Is(err, net.ErrClosed). In earlier releases + the new ErrClosed error. A typical use + would be errors.Is(err, net.ErrClosed). In earlier releases the only way to reliably detect this case was to match the string returned by the Error method with "tls: use of closed connection".

+

+ A default deadline is set in Close + before sending the close notify alert, in order to prevent blocking + indefinitely. +

+

crypto/x509

diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index f1d4cb926c0..ada19d6e7ae 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -1074,6 +1074,11 @@ var ( ) // Write writes data to the connection. +// +// As Write calls Handshake, in order to prevent indefinite blocking a deadline +// must be set for both Read and Write before Write is called when the handshake +// has not yet completed. See SetDeadline, SetReadDeadline, and +// SetWriteDeadline. func (c *Conn) Write(b []byte) (int, error) { // interlock with Close below for { @@ -1232,8 +1237,12 @@ func (c *Conn) handleKeyUpdate(keyUpdate *keyUpdateMsg) error { return nil } -// Read can be made to time out and return a net.Error with Timeout() == true -// after a fixed time limit; see SetDeadline and SetReadDeadline. +// Read reads data from the connection. +// +// As Read calls Handshake, in order to prevent indefinite blocking a deadline +// must be set for both Read and Write before Read is called when the handshake +// has not yet completed. See SetDeadline, SetReadDeadline, and +// SetWriteDeadline. func (c *Conn) Read(b []byte) (int, error) { if err := c.Handshake(); err != nil { return 0, err @@ -1301,9 +1310,10 @@ func (c *Conn) Close() error { } var alertErr error - if c.handshakeComplete() { - alertErr = c.closeNotify() + if err := c.closeNotify(); err != nil { + alertErr = fmt.Errorf("tls: failed to send closeNotify alert (but connection was closed anyway): %w", err) + } } if err := c.conn.Close(); err != nil { @@ -1330,8 +1340,12 @@ func (c *Conn) closeNotify() error { defer c.out.Unlock() if !c.closeNotifySent { + // Set a Write Deadline to prevent possibly blocking forever. + c.SetWriteDeadline(time.Now().Add(time.Second * 5)) c.closeNotifyErr = c.sendAlertLocked(alertCloseNotify) c.closeNotifySent = true + // Any subsequent writes will fail. + c.SetWriteDeadline(time.Now()) } return c.closeNotifyErr } From 33bc8ce8de855c78ec537e53e7814fa85bd90944 Mon Sep 17 00:00:00 2001 From: Meng Zhuo Date: Mon, 26 Oct 2020 15:57:33 +0800 Subject: [PATCH 378/403] crypto/cipher: use Neon for xor on arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpu: HiSilicon(R) Kirin 970 2.4GHz name old time/op new time/op delta XORBytes/8Bytes 39.8ns ± 0% 17.3ns ± 0% -56.53% (p=0.000 n=10+10) XORBytes/128Bytes 376ns ± 0% 28ns ± 0% -92.63% (p=0.000 n=10+8) XORBytes/2048Bytes 5.67µs ± 0% 0.22µs ± 0% -96.03% (p=0.000 n=10+10) XORBytes/32768Bytes 90.3µs ± 0% 3.5µs ± 0% -96.12% (p=0.000 n=10+10) AESGCMSeal1K 853ns ± 0% 853ns ± 0% ~ (all equal) AESGCMOpen1K 876ns ± 0% 874ns ± 0% -0.23% (p=0.000 n=10+10) AESGCMSign8K 3.09µs ± 0% 3.08µs ± 0% -0.34% (p=0.000 n=10+9) AESGCMSeal8K 5.87µs ± 0% 5.87µs ± 0% +0.01% (p=0.008 n=10+8) AESGCMOpen8K 5.82µs ± 0% 5.82µs ± 0% +0.02% (p=0.037 n=10+10) AESCFBEncrypt1K 7.05µs ± 0% 4.27µs ± 0% -39.38% (p=0.000 n=10+10) AESCFBDecrypt1K 7.12µs ± 0% 4.30µs ± 0% -39.54% (p=0.000 n=10+9) AESCFBDecrypt8K 56.7µs ± 0% 34.1µs ± 0% -39.82% (p=0.000 n=10+10) AESOFB1K 5.20µs ± 0% 2.54µs ± 0% -51.07% (p=0.000 n=10+10) AESCTR1K 4.96µs ± 0% 2.30µs ± 0% -53.62% (p=0.000 n=9+10) AESCTR8K 39.5µs ± 0% 18.2µs ± 0% -53.98% (p=0.000 n=8+10) AESCBCEncrypt1K 5.81µs ± 0% 3.07µs ± 0% -47.13% (p=0.000 n=10+8) AESCBCDecrypt1K 5.83µs ± 0% 3.10µs ± 0% -46.84% (p=0.000 n=10+8) name old speed new speed delta XORBytes/8Bytes 201MB/s ± 0% 461MB/s ± 0% +129.80% (p=0.000 n=6+10) XORBytes/128Bytes 340MB/s ± 0% 4625MB/s ± 0% +1259.91% (p=0.000 n=8+10) XORBytes/2048Bytes 361MB/s ± 0% 9088MB/s ± 0% +2414.23% (p=0.000 n=8+10) XORBytes/32768Bytes 363MB/s ± 0% 9350MB/s ± 0% +2477.44% (p=0.000 n=10+10) AESGCMSeal1K 1.20GB/s ± 0% 1.20GB/s ± 0% -0.02% (p=0.041 n=10+10) AESGCMOpen1K 1.17GB/s ± 0% 1.17GB/s ± 0% +0.20% (p=0.000 n=10+10) AESGCMSign8K 2.65GB/s ± 0% 2.66GB/s ± 0% +0.35% (p=0.000 n=10+9) AESGCMSeal8K 1.40GB/s ± 0% 1.40GB/s ± 0% -0.01% (p=0.000 n=10+7) AESGCMOpen8K 1.41GB/s ± 0% 1.41GB/s ± 0% -0.03% (p=0.022 n=10+10) AESCFBEncrypt1K 145MB/s ± 0% 238MB/s ± 0% +64.95% (p=0.000 n=10+10) AESCFBDecrypt1K 143MB/s ± 0% 237MB/s ± 0% +65.39% (p=0.000 n=10+9) AESCFBDecrypt8K 144MB/s ± 0% 240MB/s ± 0% +66.15% (p=0.000 n=10+10) AESOFB1K 196MB/s ± 0% 401MB/s ± 0% +104.35% (p=0.000 n=9+10) AESCTR1K 205MB/s ± 0% 443MB/s ± 0% +115.57% (p=0.000 n=7+10) AESCTR8K 207MB/s ± 0% 450MB/s ± 0% +117.27% (p=0.000 n=10+10) AESCBCEncrypt1K 176MB/s ± 0% 334MB/s ± 0% +89.15% (p=0.000 n=10+8) AESCBCDecrypt1K 176MB/s ± 0% 330MB/s ± 0% +88.08% (p=0.000 n=10+9) Updates #42010 Change-Id: I75e6d66fd0070e184d93b020c55a7580c713647c Reviewed-on: https://go-review.googlesource.com/c/go/+/142537 Reviewed-by: Meng Zhuo Reviewed-by: Filippo Valsorda Run-TryBot: Meng Zhuo TryBot-Result: Go Bot Trust: Meng Zhuo --- src/crypto/cipher/xor_arm64.go | 29 ++++++++++++++ src/crypto/cipher/xor_arm64.s | 67 ++++++++++++++++++++++++++++++++ src/crypto/cipher/xor_generic.go | 2 +- 3 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/crypto/cipher/xor_arm64.go create mode 100644 src/crypto/cipher/xor_arm64.s diff --git a/src/crypto/cipher/xor_arm64.go b/src/crypto/cipher/xor_arm64.go new file mode 100644 index 00000000000..35a785a8a14 --- /dev/null +++ b/src/crypto/cipher/xor_arm64.go @@ -0,0 +1,29 @@ +// Copyright 2020 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 cipher + +// xorBytes xors the bytes in a and b. The destination should have enough +// space, otherwise xorBytes will panic. Returns the number of bytes xor'd. +func xorBytes(dst, a, b []byte) int { + n := len(a) + if len(b) < n { + n = len(b) + } + if n == 0 { + return 0 + } + // make sure dst has enough space + _ = dst[n-1] + + xorBytesARM64(&dst[0], &a[0], &b[0], n) + return n +} + +func xorWords(dst, a, b []byte) { + xorBytes(dst, a, b) +} + +//go:noescape +func xorBytesARM64(dst, a, b *byte, n int) diff --git a/src/crypto/cipher/xor_arm64.s b/src/crypto/cipher/xor_arm64.s new file mode 100644 index 00000000000..669852d7eb7 --- /dev/null +++ b/src/crypto/cipher/xor_arm64.s @@ -0,0 +1,67 @@ +// Copyright 2020 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. + +#include "textflag.h" + +// func xorBytesARM64(dst, a, b *byte, n int) +TEXT ·xorBytesARM64(SB), NOSPLIT|NOFRAME, $0 + MOVD dst+0(FP), R0 + MOVD a+8(FP), R1 + MOVD b+16(FP), R2 + MOVD n+24(FP), R3 + CMP $64, R3 + BLT tail +loop_64: + VLD1.P 64(R1), [V0.B16, V1.B16, V2.B16, V3.B16] + VLD1.P 64(R2), [V4.B16, V5.B16, V6.B16, V7.B16] + VEOR V0.B16, V4.B16, V4.B16 + VEOR V1.B16, V5.B16, V5.B16 + VEOR V2.B16, V6.B16, V6.B16 + VEOR V3.B16, V7.B16, V7.B16 + VST1.P [V4.B16, V5.B16, V6.B16, V7.B16], 64(R0) + SUBS $64, R3 + CMP $64, R3 + BGE loop_64 +tail: + // quick end + CBZ R3, end + TBZ $5, R3, less_than32 + VLD1.P 32(R1), [V0.B16, V1.B16] + VLD1.P 32(R2), [V2.B16, V3.B16] + VEOR V0.B16, V2.B16, V2.B16 + VEOR V1.B16, V3.B16, V3.B16 + VST1.P [V2.B16, V3.B16], 32(R0) +less_than32: + TBZ $4, R3, less_than16 + LDP.P 16(R1), (R11, R12) + LDP.P 16(R2), (R13, R14) + EOR R11, R13, R13 + EOR R12, R14, R14 + STP.P (R13, R14), 16(R0) +less_than16: + TBZ $3, R3, less_than8 + MOVD.P 8(R1), R11 + MOVD.P 8(R2), R12 + EOR R11, R12, R12 + MOVD.P R12, 8(R0) +less_than8: + TBZ $2, R3, less_than4 + MOVWU.P 4(R1), R13 + MOVWU.P 4(R2), R14 + EORW R13, R14, R14 + MOVWU.P R14, 4(R0) +less_than4: + TBZ $1, R3, less_than2 + MOVHU.P 2(R1), R15 + MOVHU.P 2(R2), R16 + EORW R15, R16, R16 + MOVHU.P R16, 2(R0) +less_than2: + TBZ $0, R3, end + MOVBU (R1), R17 + MOVBU (R2), R19 + EORW R17, R19, R19 + MOVBU R19, (R0) +end: + RET diff --git a/src/crypto/cipher/xor_generic.go b/src/crypto/cipher/xor_generic.go index b7de60873c5..ca9c4bbf391 100644 --- a/src/crypto/cipher/xor_generic.go +++ b/src/crypto/cipher/xor_generic.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. -// +build !amd64,!ppc64,!ppc64le +// +build !amd64,!ppc64,!ppc64le,!arm64 package cipher From d51ae669363fdd4a741db7f0193e7e6ebc639ff3 Mon Sep 17 00:00:00 2001 From: Artyom Pervukhin Date: Wed, 4 Nov 2020 15:28:25 +0300 Subject: [PATCH 379/403] archive/zip: fix documentation to mention fs.FS interface Fixes #42374 Change-Id: I0ed1eb052d79bcc65810b74bff48f1e615e1dc1e Reviewed-on: https://go-review.googlesource.com/c/go/+/267657 Reviewed-by: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov --- src/archive/zip/reader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/archive/zip/reader.go b/src/archive/zip/reader.go index 5c9f3dea281..8b4e77875fb 100644 --- a/src/archive/zip/reader.go +++ b/src/archive/zip/reader.go @@ -695,7 +695,7 @@ func fileEntryLess(x, y string) bool { } // Open opens the named file in the ZIP archive, -// using the semantics of io.FS.Open: +// using the semantics of fs.FS.Open: // paths are always slash separated, with no // leading / or ../ elements. func (r *Reader) Open(name string) (fs.File, error) { From a6755fc0debc3005e8bd730521ecc8dba61a24e8 Mon Sep 17 00:00:00 2001 From: Cholerae Hu Date: Fri, 31 Jul 2020 13:57:48 +0800 Subject: [PATCH 380/403] cmd/compile: check indirect connection between if block and phi block in addLocalInductiveFacts CL 244579 added guard clauses to prevent a faulty state that was possible under the incorrect logic of the uniquePred loop in addLocalInductiveFacts. That faulty state was still making the intended optimization, but not for the correct reason. Removing the faulty state also removed the overly permissive application of the optimization, and therefore made these two tests fail. We disabled the tests of this optimization in CL 244579 to allow us to quickly apply the fix in the CL. This CL now corrects the logic of the uniquePred loop in order to apply the optimization correctly. The comment above the uniquePred loop says that it will follow unique predecessors until it reaches a join point. Without updating the child node on each iteration, it cannot follow the chain of unique predecessors more than one step. Adding the update to the child node on each iteration of the loop allows the logic to follow the chain of unique predecessors until reaching a join point (because a non-unique predecessor will signify a join point). Updates #40502. Change-Id: I23d8367046a2ab3ce4be969631f9ba15dc533e6c Reviewed-on: https://go-review.googlesource.com/c/go/+/246157 Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: David Chase Trust: Dmitri Shuralyov --- src/cmd/compile/internal/ssa/prove.go | 2 +- test/prove.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/ssa/prove.go b/src/cmd/compile/internal/ssa/prove.go index ce7d689f935..8a2e7c09bc5 100644 --- a/src/cmd/compile/internal/ssa/prove.go +++ b/src/cmd/compile/internal/ssa/prove.go @@ -1082,7 +1082,7 @@ func addLocalInductiveFacts(ft *factsTable, b *Block) { return nil } pred, child := b.Preds[1].b, b - for ; pred != nil; pred = uniquePred(pred) { + for ; pred != nil; pred, child = uniquePred(pred), pred { if pred.Kind != BlockIf { continue } diff --git a/test/prove.go b/test/prove.go index 3c19c513b65..d37021d2830 100644 --- a/test/prove.go +++ b/test/prove.go @@ -670,8 +670,7 @@ func oforuntil(b []int) { i := 0 if len(b) > i { top: - // TODO: remove the todo of next line once we complete the following optimization of CL 244579 - // println(b[i]) // todo: ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$" + println(b[i]) // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$" i++ if i < len(b) { goto top @@ -721,8 +720,7 @@ func range1(b []int) { // range2 elements are larger, so they use the general form of a range loop. func range2(b [][32]int) { for i, v := range b { - // TODO: remove the todo of next line once we complete the following optimization of CL 244579 - b[i][0] = v[0] + 1 // todo: ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$" + b[i][0] = v[0] + 1 // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$" if i < len(b) { // ERROR "Proved Less64$" println("x") } From bb9a96d03a35ab56f3e1a3e6a6c835f7f2120d54 Mon Sep 17 00:00:00 2001 From: "Joshua M. Clulow" Date: Fri, 6 Nov 2020 13:11:58 -0800 Subject: [PATCH 381/403] os/exec: use "pfiles" for fd debugging on illumos On illumos (and Solaris) systems, the native "pfiles" tool provides the best information about open file descriptors for a process: https://illumos.org/man/1/pfiles Use that instead of "lsof" when debugging file descriptor leaks. Updates #42431. Change-Id: If1250c4e6c9e8adbd076495a09fb1ce63abcc68b Reviewed-on: https://go-review.googlesource.com/c/go/+/268019 Run-TryBot: Ian Lance Taylor TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov Trust: Dmitri Shuralyov --- src/os/exec/read3.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/os/exec/read3.go b/src/os/exec/read3.go index 8852023e77d..8cc24da8cb4 100644 --- a/src/os/exec/read3.go +++ b/src/os/exec/read3.go @@ -56,7 +56,7 @@ func main() { switch runtime.GOOS { case "plan9": args = []string{fmt.Sprintf("/proc/%d/fd", os.Getpid())} - case "aix": + case "aix", "solaris", "illumos": args = []string{fmt.Sprint(os.Getpid())} default: args = []string{"-p", fmt.Sprint(os.Getpid())} @@ -71,6 +71,8 @@ func main() { ofcmd = "/bin/cat" case "aix": ofcmd = "procfiles" + case "solaris", "illumos": + ofcmd = "pfiles" } cmd := exec.Command(ofcmd, args...) From 2c80de74d57de74cc50ba7195392cada4e9c3ea2 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 7 Nov 2020 12:03:36 +0700 Subject: [PATCH 382/403] cmd/link: fix invalid usage of reflect.SliceHeader Caught by "go vet" built with golang.org/cl/248192. Change-Id: I446083533dd82ecef8db591beb7bd3d70b040d4a Reviewed-on: https://go-review.googlesource.com/c/go/+/268099 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Zhang --- src/cmd/link/internal/ld/outbuf_windows.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/outbuf_windows.go b/src/cmd/link/internal/ld/outbuf_windows.go index 60dc1ab92dd..915c72bef3e 100644 --- a/src/cmd/link/internal/ld/outbuf_windows.go +++ b/src/cmd/link/internal/ld/outbuf_windows.go @@ -35,7 +35,10 @@ func (out *OutBuf) Mmap(filesize uint64) error { if err != nil { return err } - *(*reflect.SliceHeader)(unsafe.Pointer(&out.buf)) = reflect.SliceHeader{Data: ptr, Len: int(filesize), Cap: int(filesize)} + bufHdr := (*reflect.SliceHeader)(unsafe.Pointer(&out.buf)) + bufHdr.Data = ptr + bufHdr.Len = int(filesize) + bufHdr.Cap = int(filesize) // copy heap to new mapping if uint64(oldlen+len(out.heap)) > filesize { From e8379ab5964a920e59dbcc5bc4eaa1bbf5a88e90 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 24 Apr 2020 08:04:16 -0700 Subject: [PATCH 383/403] crypto/x509: add support for CertPool to load certs lazily This will allow building CertPools that consume less memory. (Most certs are never accessed. Different users/programs access different ones, but not many.) This CL only adds the new internal mechanism (and uses it for the old AddCert) but does not modify any existing root pool behavior. (That is, the default Unix roots are still all slurped into memory as of this CL) Change-Id: Ib3a42e4050627b5e34413c595d8ced839c7bfa14 Reviewed-on: https://go-review.googlesource.com/c/go/+/229917 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Trust: Brad Fitzpatrick Trust: Roland Shoemaker Reviewed-by: Filippo Valsorda Reviewed-by: Roland Shoemaker --- src/crypto/x509/cert_pool.go | 124 ++++++++++++++++++----- src/crypto/x509/name_constraints_test.go | 12 +-- src/crypto/x509/root_cgo_darwin.go | 6 +- src/crypto/x509/root_darwin_test.go | 11 +- src/crypto/x509/root_unix.go | 2 +- src/crypto/x509/root_unix_test.go | 15 +-- src/crypto/x509/root_windows.go | 6 +- src/crypto/x509/verify.go | 20 ++-- src/crypto/x509/x509_test.go | 52 +++++++++- 9 files changed, 192 insertions(+), 56 deletions(-) diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go index 167390da9f6..2cfaeb2d9ef 100644 --- a/src/crypto/x509/cert_pool.go +++ b/src/crypto/x509/cert_pool.go @@ -6,35 +6,87 @@ package x509 import ( "bytes" + "crypto/sha256" "encoding/pem" "errors" "runtime" ) +type sum224 [sha256.Size224]byte + // CertPool is a set of certificates. type CertPool struct { - byName map[string][]int - certs []*Certificate + byName map[string][]int // cert.RawSubject => index into lazyCerts + + // lazyCerts contains funcs that return a certificate, + // lazily parsing/decompressing it as needed. + lazyCerts []lazyCert + + // haveSum maps from sum224(cert.Raw) to true. It's used only + // for AddCert duplicate detection, to avoid CertPool.contains + // calls in the AddCert path (because the contains method can + // call getCert and otherwise negate savings from lazy getCert + // funcs). + haveSum map[sum224]bool +} + +// lazyCert is minimal metadata about a Cert and a func to retrieve it +// in its normal expanded *Certificate form. +type lazyCert struct { + // rawSubject is the Certificate.RawSubject value. + // It's the same as the CertPool.byName key, but in []byte + // form to make CertPool.Subjects (as used by crypto/tls) do + // fewer allocations. + rawSubject []byte + + // getCert returns the certificate. + // + // It is not meant to do network operations or anything else + // where a failure is likely; the func is meant to lazily + // parse/decompress data that is already known to be good. The + // error in the signature primarily is meant for use in the + // case where a cert file existed on local disk when the program + // started up is deleted later before it's read. + getCert func() (*Certificate, error) } // NewCertPool returns a new, empty CertPool. func NewCertPool() *CertPool { return &CertPool{ - byName: make(map[string][]int), + byName: make(map[string][]int), + haveSum: make(map[sum224]bool), } } +// len returns the number of certs in the set. +// A nil set is a valid empty set. +func (s *CertPool) len() int { + if s == nil { + return 0 + } + return len(s.lazyCerts) +} + +// cert returns cert index n in s. +func (s *CertPool) cert(n int) (*Certificate, error) { + return s.lazyCerts[n].getCert() +} + func (s *CertPool) copy() *CertPool { p := &CertPool{ - byName: make(map[string][]int, len(s.byName)), - certs: make([]*Certificate, len(s.certs)), + byName: make(map[string][]int, len(s.byName)), + lazyCerts: make([]lazyCert, len(s.lazyCerts)), + haveSum: make(map[sum224]bool, len(s.haveSum)), } for k, v := range s.byName { indexes := make([]int, len(v)) copy(indexes, v) p.byName[k] = indexes } - copy(p.certs, s.certs) + for k := range s.haveSum { + p.haveSum[k] = true + } + copy(p.lazyCerts, s.lazyCerts) return p } @@ -64,7 +116,7 @@ func SystemCertPool() (*CertPool, error) { // findPotentialParents returns the indexes of certificates in s which might // have signed cert. -func (s *CertPool) findPotentialParents(cert *Certificate) []int { +func (s *CertPool) findPotentialParents(cert *Certificate) []*Certificate { if s == nil { return nil } @@ -75,18 +127,21 @@ func (s *CertPool) findPotentialParents(cert *Certificate) []int { // AKID and SKID match // AKID present, SKID missing / AKID missing, SKID present // AKID and SKID don't match - var matchingKeyID, oneKeyID, mismatchKeyID []int + var matchingKeyID, oneKeyID, mismatchKeyID []*Certificate for _, c := range s.byName[string(cert.RawIssuer)] { - candidate := s.certs[c] + candidate, err := s.cert(c) + if err != nil { + continue + } kidMatch := bytes.Equal(candidate.SubjectKeyId, cert.AuthorityKeyId) switch { case kidMatch: - matchingKeyID = append(matchingKeyID, c) + matchingKeyID = append(matchingKeyID, candidate) case (len(candidate.SubjectKeyId) == 0 && len(cert.AuthorityKeyId) > 0) || (len(candidate.SubjectKeyId) > 0 && len(cert.AuthorityKeyId) == 0): - oneKeyID = append(oneKeyID, c) + oneKeyID = append(oneKeyID, candidate) default: - mismatchKeyID = append(mismatchKeyID, c) + mismatchKeyID = append(mismatchKeyID, candidate) } } @@ -94,11 +149,10 @@ func (s *CertPool) findPotentialParents(cert *Certificate) []int { if found == 0 { return nil } - candidates := make([]int, 0, found) + candidates := make([]*Certificate, 0, found) candidates = append(candidates, matchingKeyID...) candidates = append(candidates, oneKeyID...) candidates = append(candidates, mismatchKeyID...) - return candidates } @@ -106,10 +160,13 @@ func (s *CertPool) contains(cert *Certificate) bool { if s == nil { return false } - candidates := s.byName[string(cert.RawSubject)] - for _, c := range candidates { - if s.certs[c].Equal(cert) { + for _, i := range candidates { + c, err := s.cert(i) + if err != nil { + return false + } + if c.Equal(cert) { return true } } @@ -122,17 +179,32 @@ func (s *CertPool) AddCert(cert *Certificate) { if cert == nil { panic("adding nil Certificate to CertPool") } + s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) { + return cert, nil + }) +} + +// addCertFunc adds metadata about a certificate to a pool, along with +// a func to fetch that certificate later when needed. +// +// The rawSubject is Certificate.RawSubject and must be non-empty. +// The getCert func may be called 0 or more times. +func (s *CertPool) addCertFunc(rawSum224 sum224, rawSubject string, getCert func() (*Certificate, error)) { + if getCert == nil { + panic("getCert can't be nil") + } // Check that the certificate isn't being added twice. - if s.contains(cert) { + if s.haveSum[rawSum224] { return } - n := len(s.certs) - s.certs = append(s.certs, cert) - - name := string(cert.RawSubject) - s.byName[name] = append(s.byName[name], n) + s.haveSum[rawSum224] = true + s.lazyCerts = append(s.lazyCerts, lazyCert{ + rawSubject: []byte(rawSubject), + getCert: getCert, + }) + s.byName[rawSubject] = append(s.byName[rawSubject], len(s.lazyCerts)-1) } // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. @@ -167,9 +239,9 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { // Subjects returns a list of the DER-encoded subjects of // all of the certificates in the pool. func (s *CertPool) Subjects() [][]byte { - res := make([][]byte, len(s.certs)) - for i, c := range s.certs { - res[i] = c.RawSubject + res := make([][]byte, s.len()) + for i, lc := range s.lazyCerts { + res[i] = lc.rawSubject } return res } diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go index 5469e28de24..34055d07b53 100644 --- a/src/crypto/x509/name_constraints_test.go +++ b/src/crypto/x509/name_constraints_test.go @@ -1941,7 +1941,7 @@ func TestConstraintCases(t *testing.T) { // Skip tests with CommonName set because OpenSSL will try to match it // against name constraints, while we ignore it when it's not hostname-looking. if !test.noOpenSSL && testNameConstraintsAgainstOpenSSL && test.leaf.cn == "" { - output, err := testChainAgainstOpenSSL(leafCert, intermediatePool, rootPool) + output, err := testChainAgainstOpenSSL(t, leafCert, intermediatePool, rootPool) if err == nil && len(test.expectedError) > 0 { t.Errorf("#%d: unexpectedly succeeded against OpenSSL", i) if debugOpenSSLFailure { @@ -1993,7 +1993,7 @@ func TestConstraintCases(t *testing.T) { pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) return buf.String() } - t.Errorf("#%d: root:\n%s", i, certAsPEM(rootPool.certs[0])) + t.Errorf("#%d: root:\n%s", i, certAsPEM(rootPool.mustCert(t, 0))) t.Errorf("#%d: leaf:\n%s", i, certAsPEM(leafCert)) } @@ -2019,10 +2019,10 @@ func writePEMsToTempFile(certs []*Certificate) *os.File { return file } -func testChainAgainstOpenSSL(leaf *Certificate, intermediates, roots *CertPool) (string, error) { +func testChainAgainstOpenSSL(t *testing.T, leaf *Certificate, intermediates, roots *CertPool) (string, error) { args := []string{"verify", "-no_check_time"} - rootsFile := writePEMsToTempFile(roots.certs) + rootsFile := writePEMsToTempFile(allCerts(t, roots)) if debugOpenSSLFailure { println("roots file:", rootsFile.Name()) } else { @@ -2030,8 +2030,8 @@ func testChainAgainstOpenSSL(leaf *Certificate, intermediates, roots *CertPool) } args = append(args, "-CAfile", rootsFile.Name()) - if len(intermediates.certs) > 0 { - intermediatesFile := writePEMsToTempFile(intermediates.certs) + if intermediates.len() > 0 { + intermediatesFile := writePEMsToTempFile(allCerts(t, intermediates)) if debugOpenSSLFailure { println("intermediates file:", intermediatesFile.Name()) } else { diff --git a/src/crypto/x509/root_cgo_darwin.go b/src/crypto/x509/root_cgo_darwin.go index 15c72cc0c83..825e8d4812b 100644 --- a/src/crypto/x509/root_cgo_darwin.go +++ b/src/crypto/x509/root_cgo_darwin.go @@ -313,7 +313,11 @@ func _loadSystemRootsWithCgo() (*CertPool, error) { untrustedRoots.AppendCertsFromPEM(buf) trustedRoots := NewCertPool() - for _, c := range roots.certs { + for _, lc := range roots.lazyCerts { + c, err := lc.getCert() + if err != nil { + return nil, err + } if !untrustedRoots.contains(c) { trustedRoots.AddCert(c) } diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go index 2c773b91203..69f181c2d48 100644 --- a/src/crypto/x509/root_darwin_test.go +++ b/src/crypto/x509/root_darwin_test.go @@ -24,7 +24,7 @@ func TestSystemRoots(t *testing.T) { // There are 174 system roots on Catalina, and 163 on iOS right now, require // at least 100 to make sure this is not completely broken. - if want, have := 100, len(sysRoots.certs); have < want { + if want, have := 100, sysRoots.len(); have < want { t.Errorf("want at least %d system roots, have %d", want, have) } @@ -43,11 +43,14 @@ func TestSystemRoots(t *testing.T) { t.Logf("loadSystemRootsWithCgo: %v", cgoSysRootsDuration) // Check that the two cert pools are the same. - sysPool := make(map[string]*Certificate, len(sysRoots.certs)) - for _, c := range sysRoots.certs { + sysPool := make(map[string]*Certificate, sysRoots.len()) + for i := 0; i < sysRoots.len(); i++ { + c := sysRoots.mustCert(t, i) sysPool[string(c.Raw)] = c } - for _, c := range cgoRoots.certs { + for i := 0; i < cgoRoots.len(); i++ { + c := cgoRoots.mustCert(t, i) + if _, ok := sysPool[string(c.Raw)]; ok { delete(sysPool, string(c.Raw)) } else { diff --git a/src/crypto/x509/root_unix.go b/src/crypto/x509/root_unix.go index ae72f025c30..1090b69f839 100644 --- a/src/crypto/x509/root_unix.go +++ b/src/crypto/x509/root_unix.go @@ -75,7 +75,7 @@ func loadSystemRoots() (*CertPool, error) { } } - if len(roots.certs) > 0 || firstErr == nil { + if roots.len() > 0 || firstErr == nil { return roots, nil } diff --git a/src/crypto/x509/root_unix_test.go b/src/crypto/x509/root_unix_test.go index 5a8015429c0..b2e832ff368 100644 --- a/src/crypto/x509/root_unix_test.go +++ b/src/crypto/x509/root_unix_test.go @@ -113,15 +113,15 @@ func TestEnvVars(t *testing.T) { // Verify that the returned certs match, otherwise report where the mismatch is. for i, cn := range tc.cns { - if i >= len(r.certs) { + if i >= r.len() { t.Errorf("missing cert %v @ %v", cn, i) - } else if r.certs[i].Subject.CommonName != cn { - fmt.Printf("%#v\n", r.certs[0].Subject) - t.Errorf("unexpected cert common name %q, want %q", r.certs[i].Subject.CommonName, cn) + } else if r.mustCert(t, i).Subject.CommonName != cn { + fmt.Printf("%#v\n", r.mustCert(t, 0).Subject) + t.Errorf("unexpected cert common name %q, want %q", r.mustCert(t, i).Subject.CommonName, cn) } } - if len(r.certs) > len(tc.cns) { - t.Errorf("got %v certs, which is more than %v wanted", len(r.certs), len(tc.cns)) + if r.len() > len(tc.cns) { + t.Errorf("got %v certs, which is more than %v wanted", r.len(), len(tc.cns)) } }) } @@ -197,7 +197,8 @@ func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) { strCertPool := func(p *CertPool) string { return string(bytes.Join(p.Subjects(), []byte("\n"))) } - if !reflect.DeepEqual(gotPool, wantPool) { + + if !certPoolEqual(gotPool, wantPool) { g, w := strCertPool(gotPool), strCertPool(wantPool) t.Fatalf("Mismatched certPools\nGot:\n%s\n\nWant:\n%s", g, w) } diff --git a/src/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go index 1e0f3acb670..22e5a9382be 100644 --- a/src/crypto/x509/root_windows.go +++ b/src/crypto/x509/root_windows.go @@ -38,7 +38,11 @@ func createStoreContext(leaf *Certificate, opts *VerifyOptions) (*syscall.CertCo } if opts.Intermediates != nil { - for _, intermediate := range opts.Intermediates.certs { + for i := 0; i < opts.Intermediates.len(); i++ { + intermediate, err := opts.Intermediates.cert(i) + if err != nil { + return nil, err + } ctx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &intermediate.Raw[0], uint32(len(intermediate.Raw))) if err != nil { return nil, err diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go index 5fdd4cb9fe1..46afb2698a9 100644 --- a/src/crypto/x509/verify.go +++ b/src/crypto/x509/verify.go @@ -761,11 +761,13 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e if len(c.Raw) == 0 { return nil, errNotParsed } - if opts.Intermediates != nil { - for _, intermediate := range opts.Intermediates.certs { - if len(intermediate.Raw) == 0 { - return nil, errNotParsed - } + for i := 0; i < opts.Intermediates.len(); i++ { + c, err := opts.Intermediates.cert(i) + if err != nil { + return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", err) + } + if len(c.Raw) == 0 { + return nil, errNotParsed } } @@ -891,11 +893,11 @@ func (c *Certificate) buildChains(cache map[*Certificate][][]*Certificate, curre } } - for _, rootNum := range opts.Roots.findPotentialParents(c) { - considerCandidate(rootCertificate, opts.Roots.certs[rootNum]) + for _, root := range opts.Roots.findPotentialParents(c) { + considerCandidate(rootCertificate, root) } - for _, intermediateNum := range opts.Intermediates.findPotentialParents(c) { - considerCandidate(intermediateCertificate, opts.Intermediates.certs[intermediateNum]) + for _, intermediate := range opts.Intermediates.findPotentialParents(c) { + considerCandidate(intermediateCertificate, intermediate) } if len(chains) > 0 { diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 47d78cf02af..1ba31aeff32 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -1960,7 +1960,7 @@ func TestSystemCertPool(t *testing.T) { if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(a, b) { + if !certPoolEqual(a, b) { t.Fatal("two calls to SystemCertPool had different results") } if ok := b.AppendCertsFromPEM([]byte(` @@ -2912,3 +2912,53 @@ func TestCreateCertificateMD5(t *testing.T) { t.Fatalf("CreateCertificate failed when SignatureAlgorithm = MD5WithRSA: %s", err) } } + +func (s *CertPool) mustCert(t *testing.T, n int) *Certificate { + c, err := s.lazyCerts[n].getCert() + if err != nil { + t.Fatalf("failed to load cert %d: %v", n, err) + } + return c +} + +func allCerts(t *testing.T, p *CertPool) []*Certificate { + all := make([]*Certificate, p.len()) + for i := range all { + all[i] = p.mustCert(t, i) + } + return all +} + +// certPoolEqual reports whether a and b are equal, except for the +// function pointers. +func certPoolEqual(a, b *CertPool) bool { + if (a != nil) != (b != nil) { + return false + } + if a == nil { + return true + } + if !reflect.DeepEqual(a.byName, b.byName) || + len(a.lazyCerts) != len(b.lazyCerts) { + return false + } + for i := range a.lazyCerts { + la, lb := a.lazyCerts[i], b.lazyCerts[i] + if !bytes.Equal(la.rawSubject, lb.rawSubject) { + return false + } + ca, err := la.getCert() + if err != nil { + panic(err) + } + cb, err := la.getCert() + if err != nil { + panic(err) + } + if !ca.Equal(cb) { + return false + } + } + + return true +} From 5e371e0f93c5618a36f66afdd9c6047a5955c101 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sat, 7 Nov 2020 08:00:15 -0800 Subject: [PATCH 384/403] crypto/x509: keep smaller root cert representation in memory until needed Instead of parsing the PEM files and then storing the *Certificate values forever, still parse them to see if they're valid and pick out some fields, but then only store the decoded pem.Block.Bytes until that cert is first needed. Saves about 500K of memory on my (Debian stable) machine after doing a tls.Dial or calling x509.SystemCertPool. A more aggressive version of this is still possible: we can not keep the pem.Block.Bytes in memory either, and re-read them from disk when necessary. But dealing with files disappearing and even large multi-cert PEM files changing (with offsets sliding around) made this conservative version attractive. It doesn't change the slurp-roots-on-startup semantics. It just does so with less memory retained. Change-Id: I3aea333f4749ae3b0026042ec3ff7ac015c72204 Reviewed-on: https://go-review.googlesource.com/c/go/+/230025 Run-TryBot: Brad Fitzpatrick TryBot-Result: Go Bot Trust: Roland Shoemaker Reviewed-by: Filippo Valsorda --- src/crypto/x509/cert_pool.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go index 2cfaeb2d9ef..c23ccf1b396 100644 --- a/src/crypto/x509/cert_pool.go +++ b/src/crypto/x509/cert_pool.go @@ -10,6 +10,7 @@ import ( "encoding/pem" "errors" "runtime" + "sync" ) type sum224 [sha256.Size224]byte @@ -224,16 +225,27 @@ func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { continue } - cert, err := ParseCertificate(block.Bytes) + certBytes := block.Bytes + cert, err := ParseCertificate(certBytes) if err != nil { continue } - - s.AddCert(cert) + var lazyCert struct { + sync.Once + v *Certificate + } + s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) { + lazyCert.Do(func() { + // This can't fail, as the same bytes already parsed above. + lazyCert.v, _ = ParseCertificate(certBytes) + certBytes = nil + }) + return lazyCert.v, nil + }) ok = true } - return + return ok } // Subjects returns a list of the DER-encoded subjects of From afe7c8d0b25f26f0abd749ca52c7e1e7dfdee8cb Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Mon, 2 Nov 2020 08:48:23 -0500 Subject: [PATCH 385/403] testing: increase benchmark output to four significant figures Currently, the benchmark output from the testing package prints small values with three significant figures. This means it can only distinguish 1 part in 100, or a 1% error, which can be enough to throw off further analysis of the output. This CL increases it to four significant figures. For time values, at least, anything beyond four significant figures is almost certainly noise. Fixes #34626. Change-Id: I3bcf305427130026276e6a4c78167989319f280c Reviewed-on: https://go-review.googlesource.com/c/go/+/267102 Trust: Austin Clements Run-TryBot: Austin Clements TryBot-Result: Go Bot Reviewed-by: Michael Pratt --- src/testing/benchmark.go | 20 ++++++++++++-------- src/testing/benchmark_test.go | 21 +++++++++++---------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/testing/benchmark.go b/src/testing/benchmark.go index 1b81ec3a2d6..a8f75e97123 100644 --- a/src/testing/benchmark.go +++ b/src/testing/benchmark.go @@ -451,23 +451,27 @@ func (r BenchmarkResult) String() string { func prettyPrint(w io.Writer, x float64, unit string) { // Print all numbers with 10 places before the decimal point - // and small numbers with three sig figs. + // and small numbers with four sig figs. Field widths are + // chosen to fit the whole part in 10 places while aligning + // the decimal point of all fractional formats. var format string switch y := math.Abs(x); { - case y == 0 || y >= 99.95: + case y == 0 || y >= 999.95: format = "%10.0f %s" - case y >= 9.995: + case y >= 99.995: format = "%12.1f %s" - case y >= 0.9995: + case y >= 9.9995: format = "%13.2f %s" - case y >= 0.09995: + case y >= 0.99995: format = "%14.3f %s" - case y >= 0.009995: + case y >= 0.099995: format = "%15.4f %s" - case y >= 0.0009995: + case y >= 0.0099995: format = "%16.5f %s" - default: + case y >= 0.00099995: format = "%17.6f %s" + default: + format = "%18.7f %s" } fmt.Fprintf(w, format, x, unit) } diff --git a/src/testing/benchmark_test.go b/src/testing/benchmark_test.go index 1434c2613f1..4c1cbd19335 100644 --- a/src/testing/benchmark_test.go +++ b/src/testing/benchmark_test.go @@ -22,13 +22,14 @@ var prettyPrintTests = []struct { {0, " 0 x"}, {1234.1, " 1234 x"}, {-1234.1, " -1234 x"}, - {99.950001, " 100 x"}, - {99.949999, " 99.9 x"}, - {9.9950001, " 10.0 x"}, - {9.9949999, " 9.99 x"}, - {-9.9949999, " -9.99 x"}, - {0.0099950001, " 0.0100 x"}, - {0.0099949999, " 0.00999 x"}, + {999.950001, " 1000 x"}, + {999.949999, " 999.9 x"}, + {99.9950001, " 100.0 x"}, + {99.9949999, " 99.99 x"}, + {-99.9949999, " -99.99 x"}, + {0.000999950001, " 0.001000 x"}, + {0.000999949999, " 0.0009999 x"}, // smallest case + {0.0000999949999, " 0.0001000 x"}, } func TestPrettyPrint(t *testing.T) { @@ -50,13 +51,13 @@ func TestResultString(t *testing.T) { if r.NsPerOp() != 2 { t.Errorf("NsPerOp: expected 2, actual %v", r.NsPerOp()) } - if want, got := " 100\t 2.40 ns/op", r.String(); want != got { + if want, got := " 100\t 2.400 ns/op", r.String(); want != got { t.Errorf("String: expected %q, actual %q", want, got) } // Test sub-1 ns/op (issue #31005) r.T = 40 * time.Nanosecond - if want, got := " 100\t 0.400 ns/op", r.String(); want != got { + if want, got := " 100\t 0.4000 ns/op", r.String(); want != got { t.Errorf("String: expected %q, actual %q", want, got) } @@ -130,7 +131,7 @@ func TestReportMetric(t *testing.T) { } // Test stringing. res.N = 1 // Make the output stable - want := " 1\t 12345 ns/op\t 0.200 frobs/op" + want := " 1\t 12345 ns/op\t 0.2000 frobs/op" if want != res.String() { t.Errorf("expected %q, actual %q", want, res.String()) } From 7307e86afda3c5c7f6158d2469c39606fd1dba65 Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Sun, 8 Nov 2020 09:44:33 +0100 Subject: [PATCH 386/403] test/codegen: go fmt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #42445 Change-Id: I9653ef094dba2a1ac2e3daaa98279d10df17a2a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/268257 Trust: Alberto Donizetti Trust: Martin Möhrmann Run-TryBot: Alberto Donizetti TryBot-Result: Go Bot Reviewed-by: Martin Möhrmann --- test/codegen/bits.go | 4 +- test/codegen/compare_and_branch.go | 64 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/test/codegen/bits.go b/test/codegen/bits.go index 56e0f3474e1..4508eba4877 100644 --- a/test/codegen/bits.go +++ b/test/codegen/bits.go @@ -344,11 +344,11 @@ func bitSetTest(x int) bool { // mask contiguous one bits func cont1Mask64U(x uint64) uint64 { // s390x:"RISBGZ\t[$]16, [$]47, [$]0," - return x&0x0000ffffffff0000 + return x & 0x0000ffffffff0000 } // mask contiguous zero bits func cont0Mask64U(x uint64) uint64 { // s390x:"RISBGZ\t[$]48, [$]15, [$]0," - return x&0xffff00000000ffff + return x & 0xffff00000000ffff } diff --git a/test/codegen/compare_and_branch.go b/test/codegen/compare_and_branch.go index 696a2d5f1c5..f7515064b08 100644 --- a/test/codegen/compare_and_branch.go +++ b/test/codegen/compare_and_branch.go @@ -155,52 +155,52 @@ func ui32x8() { // Signed 64-bit comparison with unsigned 8-bit immediate. func si64xu8(x chan int64) { - // s390x:"CLGIJ\t[$]8, R[0-9]+, [$]128, " - for <-x == 128 { - dummy() - } + // s390x:"CLGIJ\t[$]8, R[0-9]+, [$]128, " + for <-x == 128 { + dummy() + } - // s390x:"CLGIJ\t[$]6, R[0-9]+, [$]255, " - for <-x != 255 { - dummy() - } + // s390x:"CLGIJ\t[$]6, R[0-9]+, [$]255, " + for <-x != 255 { + dummy() + } } // Signed 32-bit comparison with unsigned 8-bit immediate. func si32xu8(x chan int32) { - // s390x:"CLIJ\t[$]8, R[0-9]+, [$]255, " - for <-x == 255 { - dummy() - } + // s390x:"CLIJ\t[$]8, R[0-9]+, [$]255, " + for <-x == 255 { + dummy() + } - // s390x:"CLIJ\t[$]6, R[0-9]+, [$]128, " - for <-x != 128 { - dummy() - } + // s390x:"CLIJ\t[$]6, R[0-9]+, [$]128, " + for <-x != 128 { + dummy() + } } // Unsigned 64-bit comparison with signed 8-bit immediate. func ui64xu8(x chan uint64) { - // s390x:"CGIJ\t[$]8, R[0-9]+, [$]-1, " - for <-x == ^uint64(0) { - dummy() - } + // s390x:"CGIJ\t[$]8, R[0-9]+, [$]-1, " + for <-x == ^uint64(0) { + dummy() + } - // s390x:"CGIJ\t[$]6, R[0-9]+, [$]-128, " - for <-x != ^uint64(127) { - dummy() - } + // s390x:"CGIJ\t[$]6, R[0-9]+, [$]-128, " + for <-x != ^uint64(127) { + dummy() + } } // Unsigned 32-bit comparison with signed 8-bit immediate. func ui32xu8(x chan uint32) { - // s390x:"CIJ\t[$]8, R[0-9]+, [$]-128, " - for <-x == ^uint32(127) { - dummy() - } + // s390x:"CIJ\t[$]8, R[0-9]+, [$]-128, " + for <-x == ^uint32(127) { + dummy() + } - // s390x:"CIJ\t[$]6, R[0-9]+, [$]-1, " - for <-x != ^uint32(0) { - dummy() - } + // s390x:"CIJ\t[$]6, R[0-9]+, [$]-1, " + for <-x != ^uint32(0) { + dummy() + } } From 22312437ee1e72451c70b79c90e36ad0b849e3f6 Mon Sep 17 00:00:00 2001 From: cch123 Date: Mon, 19 Oct 2020 12:55:46 +0000 Subject: [PATCH 387/403] crypto/tls: pool Conn's outBuf to reduce memory cost of idle connections Derived from CL 263277, which includes benchmarks. Fixes #42035 Co-authored-by: Filippo Valsorda Change-Id: I5f28673f95d4568b7d13dbc20e9d4b48d481a93d Reviewed-on: https://go-review.googlesource.com/c/go/+/267957 Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Trust: Filippo Valsorda Trust: Roland Shoemaker Reviewed-by: Roland Shoemaker Reviewed-by: Roberto Clapis --- src/crypto/tls/conn.go | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index ada19d6e7ae..b9a1095862a 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -94,7 +94,6 @@ type Conn struct { rawInput bytes.Buffer // raw input, starting with a record header input bytes.Reader // application data waiting to be read, from rawInput.Next hand bytes.Buffer // handshake data waiting to be read - outBuf []byte // scratch buffer used by out.encrypt buffering bool // whether records are buffered in sendBuf sendBuf []byte // a buffer of records waiting to be sent @@ -928,9 +927,28 @@ func (c *Conn) flush() (int, error) { return n, err } +// outBufPool pools the record-sized scratch buffers used by writeRecordLocked. +var outBufPool = sync.Pool{ + New: func() interface{} { + return new([]byte) + }, +} + // writeRecordLocked writes a TLS record with the given type and payload to the // connection and updates the record layer state. func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) { + outBufPtr := outBufPool.Get().(*[]byte) + outBuf := *outBufPtr + defer func() { + // You might be tempted to simplify this by just passing &outBuf to Put, + // but that would make the local copy of the outBuf slice header escape + // to the heap, causing an allocation. Instead, we keep around the + // pointer to the slice header returned by Get, which is already on the + // heap, and overwrite and return that. + *outBufPtr = outBuf + outBufPool.Put(outBufPtr) + }() + var n int for len(data) > 0 { m := len(data) @@ -938,8 +956,8 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) { m = maxPayload } - _, c.outBuf = sliceForAppend(c.outBuf[:0], recordHeaderLen) - c.outBuf[0] = byte(typ) + _, outBuf = sliceForAppend(outBuf[:0], recordHeaderLen) + outBuf[0] = byte(typ) vers := c.vers if vers == 0 { // Some TLS servers fail if the record version is @@ -950,17 +968,17 @@ func (c *Conn) writeRecordLocked(typ recordType, data []byte) (int, error) { // See RFC 8446, Section 5.1. vers = VersionTLS12 } - c.outBuf[1] = byte(vers >> 8) - c.outBuf[2] = byte(vers) - c.outBuf[3] = byte(m >> 8) - c.outBuf[4] = byte(m) + outBuf[1] = byte(vers >> 8) + outBuf[2] = byte(vers) + outBuf[3] = byte(m >> 8) + outBuf[4] = byte(m) var err error - c.outBuf, err = c.out.encrypt(c.outBuf, data[:m], c.config.rand()) + outBuf, err = c.out.encrypt(outBuf, data[:m], c.config.rand()) if err != nil { return n, err } - if _, err := c.write(c.outBuf); err != nil { + if _, err := c.write(outBuf); err != nil { return n, err } n += m From f858c221270addffaceb668196caf7fd8ceb0019 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 6 Nov 2020 15:15:44 -0500 Subject: [PATCH 388/403] cmd/go/internal/modget: fix a typo introduced in CL 263267 Updates #37438 Change-Id: I78f377afd73dad75aed219836725a27fbaa5b69c Reviewed-on: https://go-review.googlesource.com/c/go/+/268117 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Dan Peterson Reviewed-by: Dmitri Shuralyov TryBot-Result: Go Bot --- src/cmd/go/alldocs.go | 4 ++-- src/cmd/go/internal/modget/get.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index ada85b13241..583ae9e92ef 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -617,8 +617,8 @@ // dependency should be removed entirely, downgrading or removing modules // depending on it as needed. // -// The version suffix @latest explicitly requests the latest minor release ofthe -// module named by the given path. The suffix @upgrade is like @latest but +// The version suffix @latest explicitly requests the latest minor release of +// the module named by the given path. The suffix @upgrade is like @latest but // will not downgrade a module if it is already required at a revision or // pre-release version newer than the latest released version. The suffix // @patch requests the latest patch release: the latest released version diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index bb59191c734..f7598884365 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -89,8 +89,8 @@ downgrades the dependency. The version suffix @none indicates that the dependency should be removed entirely, downgrading or removing modules depending on it as needed. -The version suffix @latest explicitly requests the latest minor release ofthe -module named by the given path. The suffix @upgrade is like @latest but +The version suffix @latest explicitly requests the latest minor release of +the module named by the given path. The suffix @upgrade is like @latest but will not downgrade a module if it is already required at a revision or pre-release version newer than the latest released version. The suffix @patch requests the latest patch release: the latest released version From feccfb8adaf5a0ce93a0dafa31336ccb6f41c618 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 9 Nov 2020 14:00:09 +0100 Subject: [PATCH 389/403] crypto/x509: use fingerprint map for (*CertPool).contains This fell through the cracks from the CL 229917 comments. Change-Id: I22584107f1e8111f9c523f45307dd50e1e5f4b8f Reviewed-on: https://go-review.googlesource.com/c/go/+/268339 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Brad Fitzpatrick --- src/crypto/x509/cert_pool.go | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go index c23ccf1b396..bcc5db3b703 100644 --- a/src/crypto/x509/cert_pool.go +++ b/src/crypto/x509/cert_pool.go @@ -161,18 +161,7 @@ func (s *CertPool) contains(cert *Certificate) bool { if s == nil { return false } - candidates := s.byName[string(cert.RawSubject)] - for _, i := range candidates { - c, err := s.cert(i) - if err != nil { - return false - } - if c.Equal(cert) { - return true - } - } - - return false + return s.haveSum[sha256.Sum224(cert.Raw)] } // AddCert adds a certificate to a pool. From 564ec4867bd867ccf37d149243d016abfa5a857c Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 30 Oct 2020 16:12:13 +0100 Subject: [PATCH 390/403] crypto/tls: don't use CN in BuildNameToCertificate if SANs are present Change-Id: I18d5b9fc392a6a52fbdd240254d6d9db838073a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/266540 Trust: Filippo Valsorda Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- src/crypto/tls/common.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 66d2c005a7c..86dc0dd3b2e 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -1263,7 +1263,9 @@ func (c *Config) BuildNameToCertificate() { if err != nil { continue } - if len(x509Cert.Subject.CommonName) > 0 { + // If SANs are *not* present, some clients will consider the certificate + // valid for the name in the Common Name. + if x509Cert.Subject.CommonName != "" && len(x509Cert.DNSNames) == 0 { c.NameToCertificate[x509Cert.Subject.CommonName] = cert } for _, san := range x509Cert.DNSNames { From 3fad58f12efae91ee2ab40f28e513a8d02cbcf96 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Fri, 30 Oct 2020 19:15:09 +0100 Subject: [PATCH 391/403] crypto/x509: update iOS bundled roots to version 55161.140.3 Extended the sorting logic to be stable even when there are two roots with the same name and notBefore timestamp, like the GlobalSign ones. Updates #38843 Change-Id: Ie4db0bb8b6a8b5ffbb7390b6bd527fc0c3badaca Reviewed-on: https://go-review.googlesource.com/c/go/+/266677 Reviewed-by: Katie Hockman Trust: Filippo Valsorda --- src/crypto/x509/root.go | 2 +- src/crypto/x509/root_ios.go | 213 ++++++-------------------------- src/crypto/x509/root_ios_gen.go | 6 +- 3 files changed, 41 insertions(+), 180 deletions(-) diff --git a/src/crypto/x509/root.go b/src/crypto/x509/root.go index eccb64121fa..ac92915128d 100644 --- a/src/crypto/x509/root.go +++ b/src/crypto/x509/root.go @@ -4,7 +4,7 @@ package x509 -//go:generate go run root_ios_gen.go -version 55161.80.1 +//go:generate go run root_ios_gen.go -version 55161.140.3 import "sync" diff --git a/src/crypto/x509/root_ios.go b/src/crypto/x509/root_ios.go index 98e747733a5..bb4a5f75ba8 100644 --- a/src/crypto/x509/root_ios.go +++ b/src/crypto/x509/root_ios.go @@ -1,4 +1,4 @@ -// Code generated by root_ios_gen.go -version 55161.80.1; DO NOT EDIT. +// Code generated by root_ios_gen.go -version 55161.140.3; DO NOT EDIT. // Update the version in root.go and regenerate with "go generate". // +build ios @@ -561,33 +561,6 @@ Hld2j383LS4CXN1jyfJxuCZA3xWNdUQ/eb3mHZnhQyw+rW++uaT+DjUZUWOxw961 kj5ReAFziqQjyqSI8R5cH0EWLX6VCqrpiUGYGxrdyyC/R14MJsVVNU3GMIuZZxTH CR+6R8faAQmHJEKVvRNgGQrv6n8Obs3BREM6StXj -----END CERTIFICATE----- -# "ApplicationCA2 Root" -# 12 6B F0 1C 10 94 D2 F0 CA 2E 35 23 80 B3 C7 24 -# 29 45 46 CC C6 55 97 BE F7 F1 2D 8A 17 1F 19 84 ------BEGIN CERTIFICATE----- -MIID9zCCAt+gAwIBAgILMTI1MzcyODI4MjgwDQYJKoZIhvcNAQELBQAwWDELMAkG -A1UEBhMCSlAxHDAaBgNVBAoTE0phcGFuZXNlIEdvdmVybm1lbnQxDTALBgNVBAsT -BEdQS0kxHDAaBgNVBAMTE0FwcGxpY2F0aW9uQ0EyIFJvb3QwHhcNMTMwMzEyMTUw -MDAwWhcNMzMwMzEyMTUwMDAwWjBYMQswCQYDVQQGEwJKUDEcMBoGA1UEChMTSmFw -YW5lc2UgR292ZXJubWVudDENMAsGA1UECxMER1BLSTEcMBoGA1UEAxMTQXBwbGlj -YXRpb25DQTIgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKaq -rSVl1gAR1uh6dqr05rRL88zDUrSNrKZPtZJxb0a11a2LEiIXJc5F6BR6hZrkIxCo -+rFnUOVtR+BqiRPjrq418fRCxQX3TZd+PCj8sCaRHoweOBqW3FhEl2LjMsjRFUFN -dZh4vqtoqV7tR76kuo6hApfek3SZbWe0BSXulMjtqqS6MmxCEeu+yxcGkOGThchk -KM4fR8fAXWDudjbcMztR63vPctgPeKgZggiQPhqYjY60zxU2pm7dt+JNQCBT2XYq -0HisifBPizJtROouurCp64ndt295D6uBbrjmiykLWa+2SQ1RLKn9nShjZrhwlXOa -2Po7M7xCQhsyrLEy+z0CAwEAAaOBwTCBvjAdBgNVHQ4EFgQUVqesqgIdsqw9kA6g -by5Bxnbne9owDgYDVR0PAQH/BAQDAgEGMHwGA1UdEQR1MHOkcTBvMQswCQYDVQQG -EwJKUDEYMBYGA1UECgwP5pel5pys5Zu95pS/5bqcMRswGQYDVQQLDBLmlL/lupzo -qo3oqLzln7rnm6QxKTAnBgNVBAMMIOOCouODl+ODquOCseODvOOCt+ODp+ODs0NB -MiBSb290MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAH+aCXWs -B9FydC53VzDCBJzUgKaD56WgG5/+q/OAvdVKo6GPtkxgEefK4WCB10jBIFmlYTKL -nZ6X02aD2mUuWD7b5S+lzYxzplG+WCigeVxpL0PfY7KJR8q73rk0EWOgDiUX5Yf0 -HbCwpc9BqHTG6FPVQvSCLVMJEWgmcZR1E02qdog8dLHW40xPYsNJTE5t8XB+w3+m -Bcx4m+mB26jIx1ye/JKSLaaX8ji1bnOVDMA/zqaUMLX6BbfeniCq/BNkyYq6ZO/i -Y+TYmK5rtT6mVbgzPixy+ywRAPtbFi+E0hOe+gXFwctyTiLdhMpLvNIthhoEdlkf -SUJiOxMfFui61/0= ------END CERTIFICATE----- # "Atos TrustedRoot 2011" # F3 56 BE A2 44 B7 A9 1E B3 5D 53 CA 9A D7 86 4A # CE 01 8E 2D 35 D5 F8 F9 6D DF 68 A6 F4 1A A4 74 @@ -2032,35 +2005,6 @@ nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== -----END CERTIFICATE----- # "Entrust.net Certification Authority (2048)" -# D1 C3 39 EA 27 84 EB 87 0F 93 4F C5 63 4E 4A A9 -# AD 55 05 01 64 01 F2 64 65 D3 7A 57 46 63 35 9F ------BEGIN CERTIFICATE----- -MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML -RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp -bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 -IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp -ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy -MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 -LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp -YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG -A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq -K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe -sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX -MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT -XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ -HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH -4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA -vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G -CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA -WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo -oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ -h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18 -f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN -B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy -vUxFnmG6v4SBkgPR0ml8xQ== ------END CERTIFICATE----- -# "Entrust.net Certification Authority (2048)" # 6D C4 71 72 E0 1C BC B0 BF 62 58 0D 89 5F E2 B8 # AC 9A D4 F8 73 80 1E 0C 10 B9 C8 37 D2 1E B1 77 -----BEGIN CERTIFICATE----- @@ -2378,22 +2322,6 @@ Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH WD9f -----END CERTIFICATE----- # "GlobalSign" -# BE C9 49 11 C2 95 56 76 DB 6C 0A 55 09 86 D7 6E -# 3B A0 05 66 7C 44 2C 97 62 B4 FB B7 73 DE 22 8C ------BEGIN CERTIFICATE----- -MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk -MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH -bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX -DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD -QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ -FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F -uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX -kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs -ewv4n4Q= ------END CERTIFICATE----- -# "GlobalSign" # 17 9F BC 14 8A 3D D0 0F D2 4E A1 34 58 CC 43 BF # A7 F5 9C 81 82 D7 83 A5 13 F6 EB EC 10 0C 89 24 -----BEGIN CERTIFICATE----- @@ -2410,6 +2338,22 @@ KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg 515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO xwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- +# "GlobalSign" +# BE C9 49 11 C2 95 56 76 DB 6C 0A 55 09 86 D7 6E +# 3B A0 05 66 7C 44 2C 97 62 B4 FB B7 73 DE 22 8C +-----BEGIN CERTIFICATE----- +MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk +MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH +bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX +DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD +QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ +FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw +DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F +uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX +kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs +ewv4n4Q= +-----END CERTIFICATE----- # "GlobalSign Root CA" # EB D4 10 40 E4 BB 3E C7 42 C9 E3 81 D3 1E F2 A4 # 1A 48 B6 68 5C 96 E7 CE F3 C1 DF 6C D4 33 1C 99 @@ -3095,6 +3039,24 @@ ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= -----END CERTIFICATE----- +# "OISTE WISeKey Global Root GC CA" +# 85 60 F9 1C 36 24 DA BA 95 70 B5 FE A0 DB E3 6F +# F1 1A 83 23 BE 94 86 85 4F B3 F3 4A 55 71 19 8D +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw +CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91 +bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg +Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ +BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu +ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS +b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni +eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W +p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T +rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV +57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg +Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- # "OpenTrust Root CA G1" # 56 C7 71 28 D9 8C 18 D9 1B 4C FD FF BC 25 EE 91 # 03 D4 75 8E A2 AB AD 82 6A 90 F3 45 7D 46 0E B4 @@ -4113,41 +4075,6 @@ Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- -# "SwissSign Gold Root CA - G3" -# 7A F6 EA 9F 75 3A 1E 70 9B D6 4D 0B EB 86 7C 11 -# E8 C2 95 A5 6E 24 A6 E0 47 14 59 DC CD AA 15 58 ------BEGIN CERTIFICATE----- -MIIFejCCA2KgAwIBAgIJAN7E8kTzHab8MA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxJDAiBgNVBAMTG1N3aXNzU2ln -biBHb2xkIFJvb3QgQ0EgLSBHMzAeFw0wOTA4MDQxMzMxNDdaFw0zNzA4MDQxMzMx -NDdaMEoxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxJDAiBgNV -BAMTG1N3aXNzU2lnbiBHb2xkIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEB -BQADggIPADCCAgoCggIBAMPon8hlWp1nG8FFl7S0h0NbYWCAnvJ/XvlnRN1E+qu1 -q3f/KhlMzm/Ej0Gf4OLNcuDR1FJhQQkKvwpw++CDaWEpytsimlul5t0XlbBvhI46 -PmRaQfsbWPz9Kz6ypOasyYK8zvaV+Jd37Sb2WK6eJ+IPg+zFNljIe8/Vh6GphxoT -Z2EBbaZpnOKQ8StoZfPosHz8gj3erdgKAAlEeROc8P5udXvCvLNZAQt8xdUt8L// -bVfSSYHrtLNQrFv5CxUVjGn/ozkB7fzc3CeXjnuL1Wqm1uAdX80Bkeb1Ipi6LgkY -OG8TqIHS+yE35y20YueBkLDGeVm3Z3X+vo87+jbsr63ST3Q2AeVXqyMEzEpel89+ -xu+MzJUjaY3LOMcZ9taKABQeND1v2gwLw7qX/BFLUmE+vzNnUxC/eBsJwke6Hq9Y -9XWBf71W8etW19lpDAfpNzGwEhwy71bZvnorfL3TPbxqM006PFAQhyfHegpnU9t/ -gJvoniP6+Qg6i6GONFpIM19k05eGBxl9iJTOKnzFat+vvKmfzTqmurtU+X+P388O -WsStmryzOndzg0yTPJBotXxQlRHIgl6UcdBBGPvJxmXszom2ziKzEVs/4J0+Gxho -DaoDoWdZv2udvPjyZS+aQTpF2F7QNmxvOx5jtI6YTBPbIQ6fe+3qoKpxw+ujoNIl -AgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud -DgQWBBRclwZGNKvfMMV8xQ1VcWYwtWCPnjAfBgNVHSMEGDAWgBRclwZGNKvfMMV8 -xQ1VcWYwtWCPnjANBgkqhkiG9w0BAQsFAAOCAgEAd0tN3uqFSqssJ9ZFx/FfIMFb -YO0Hy6Iz3DbPx5TxBsfV2s/NrYQ+/xJIf0HopWZXMMQd5KcaLy1Cwe9Gc7LV9Vr9 -Dnpr0sgxow1IlldlY1UYwPzkisyYhlurDIonN/ojaFlcJtehwcK5Tiz/KV7mlAu+ -zXJPleiP9ve4Pl7Oz54RyawDKUiKqbamNLmsQP/EtnM3scd/qVHbSypHX0AkB4gG -tySz+3/3sIsz+r8jdaNc/qplGsK+8X2BdwOBsY3XlQ16PEKYt4+pfVDh31IGmqBS -VHiDB2FSCTdeipynxlHRXGPRhNzC29L6Wxg2fWa81CiXL3WWHIQHrIuOUxG+JCGq -Z/LBrYic07B4Z3j101gDIApdIPG152XMDiDj1d/mLxkrhWjBBCbPj+0FU6HdBw7r -QSbHtKksW+NpPWbAYhvAqobAN8MxBIZwOb5rXyFAQaB/5dkPOEtwX0n4hbgrLqof -k0FD+PuydDwfS1dbt9RRoZJKzr4Qou7YFCJ7uUG9jemIqdGPAxpg/z+HiaCZJyJm -sD5onnKIUTidEz5FbQXlRrVz7UOGsRQKHrzaDb8eJFxmjw6+of3G62m8Q3nXA3b5 -3IeZuJjEzX9tEPkQvixC/pwpTYNrCr21jsRIiv0hB6aAfR+b6au9gmFECnEnX22b -kJ6u/zYks2gD1pWMa3M= ------END CERTIFICATE----- # "SwissSign Platinum CA - G2" # 3B 22 2E 56 67 11 E9 92 30 0D C0 B1 5A B9 47 3D # AF DE F8 C8 4D 0C EF 7D 33 17 B4 C1 82 1D 14 36 @@ -4184,41 +4111,6 @@ DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== -----END CERTIFICATE----- -# "SwissSign Platinum Root CA - G3" -# 59 B3 82 9F 1F F4 43 34 49 58 FA E8 BF F6 21 B6 -# 84 C8 48 CF BF 7E AD 6B 63 A6 CA 50 F2 79 4F 89 ------BEGIN CERTIFICATE----- -MIIFgTCCA2mgAwIBAgIIIj+pFyDegZQwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UE -BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEoMCYGA1UEAxMfU3dpc3NTaWdu -IFBsYXRpbnVtIFJvb3QgQ0EgLSBHMzAeFw0wOTA4MDQxMzM0MDRaFw0zNzA4MDQx -MzM0MDRaME4xCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxKDAm -BgNVBAMTH1N3aXNzU2lnbiBQbGF0aW51bSBSb290IENBIC0gRzMwggIiMA0GCSqG -SIb3DQEBAQUAA4ICDwAwggIKAoICAQCUoO8TG59EIBvNxaoiu9nyUj56Wlh35o2h -K8ncpPPksxOUAGKbHPJDUEOBfq8wNkmsGIkMGEW4PsdUbePYmllriholqba1Dbd9 -I/BffagHqfc+hi7IAU3c5jbtHeU3B2kSS+OD0QQcJPAfcHHnGe1zSG6VKxW2VuYC -31bpm/rqpu7gwsO64MzGyHvXbzqVmzqPvlss0qmgOD7WiOGxYhOO3KswZ82oaqZj -K4Kwy8c9Tu1y9n2rMk5lAusPmXT4HBoojA5FAJMsFJ9txxue9orce3jjtJRHHU0F -bYR6kFSynot1woDfhzk/n/tIVAeNoCn1+WBfWnLou5ugQuAIADSjFTwT49YaawKy -lCGjnUG8KmtOMzumlDj8PccrM7MuKwZ0rJsQb8VORfddoVYDLA1fer0e3h13kGva -pS2KTOnfQfTnS+x9lUKfTKkJD0OIPz2T5yv0ekjaaMTdEoAxGl0kVCamJCGzTK3a -Fwg2AlfGnIZwyXXJnnxh2HjmuegUafkcECgSXUt1ULo80GdwVVVWS/s9HNjbeU2X -37ie2xcs1TUHuFCp9473Vv96Z0NPINnKZtY4YEvulDHWDaJIm/80aZTGNfWWiO+q -ZsyBputMU/8ydKe2nZhXtLomqfEzM2J+OrADEVf/3G8RI60+xgrQzFS3LcKTHeXC -pozH2O9T9wIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB -/zAdBgNVHQ4EFgQUVio/kFj0F1oUstcIG4VbVGpUGigwHwYDVR0jBBgwFoAUVio/ -kFj0F1oUstcIG4VbVGpUGigwDQYJKoZIhvcNAQELBQADggIBAGztiudDqHknm7jP -hz5kOBiMEUKShjfgWMMb7gQu94TsgxBoDH94LZzCl442ThbYDuprSK1Pnl0NzA2p -PhiFfsxomTk11tifhsEy+01lsyIUS8iFZtoX/3GRrJxWV95xLFZCv/jNDvCi0//S -IhX70HgKfuGwWs6ON9upnueVz2PyLA3S+m/zyNX7ALf3NWcQ03tS7BAy+L/dXsmm -gqTxsL8dLt0l5L1N8DWpkQFH+BAClFvrPusNutUdYyylLqvn4x6j7kuqX7FmAbSC -WvlGS8fx+N8svv113ZY4mjc6bqXmMhVus5DAOYp0pZWgvg0uiXnNKVaOw15XUcQF -bwRVj4HpTL1ZRssqvE3JHfLGTwXkyAQN925P2sM6nNLC9enGJHoUPhxCMKgCRTGp -/FCp3NyGOA9bkz9/CE5qDSc6EHlWwxW4PgaG9tlwZ691eoviWMzGdU8yVcVsFAko -O/KV5GreLCgHraB9Byjd1Fqj6aZ8E4yZC1J429nR3z5aQ3Z/RmBTws3ndkd8Vc20 -OWQQW5VLNV1EgyTV4C4kDMGAbmkAgAZ3CmaCEAxRbzeJV9vzTOW4ue4jZpdgt1Ld -2Zb7uoo7oE3OXvBETJDMIU8bOphrjjGD+YMIUssZwTVr7qEVW4g/bazyNJJTpjAq -E9fmhqhd2ULSx52peovL3+6iMcLl ------END CERTIFICATE----- # "SwissSign Silver CA - G2" # BE 6C 4D A2 BB B9 BA 59 B6 F3 93 97 68 37 42 46 # C3 C0 05 99 3F A9 8F 02 0D 1D ED BE D4 8A 81 D5 @@ -4255,41 +4147,6 @@ OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- -# "SwissSign Silver Root CA - G3" -# 1E 49 AC 5D C6 9E 86 D0 56 5D A2 C1 30 5C 41 93 -# 30 B0 B7 81 BF EC 50 E5 4A 1B 35 AF 7F DD D5 01 ------BEGIN CERTIFICATE----- -MIIFfjCCA2agAwIBAgIJAKqIsFoLsXabMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV -BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxJjAkBgNVBAMTHVN3aXNzU2ln -biBTaWx2ZXIgUm9vdCBDQSAtIEczMB4XDTA5MDgwNDEzMTkxNFoXDTM3MDgwNDEz -MTkxNFowTDELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEmMCQG -A1UEAxMdU3dpc3NTaWduIFNpbHZlciBSb290IENBIC0gRzMwggIiMA0GCSqGSIb3 -DQEBAQUAA4ICDwAwggIKAoICAQC+h5sF5nF8Um9t7Dep6bPczF9/01DqIZsE8D2/ -vo7JpRQWMhDPmfzscK1INmckDBcy1inlSjmxN+umeAxsbxnKTvdR2hro+iE4bJWc -L9aLzDsCm78mmxFFtrg0Wh2mVEhSyJ14cc5ISsyneIPcaKtmHncH0zYYCNfUbWD4 -8HnTMzYJkmO3BJr1p5baRa90GvyC46hbDjo/UleYfrycjMHAslrfxH7+DKZUdoN+ -ut3nKvRKNk+HZS6lujmNWWEp89OOJHCMU5sRpUcHsnUFXA2E2UTZzckmRFduAn2V -AdSrJIbuPXD7V/qwKRTQnfLFl8sJyvHyPefYS5bpiC+eR1GKVGWYSNIS5FR3DAfm -vluc8d0Dfo2E/L7JYtX8yTroibVfwgVSYfCcPuwuTYxykY7IQ8GiKF71gCTc4i+H -O1MA5cvwsnyNeRmgiM14+MWKWnflBqzdSt7mcG6+r771sasOCLDboD+Uxb4Subx7 -J3m1MildrsUgI5IDe1Q5sIkiVG0S48N46jpA/aSTrOktiDzbpkdmTN/YF+0W3hrW -10Fmvx2A8aTgZBEpXgwnBWLr5cQEYtHEnwxqVdZYOJxmD537q1SAmZzsSdaCn9pF -1j9TBgO3/R/shn104KS06DK2qgcj+O8kQZ5jMHj0VN2O8Fo4jhJ/eMdvAlYhM864 -uK1pVQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd -BgNVHQ4EFgQUoYxFkwoSYwunV18ySn3hIee3PmYwHwYDVR0jBBgwFoAUoYxFkwoS -YwunV18ySn3hIee3PmYwDQYJKoZIhvcNAQELBQADggIBAIeuYW1IOCrGHNxKLoR4 -ScAjKkW4NU3RBfq5BTPEZL3brVQWKrA+DVoo2qYagHMMxEFvr7g0tnfUW44dC4tG -kES1s+5JGInBSzSzhzV0op5FZ+1FcWa2uaElc9fCrIj70h2na9rAWubYWWQ0l2Ug -MTMDT86tCZ6u6cI+GHW0MyUSuwXsULpxQOK93ohGBSGEi6MrHuswMIm/EfVcRPiR -i0tZRQswDcoMT29jvgT+we3gh/7IzVa/5dyOetTWKU6A26ubP45lByL3RM2WHy3H -9Qm2mHD/ONxQFRGEO3+p8NgkVMgXjCsTSdaZf0XRD46/aXI3Uwf05q79Wz55uQbN -uIF4tE2g0DW65K7/00m8Ne1jxrP846thWgW2C+T/qSq+31ROwktcaNqjMqLJTVcY -UzRZPGaZ1zwCeKdMcdC/2/HEPOcB5gTyRPZIJjAzybEBGesC8cwh+joCMBedyF+A -P90lrAKb4xfevcqSFNJSgVPm6vwwZzKpYvaTFxUHMV4PG2n19Km3fC2z7YREMkco -BzuGaUWpxzaWkHJ02BKmcyPRTrm2ejrEKaFQBhG52fQmbmIIEiAW8AFXF9QFNmeX -61H5/zMkDAUPVr/vPRxSjoreaQ9aH/DVAzFEs5LG6nWorrvHYAOImP/HBIRSkIbh -tJOpUC/o69I2rDBgp9ADE7UK ------END CERTIFICATE----- # "Symantec Class 1 Public Primary Certification Authority - G6" # 9D 19 0B 2E 31 45 66 68 5B E8 A8 89 E2 7A A8 C7 # D7 AE 1D 8A AD DB A3 C1 EC F9 D2 48 63 CD 34 B9 diff --git a/src/crypto/x509/root_ios_gen.go b/src/crypto/x509/root_ios_gen.go index 0641c073ead..f7eecb576d6 100644 --- a/src/crypto/x509/root_ios_gen.go +++ b/src/crypto/x509/root_ios_gen.go @@ -124,7 +124,11 @@ func main() { if strings.ToLower(certName(certs[i])) != strings.ToLower(certName(certs[j])) { return strings.ToLower(certName(certs[i])) < strings.ToLower(certName(certs[j])) } - return certs[i].NotBefore.Before(certs[j].NotBefore) + if !certs[i].NotBefore.Equal(certs[j].NotBefore) { + return certs[i].NotBefore.Before(certs[j].NotBefore) + } + fi, fj := sha256.Sum256(certs[i].Raw), sha256.Sum256(certs[j].Raw) + return bytes.Compare(fi[:], fj[:]) < 0 }) out := new(bytes.Buffer) From cb4df9833474d36c6e4cb005682215047b5f0979 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Sun, 18 Oct 2020 17:02:06 +0000 Subject: [PATCH 392/403] cmd/go: add /v2 to another require example This is the same change as in CL 144917, but applied to a nearby line. For #28374. Change-Id: I6e1693d3a14e2517d863d1052a06c1156fc1edd4 Reviewed-on: https://go-review.googlesource.com/c/go/+/263437 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/alldocs.go | 2 +- src/cmd/go/internal/modload/help.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 583ae9e92ef..6e0d8337bfb 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1976,7 +1976,7 @@ // like in Go imports: // // require ( -// new/thing v2.3.4 +// new/thing/v2 v2.3.4 // old/thing v1.2.3 // ) // diff --git a/src/cmd/go/internal/modload/help.go b/src/cmd/go/internal/modload/help.go index 56920c28b99..0d2dd28e5f3 100644 --- a/src/cmd/go/internal/modload/help.go +++ b/src/cmd/go/internal/modload/help.go @@ -439,7 +439,7 @@ The leading verb can be factored out of adjacent lines to create a block, like in Go imports: require ( - new/thing v2.3.4 + new/thing/v2 v2.3.4 old/thing v1.2.3 ) From 979e1376096a4c1c7525f33dd4e76414f63c93fb Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 29 Oct 2020 10:57:38 -0400 Subject: [PATCH 393/403] cmd/go: add GOVCS setting to control version control usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The go command runs commands like git and hg to download modules. In the past, we have had problems with security bugs in version control systems becoming security bugs in “go get”. The original modules draft design removed use of these commands entirely, saying: > We want to move away from invoking version control tools such as bzr, > fossil, git, hg, and svn to download source code. These fragment the > ecosystem: packages developed using Bazaar or Fossil, for example, are > effectively unavailable to users who cannot or choose not to install > these tools. The version control tools have also been a source of > exciting security problems. It would be good to move them outside the > security perimeter. The removal of these commands was not possible in the end: being able to fetch directly from Git repos is too important, especially for closed source. But the security exposure has not gone away. We remain vulnerable to problems in VCS systems, especially the less scrutinized ones. This change adds a GOVCS setting to let users control which version control systems are allowed by default. It also changes the default allowed version control systems to git and hg for public code and any version control system for private code (import path or module path matched by the GOPRIVATE setting). See the changes in alldocs.go for detailed documentation. See #41730 for proposal and discussion. Fixes #41730. [Replay of CL 266420. See changes from Patch Set 1 for updates to fix a few long tests.] Change-Id: I4fe93804548956c42aea985368b4571bdb220f48 Reviewed-on: https://go-review.googlesource.com/c/go/+/267888 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Dmitri Shuralyov --- src/cmd/go/alldocs.go | 177 +++++++++++++++++------- src/cmd/go/go_test.go | 8 ++ src/cmd/go/internal/cfg/cfg.go | 1 + src/cmd/go/internal/envcmd/env.go | 1 + src/cmd/go/internal/help/helpdoc.go | 2 +- src/cmd/go/internal/modfetch/fetch.go | 13 +- src/cmd/go/internal/modget/get.go | 76 ++++++++++ src/cmd/go/internal/modload/help.go | 2 +- src/cmd/go/internal/vcs/vcs.go | 144 +++++++++++++++++++ src/cmd/go/internal/vcs/vcs_test.go | 104 ++++++++++++++ src/cmd/go/main.go | 3 +- src/cmd/go/script_test.go | 1 + src/cmd/go/testdata/script/govcs.txt | 174 +++++++++++++++++++++++ src/cmd/go/testdata/script/mod_auth.txt | 1 + src/internal/cfg/cfg.go | 1 + 15 files changed, 652 insertions(+), 56 deletions(-) create mode 100644 src/cmd/go/testdata/script/govcs.txt diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 6e0d8337bfb..e68fa55d09b 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -49,10 +49,11 @@ // modules modules, module versions, and more // module-get module-aware go get // module-auth module authentication using go.sum -// module-private module configuration for non-public modules // packages package lists and patterns +// private configuration for downloading non-public code // testflag testing flags // testfunc testing functions +// vcs controlling version control with GOVCS // // Use "go help " for more information about that topic. // @@ -1799,7 +1800,7 @@ // Comma-separated list of glob patterns (in the syntax of Go's path.Match) // of module path prefixes that should always be fetched directly // or that should not be compared against the checksum database. -// See 'go help module-private'. +// See 'go help private'. // GOROOT // The root of the go tree. // GOSUMDB @@ -2869,7 +2870,7 @@ // followed by a pipe character, indicating it is safe to fall back on any error. // // The GOPRIVATE and GONOPROXY environment variables allow bypassing -// the proxy for selected modules. See 'go help module-private' for details. +// the proxy for selected modules. See 'go help private' for details. // // No matter the source of the modules, the go command checks downloads against // known checksums, to detect unexpected changes in the content of any specific @@ -2989,52 +2990,7 @@ // accepted, at the cost of giving up the security guarantee of verified repeatable // downloads for all modules. A better way to bypass the checksum database // for specific modules is to use the GOPRIVATE or GONOSUMDB environment -// variables. See 'go help module-private' for details. -// -// The 'go env -w' command (see 'go help env') can be used to set these variables -// for future go command invocations. -// -// -// Module configuration for non-public modules -// -// The go command defaults to downloading modules from the public Go module -// mirror at proxy.golang.org. It also defaults to validating downloaded modules, -// regardless of source, against the public Go checksum database at sum.golang.org. -// These defaults work well for publicly available source code. -// -// The GOPRIVATE environment variable controls which modules the go command -// considers to be private (not available publicly) and should therefore not use the -// proxy or checksum database. The variable is a comma-separated list of -// glob patterns (in the syntax of Go's path.Match) of module path prefixes. -// For example, -// -// GOPRIVATE=*.corp.example.com,rsc.io/private -// -// causes the go command to treat as private any module with a path prefix -// matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, -// and rsc.io/private/quux. -// -// The GOPRIVATE environment variable may be used by other tools as well to -// identify non-public modules. For example, an editor could use GOPRIVATE -// to decide whether to hyperlink a package import to a godoc.org page. -// -// For fine-grained control over module download and validation, the GONOPROXY -// and GONOSUMDB environment variables accept the same kind of glob list -// and override GOPRIVATE for the specific decision of whether to use the proxy -// and checksum database, respectively. -// -// For example, if a company ran a module proxy serving private modules, -// users would configure go using: -// -// GOPRIVATE=*.corp.example.com -// GOPROXY=proxy.example.com -// GONOPROXY=none -// -// This would tell the go command and other tools that modules beginning with -// a corp.example.com subdomain are private but that the company proxy should -// be used for downloading both public and private modules, because -// GONOPROXY has been set to a pattern that won't match any modules, -// overriding GOPRIVATE. +// variables. See 'go help private' for details. // // The 'go env -w' command (see 'go help env') can be used to set these variables // for future go command invocations. @@ -3124,6 +3080,56 @@ // by the go tool, as are directories named "testdata". // // +// Configuration for downloading non-public code +// +// The go command defaults to downloading modules from the public Go module +// mirror at proxy.golang.org. It also defaults to validating downloaded modules, +// regardless of source, against the public Go checksum database at sum.golang.org. +// These defaults work well for publicly available source code. +// +// The GOPRIVATE environment variable controls which modules the go command +// considers to be private (not available publicly) and should therefore not use the +// proxy or checksum database. The variable is a comma-separated list of +// glob patterns (in the syntax of Go's path.Match) of module path prefixes. +// For example, +// +// GOPRIVATE=*.corp.example.com,rsc.io/private +// +// causes the go command to treat as private any module with a path prefix +// matching either pattern, including git.corp.example.com/xyzzy, rsc.io/private, +// and rsc.io/private/quux. +// +// The GOPRIVATE environment variable may be used by other tools as well to +// identify non-public modules. For example, an editor could use GOPRIVATE +// to decide whether to hyperlink a package import to a godoc.org page. +// +// For fine-grained control over module download and validation, the GONOPROXY +// and GONOSUMDB environment variables accept the same kind of glob list +// and override GOPRIVATE for the specific decision of whether to use the proxy +// and checksum database, respectively. +// +// For example, if a company ran a module proxy serving private modules, +// users would configure go using: +// +// GOPRIVATE=*.corp.example.com +// GOPROXY=proxy.example.com +// GONOPROXY=none +// +// This would tell the go command and other tools that modules beginning with +// a corp.example.com subdomain are private but that the company proxy should +// be used for downloading both public and private modules, because +// GONOPROXY has been set to a pattern that won't match any modules, +// overriding GOPRIVATE. +// +// The GOPRIVATE variable is also used to define the "public" and "private" +// patterns for the GOVCS variable; see 'go help vcs'. For that usage, +// GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths +// instead of module paths. +// +// The 'go env -w' command (see 'go help env') can be used to set these variables +// for future go command invocations. +// +// // Testing flags // // The 'go test' command takes both flags that apply to 'go test' itself @@ -3416,4 +3422,77 @@ // See the documentation of the testing package for more information. // // +// Controlling version control with GOVCS +// +// The 'go get' command can run version control commands like git +// to download imported code. This functionality is critical to the decentralized +// Go package ecosystem, in which code can be imported from any server, +// but it is also a potential security problem, if a malicious server finds a +// way to cause the invoked version control command to run unintended code. +// +// To balance the functionality and security concerns, the 'go get' command +// by default will only use git and hg to download code from public servers. +// But it will use any known version control system (bzr, fossil, git, hg, svn) +// to download code from private servers, defined as those hosting packages +// matching the GOPRIVATE variable (see 'go help private'). The rationale behind +// allowing only Git and Mercurial is that these two systems have had the most +// attention to issues of being run as clients of untrusted servers. In contrast, +// Bazaar, Fossil, and Subversion have primarily been used in trusted, +// authenticated environments and are not as well scrutinized as attack surfaces. +// +// The version control command restrictions only apply when using direct version +// control access to download code. When downloading modules from a proxy, +// 'go get' uses the proxy protocol instead, which is always permitted. +// By default, the 'go get' command uses the Go module mirror (proxy.golang.org) +// for public packages and only falls back to version control for private +// packages or when the mirror refuses to serve a public package (typically for +// legal reasons). Therefore, clients can still access public code served from +// Bazaar, Fossil, or Subversion repositories by default, because those downloads +// use the Go module mirror, which takes on the security risk of running the +// version control commands, using a custom sandbox. +// +// The GOVCS variable can be used to change the allowed version control systems +// for specific packages (identified by a module or import path). +// The GOVCS variable applies both when using modules and when using GOPATH. +// When using modules, the patterns match against the module path. +// When using GOPATH, the patterns match against the import path +// corresponding to the root of the version control repository. +// +// The general form of the GOVCS setting is a comma-separated list of +// pattern:vcslist rules. The pattern is a glob pattern that must match +// one or more leading elements of the module or import path. The vcslist +// is a pipe-separated list of allowed version control commands, or "all" +// to allow use of any known command, or "off" to allow nothing. +// The earliest matching pattern in the list applies, even if later patterns +// might also match. +// +// For example, consider: +// +// GOVCS=github.com:git,evil.com:off,*:git|hg +// +// With this setting, code with an module or import path beginning with +// github.com/ can only use git; paths on evil.com cannot use any version +// control command, and all other paths (* matches everything) can use +// only git or hg. +// +// The special patterns "public" and "private" match public and private +// module or import paths. A path is private if it matches the GOPRIVATE +// variable; otherwise it is public. +// +// If no rules in the GOVCS variable match a particular module or import path, +// the 'go get' command applies its default rule, which can now be summarized +// in GOVCS notation as 'public:git|hg,private:all'. +// +// To allow unfettered use of any version control system for any package, use: +// +// GOVCS=*:all +// +// To disable all use of version control, use: +// +// GOVCS=*:off +// +// The 'go env -w' command (see 'go help env') can be used to set the GOVCS +// variable for future go command invocations. +// +// package main diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 91d5884036d..ee0cd8e2c72 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -35,6 +35,14 @@ import ( "cmd/internal/sys" ) +func init() { + // GOVCS defaults to public:git|hg,private:all, + // which breaks many tests here - they can't use non-git, non-hg VCS at all! + // Change to fully permissive. + // The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt. + os.Setenv("GOVCS", "*:all") +} + var ( canRace = false // whether we can run the race detector canCgo = false // whether we can use cgo diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index 67d581f6e6d..9bc48132ae2 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -268,6 +268,7 @@ var ( GONOPROXY = envOr("GONOPROXY", GOPRIVATE) GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE) GOINSECURE = Getenv("GOINSECURE") + GOVCS = Getenv("GOVCS") ) var SumdbDir = gopathDir("pkg/sumdb") diff --git a/src/cmd/go/internal/envcmd/env.go b/src/cmd/go/internal/envcmd/env.go index 557e4189213..d65ace879db 100644 --- a/src/cmd/go/internal/envcmd/env.go +++ b/src/cmd/go/internal/envcmd/env.go @@ -87,6 +87,7 @@ func MkEnv() []cfg.EnvVar { {Name: "GOSUMDB", Value: cfg.GOSUMDB}, {Name: "GOTMPDIR", Value: cfg.Getenv("GOTMPDIR")}, {Name: "GOTOOLDIR", Value: base.ToolDir}, + {Name: "GOVCS", Value: cfg.GOVCS}, } if work.GccgoBin != "" { diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 8dfabbaa4a0..50cf911407e 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -526,7 +526,7 @@ General-purpose environment variables: Comma-separated list of glob patterns (in the syntax of Go's path.Match) of module path prefixes that should always be fetched directly or that should not be compared against the checksum database. - See 'go help module-private'. + See 'go help private'. GOROOT The root of the go tree. GOSUMDB diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index 25e9fb62c13..a3e2cd1f9d6 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -848,16 +848,16 @@ the checksum database is not consulted, and all unrecognized modules are accepted, at the cost of giving up the security guarantee of verified repeatable downloads for all modules. A better way to bypass the checksum database for specific modules is to use the GOPRIVATE or GONOSUMDB environment -variables. See 'go help module-private' for details. +variables. See 'go help private' for details. The 'go env -w' command (see 'go help env') can be used to set these variables for future go command invocations. `, } -var HelpModulePrivate = &base.Command{ - UsageLine: "module-private", - Short: "module configuration for non-public modules", +var HelpPrivate = &base.Command{ + UsageLine: "private", + Short: "configuration for downloading non-public code", Long: ` The go command defaults to downloading modules from the public Go module mirror at proxy.golang.org. It also defaults to validating downloaded modules, @@ -898,6 +898,11 @@ be used for downloading both public and private modules, because GONOPROXY has been set to a pattern that won't match any modules, overriding GOPRIVATE. +The GOPRIVATE variable is also used to define the "public" and "private" +patterns for the GOVCS variable; see 'go help vcs'. For that usage, +GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths +instead of module paths. + The 'go env -w' command (see 'go help env') can be used to set these variables for future go command invocations. `, diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index f7598884365..6ab242944ac 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -195,6 +195,82 @@ Usage: ` + CmdGet.UsageLine + ` ` + CmdGet.Long, } +var HelpVCS = &base.Command{ + UsageLine: "vcs", + Short: "controlling version control with GOVCS", + Long: ` +The 'go get' command can run version control commands like git +to download imported code. This functionality is critical to the decentralized +Go package ecosystem, in which code can be imported from any server, +but it is also a potential security problem, if a malicious server finds a +way to cause the invoked version control command to run unintended code. + +To balance the functionality and security concerns, the 'go get' command +by default will only use git and hg to download code from public servers. +But it will use any known version control system (bzr, fossil, git, hg, svn) +to download code from private servers, defined as those hosting packages +matching the GOPRIVATE variable (see 'go help private'). The rationale behind +allowing only Git and Mercurial is that these two systems have had the most +attention to issues of being run as clients of untrusted servers. In contrast, +Bazaar, Fossil, and Subversion have primarily been used in trusted, +authenticated environments and are not as well scrutinized as attack surfaces. + +The version control command restrictions only apply when using direct version +control access to download code. When downloading modules from a proxy, +'go get' uses the proxy protocol instead, which is always permitted. +By default, the 'go get' command uses the Go module mirror (proxy.golang.org) +for public packages and only falls back to version control for private +packages or when the mirror refuses to serve a public package (typically for +legal reasons). Therefore, clients can still access public code served from +Bazaar, Fossil, or Subversion repositories by default, because those downloads +use the Go module mirror, which takes on the security risk of running the +version control commands, using a custom sandbox. + +The GOVCS variable can be used to change the allowed version control systems +for specific packages (identified by a module or import path). +The GOVCS variable applies both when using modules and when using GOPATH. +When using modules, the patterns match against the module path. +When using GOPATH, the patterns match against the import path +corresponding to the root of the version control repository. + +The general form of the GOVCS setting is a comma-separated list of +pattern:vcslist rules. The pattern is a glob pattern that must match +one or more leading elements of the module or import path. The vcslist +is a pipe-separated list of allowed version control commands, or "all" +to allow use of any known command, or "off" to allow nothing. +The earliest matching pattern in the list applies, even if later patterns +might also match. + +For example, consider: + + GOVCS=github.com:git,evil.com:off,*:git|hg + +With this setting, code with an module or import path beginning with +github.com/ can only use git; paths on evil.com cannot use any version +control command, and all other paths (* matches everything) can use +only git or hg. + +The special patterns "public" and "private" match public and private +module or import paths. A path is private if it matches the GOPRIVATE +variable; otherwise it is public. + +If no rules in the GOVCS variable match a particular module or import path, +the 'go get' command applies its default rule, which can now be summarized +in GOVCS notation as 'public:git|hg,private:all'. + +To allow unfettered use of any version control system for any package, use: + + GOVCS=*:all + +To disable all use of version control, use: + + GOVCS=*:off + +The 'go env -w' command (see 'go help env') can be used to set the GOVCS +variable for future go command invocations. +`, +} + var ( getD = CmdGet.Flag.Bool("d", false, "") getF = CmdGet.Flag.Bool("f", false, "") diff --git a/src/cmd/go/internal/modload/help.go b/src/cmd/go/internal/modload/help.go index 0d2dd28e5f3..d81dfd56fb5 100644 --- a/src/cmd/go/internal/modload/help.go +++ b/src/cmd/go/internal/modload/help.go @@ -365,7 +365,7 @@ list if the error is a 404 or 410 HTTP response or if the current proxy is followed by a pipe character, indicating it is safe to fall back on any error. The GOPRIVATE and GONOPROXY environment variables allow bypassing -the proxy for selected modules. See 'go help module-private' for details. +the proxy for selected modules. See 'go help private' for details. No matter the source of the modules, the go command checks downloads against known checksums, to detect unexpected changes in the content of any specific diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index 7812afd4888..e7bef9f591a 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -22,7 +22,10 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" + "cmd/go/internal/search" "cmd/go/internal/web" + + "golang.org/x/mod/module" ) // A vcsCmd describes how to use a version control system @@ -591,12 +594,146 @@ func FromDir(dir, srcRoot string) (vcs *Cmd, root string, err error) { } if vcsRet != nil { + if err := checkGOVCS(vcsRet, rootRet); err != nil { + return nil, "", err + } return vcsRet, rootRet, nil } return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir) } +// A govcsRule is a single GOVCS rule like private:hg|svn. +type govcsRule struct { + pattern string + allowed []string +} + +// A govcsConfig is a full GOVCS configuration. +type govcsConfig []govcsRule + +func parseGOVCS(s string) (govcsConfig, error) { + s = strings.TrimSpace(s) + if s == "" { + return nil, nil + } + var cfg govcsConfig + have := make(map[string]string) + for _, item := range strings.Split(s, ",") { + item = strings.TrimSpace(item) + if item == "" { + return nil, fmt.Errorf("empty entry in GOVCS") + } + i := strings.Index(item, ":") + if i < 0 { + return nil, fmt.Errorf("malformed entry in GOVCS (missing colon): %q", item) + } + pattern, list := strings.TrimSpace(item[:i]), strings.TrimSpace(item[i+1:]) + if pattern == "" { + return nil, fmt.Errorf("empty pattern in GOVCS: %q", item) + } + if list == "" { + return nil, fmt.Errorf("empty VCS list in GOVCS: %q", item) + } + if search.IsRelativePath(pattern) { + return nil, fmt.Errorf("relative pattern not allowed in GOVCS: %q", pattern) + } + if old := have[pattern]; old != "" { + return nil, fmt.Errorf("unreachable pattern in GOVCS: %q after %q", item, old) + } + have[pattern] = item + allowed := strings.Split(list, "|") + for i, a := range allowed { + a = strings.TrimSpace(a) + if a == "" { + return nil, fmt.Errorf("empty VCS name in GOVCS: %q", item) + } + allowed[i] = a + } + cfg = append(cfg, govcsRule{pattern, allowed}) + } + return cfg, nil +} + +func (c *govcsConfig) allow(path string, private bool, vcs string) bool { + for _, rule := range *c { + match := false + switch rule.pattern { + case "private": + match = private + case "public": + match = !private + default: + // Note: rule.pattern is known to be comma-free, + // so MatchPrefixPatterns is only matching a single pattern for us. + match = module.MatchPrefixPatterns(rule.pattern, path) + } + if !match { + continue + } + for _, allow := range rule.allowed { + if allow == vcs || allow == "all" { + return true + } + } + return false + } + + // By default, nothing is allowed. + return false +} + +var ( + govcs govcsConfig + govcsErr error + govcsOnce sync.Once +) + +// defaultGOVCS is the default setting for GOVCS. +// Setting GOVCS adds entries ahead of these but does not remove them. +// (They are appended to the parsed GOVCS setting.) +// +// The rationale behind allowing only Git and Mercurial is that +// these two systems have had the most attention to issues +// of being run as clients of untrusted servers. In contrast, +// Bazaar, Fossil, and Subversion have primarily been used +// in trusted, authenticated environments and are not as well +// scrutinized as attack surfaces. +// +// See golang.org/issue/41730 for details. +var defaultGOVCS = govcsConfig{ + {"private", []string{"all"}}, + {"public", []string{"git", "hg"}}, +} + +func checkGOVCS(vcs *Cmd, root string) error { + if vcs == vcsMod { + // Direct module (proxy protocol) fetches don't + // involve an external version control system + // and are always allowed. + return nil + } + + govcsOnce.Do(func() { + govcs, govcsErr = parseGOVCS(os.Getenv("GOVCS")) + govcs = append(govcs, defaultGOVCS...) + }) + if govcsErr != nil { + return govcsErr + } + + private := module.MatchPrefixPatterns(cfg.GOPRIVATE, root) + if !govcs.allow(root, private, vcs.Cmd) { + what := "public" + if private { + what = "private" + } + return fmt.Errorf("GOVCS disallows using %s for %s %s", vcs.Cmd, what, root) + } + + return nil +} + // CheckNested checks for an incorrectly-nested VCS-inside-VCS // situation for dir, checking parents up until srcRoot. func CheckNested(vcs *Cmd, dir, srcRoot string) error { @@ -733,6 +870,9 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths if vcs == nil { return nil, fmt.Errorf("unknown version control system %q", match["vcs"]) } + if err := checkGOVCS(vcs, match["root"]); err != nil { + return nil, err + } var repoURL string if !srv.schemelessRepo { repoURL = match["repo"] @@ -857,6 +997,10 @@ func repoRootForImportDynamic(importPath string, mod ModuleMode, security web.Se } } + if err := checkGOVCS(vcs, mmi.Prefix); err != nil { + return nil, err + } + rr := &RepoRoot{ Repo: mmi.RepoRoot, Root: mmi.Prefix, diff --git a/src/cmd/go/internal/vcs/vcs_test.go b/src/cmd/go/internal/vcs/vcs_test.go index 5b874204f1e..72d74a01e30 100644 --- a/src/cmd/go/internal/vcs/vcs_test.go +++ b/src/cmd/go/internal/vcs/vcs_test.go @@ -11,11 +11,20 @@ import ( "os" "path" "path/filepath" + "strings" "testing" "cmd/go/internal/web" ) +func init() { + // GOVCS defaults to public:git|hg,private:all, + // which breaks many tests here - they can't use non-git, non-hg VCS at all! + // Change to fully permissive. + // The tests of the GOVCS setting itself are in ../../testdata/script/govcs.txt. + os.Setenv("GOVCS", "*:all") +} + // Test that RepoRootForImportPath determines the correct RepoRoot for a given importPath. // TODO(cmang): Add tests for SVN and BZR. func TestRepoRootForImportPath(t *testing.T) { @@ -473,3 +482,98 @@ func TestValidateRepoRoot(t *testing.T) { } } } + +var govcsTests = []struct { + govcs string + path string + vcs string + ok bool +}{ + {"private:all", "is-public.com/foo", "zzz", false}, + {"private:all", "is-private.com/foo", "zzz", true}, + {"public:all", "is-public.com/foo", "zzz", true}, + {"public:all", "is-private.com/foo", "zzz", false}, + {"public:all,private:none", "is-public.com/foo", "zzz", true}, + {"public:all,private:none", "is-private.com/foo", "zzz", false}, + {"*:all", "is-public.com/foo", "zzz", true}, + {"golang.org:git", "golang.org/x/text", "zzz", false}, + {"golang.org:git", "golang.org/x/text", "git", true}, + {"golang.org:zzz", "golang.org/x/text", "zzz", true}, + {"golang.org:zzz", "golang.org/x/text", "git", false}, + {"golang.org:zzz", "golang.org/x/text", "zzz", true}, + {"golang.org:zzz", "golang.org/x/text", "git", false}, + {"golang.org:git|hg", "golang.org/x/text", "hg", true}, + {"golang.org:git|hg", "golang.org/x/text", "git", true}, + {"golang.org:git|hg", "golang.org/x/text", "zzz", false}, + {"golang.org:all", "golang.org/x/text", "hg", true}, + {"golang.org:all", "golang.org/x/text", "git", true}, + {"golang.org:all", "golang.org/x/text", "zzz", true}, + {"other.xyz/p:none,golang.org/x:git", "other.xyz/p/x", "git", false}, + {"other.xyz/p:none,golang.org/x:git", "unexpected.com", "git", false}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/x/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/x/text", "git", true}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/x/text", "zzz", true}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/x/text", "git", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "hg", true}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "git", true}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/x/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "hg", true}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "git", true}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/x/text", "zzz", true}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/y/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:git", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/y/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:zzz", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "hg", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:git|hg", "golang.org/y/text", "zzz", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "hg", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "git", false}, + {"other.xyz/p:none,golang.org/x:all", "golang.org/y/text", "zzz", false}, +} + +func TestGOVCS(t *testing.T) { + for _, tt := range govcsTests { + cfg, err := parseGOVCS(tt.govcs) + if err != nil { + t.Errorf("parseGOVCS(%q): %v", tt.govcs, err) + continue + } + private := strings.HasPrefix(tt.path, "is-private") + ok := cfg.allow(tt.path, private, tt.vcs) + if ok != tt.ok { + t.Errorf("parseGOVCS(%q).allow(%q, %v, %q) = %v, want %v", + tt.govcs, tt.path, private, tt.vcs, ok, tt.ok) + } + } +} + +var govcsErrors = []struct { + s string + err string +}{ + {`,`, `empty entry in GOVCS`}, + {`,x`, `empty entry in GOVCS`}, + {`x,`, `malformed entry in GOVCS (missing colon): "x"`}, + {`x:y,`, `empty entry in GOVCS`}, + {`x`, `malformed entry in GOVCS (missing colon): "x"`}, + {`x:`, `empty VCS list in GOVCS: "x:"`}, + {`x:|`, `empty VCS name in GOVCS: "x:|"`}, + {`x:y|`, `empty VCS name in GOVCS: "x:y|"`}, + {`x:|y`, `empty VCS name in GOVCS: "x:|y"`}, + {`x:y,z:`, `empty VCS list in GOVCS: "z:"`}, + {`x:y,z:|`, `empty VCS name in GOVCS: "z:|"`}, + {`x:y,z:|w`, `empty VCS name in GOVCS: "z:|w"`}, + {`x:y,z:w|`, `empty VCS name in GOVCS: "z:w|"`}, + {`x:y,z:w||v`, `empty VCS name in GOVCS: "z:w||v"`}, + {`x:y,x:z`, `unreachable pattern in GOVCS: "x:z" after "x:y"`}, +} + +func TestGOVCSErrors(t *testing.T) { + for _, tt := range govcsErrors { + _, err := parseGOVCS(tt.s) + if err == nil || !strings.Contains(err.Error(), tt.err) { + t.Errorf("parseGOVCS(%s): err=%v, want %v", tt.s, err, tt.err) + } + } +} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index 37bb7d6d270..9cc44da84db 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -75,10 +75,11 @@ func init() { modload.HelpModules, modget.HelpModuleGet, modfetch.HelpModuleAuth, - modfetch.HelpModulePrivate, help.HelpPackages, + modfetch.HelpPrivate, test.HelpTestflag, test.HelpTestfunc, + modget.HelpVCS, } } diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index e301f2fb069..b1d1499038f 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -135,6 +135,7 @@ func (ts *testScript) setup() { "GOSUMDB=" + testSumDBVerifierKey, "GONOPROXY=", "GONOSUMDB=", + "GOVCS=*:all", "PWD=" + ts.cd, tempEnvName() + "=" + filepath.Join(ts.workdir, "tmp"), "devnull=" + os.DevNull, diff --git a/src/cmd/go/testdata/script/govcs.txt b/src/cmd/go/testdata/script/govcs.txt new file mode 100644 index 00000000000..35f092ee493 --- /dev/null +++ b/src/cmd/go/testdata/script/govcs.txt @@ -0,0 +1,174 @@ +env GO111MODULE=on +env proxy=$GOPROXY +env GOPROXY=direct + +# GOVCS stops go get +env GOVCS='*:none' +! go get github.com/google/go-cmp +stderr 'go get: GOVCS disallows using git for public github.com/google/go-cmp' +env GOPRIVATE='github.com/google' +! go get github.com/google/go-cmp +stderr 'go get: GOVCS disallows using git for private github.com/google/go-cmp' + +# public pattern works +env GOPRIVATE='github.com/google' +env GOVCS='public:all,private:none' +! go get github.com/google/go-cmp +stderr 'go get: GOVCS disallows using git for private github.com/google/go-cmp' + +# private pattern works +env GOPRIVATE='hubgit.com/google' +env GOVCS='private:all,public:none' +! go get github.com/google/go-cmp +stderr 'go get: GOVCS disallows using git for public github.com/google/go-cmp' + +# other patterns work (for more patterns, see TestGOVCS) +env GOPRIVATE= +env GOVCS='github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'go get: GOVCS disallows using git for public github.com/google/go-cmp' +env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'go get: GOVCS disallows using git for public github.com/google/go-cmp' + +# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) +env GOVCS='git' +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"' + +env GOVCS=github.com:hg,github.com:git +! go get github.com/google/go-cmp +stderr 'go get github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"' + +# bad GOVCS patterns do not stop commands that do not need to check VCS +go list +env GOPROXY=$proxy +go get -d rsc.io/quote # ok because used proxy +env GOPROXY=direct + +# svn is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.svn/hello +stderr 'go get rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn' + +# fossil is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.fossil/hello +stderr 'go get rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil' + +# bzr is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.bzr/hello +stderr 'go get rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr' + +# git is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:git] [!short] go get rsc.io/sampler + +# hg is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello + +# git can be disallowed +env GOVCS=public:hg +! go get rsc.io/nonexist.git/hello +stderr 'go get rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git' + +# hg can be disallowed +env GOVCS=public:git +! go get rsc.io/nonexist.hg/hello +stderr 'go get rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg' + +# Repeat in GOPATH mode. Error texts slightly different. + +env GO111MODULE=off + +# GOVCS stops go get +env GOVCS='*:none' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' +env GOPRIVATE='github.com/google' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' + +# public pattern works +env GOPRIVATE='github.com/google' +env GOVCS='public:all,private:none' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for private github.com/google/go-cmp' + +# private pattern works +env GOPRIVATE='hubgit.com/google' +env GOVCS='private:all,public:none' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' + +# other patterns work (for more patterns, see TestGOVCS) +env GOPRIVATE= +env GOVCS='github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' +env GOVCS='github.com/google/go-cmp/inner:git,github.com:svn|hg' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: GOVCS disallows using git for public github.com/google/go-cmp' + +# bad patterns are reported (for more bad patterns, see TestGOVCSErrors) +env GOVCS='git' +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: malformed entry in GOVCS \(missing colon\): "git"' + +env GOVCS=github.com:hg,github.com:git +! go get github.com/google/go-cmp +stderr 'package github.com/google/go-cmp: unreachable pattern in GOVCS: "github.com:git" after "github.com:hg"' + +# bad GOVCS patterns do not stop commands that do not need to check VCS +go list + +# svn is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.svn/hello +stderr 'package rsc.io/nonexist.svn/hello: GOVCS disallows using svn for public rsc.io/nonexist.svn' + +# fossil is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.fossil/hello +stderr 'package rsc.io/nonexist.fossil/hello: GOVCS disallows using fossil for public rsc.io/nonexist.fossil' + +# bzr is disallowed by default +env GOPRIVATE= +env GOVCS= +! go get rsc.io/nonexist.bzr/hello +stderr 'package rsc.io/nonexist.bzr/hello: GOVCS disallows using bzr for public rsc.io/nonexist.bzr' + +# git is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:git] [!short] go get rsc.io/sampler + +# hg is OK by default +env GOVCS= +env GONOSUMDB='*' +[net] [exec:hg] [!short] go get vcs-test.golang.org/go/custom-hg-hello + +# git can be disallowed +env GOVCS=public:hg +! go get rsc.io/nonexist.git/hello +stderr 'package rsc.io/nonexist.git/hello: GOVCS disallows using git for public rsc.io/nonexist.git' + +# hg can be disallowed +env GOVCS=public:git +! go get rsc.io/nonexist.hg/hello +stderr 'package rsc.io/nonexist.hg/hello: GOVCS disallows using hg for public rsc.io/nonexist.hg' + +-- go.mod -- +module m + +-- p.go -- +package p diff --git a/src/cmd/go/testdata/script/mod_auth.txt b/src/cmd/go/testdata/script/mod_auth.txt index 544acbc1f86..d8ea5867d6b 100644 --- a/src/cmd/go/testdata/script/mod_auth.txt +++ b/src/cmd/go/testdata/script/mod_auth.txt @@ -3,6 +3,7 @@ env GO111MODULE=on env GOPROXY=direct env GOSUMDB=off +env GOVCS='*:off' # Without credentials, downloading a module from a path that requires HTTPS # basic auth should fail. diff --git a/src/internal/cfg/cfg.go b/src/internal/cfg/cfg.go index bdbe9df3e75..553021374d5 100644 --- a/src/internal/cfg/cfg.go +++ b/src/internal/cfg/cfg.go @@ -58,6 +58,7 @@ const KnownEnv = ` GOSUMDB GOTMPDIR GOTOOLDIR + GOVCS GOWASM GO_EXTLINK_ENABLED PKG_CONFIG From a444458112e4059e73c9a5a2bc5867f53bf9faa2 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Fri, 6 Nov 2020 22:46:18 -0500 Subject: [PATCH 394/403] cmd/compile: make sure linkname'd symbol is non-package When a variable symbol is both imported (possibly through inlining) and linkname'd, make sure its LSym is marked as non-package for symbol indexing in the object file, so it is resolved by name and dedup'd with the original definition. Fixes #42401. Change-Id: I8e90c0418c6f46a048945c5fdc06c022b77ed68d Reviewed-on: https://go-review.googlesource.com/c/go/+/268178 Trust: Cherry Zhang Run-TryBot: Cherry Zhang TryBot-Result: Go Bot Reviewed-by: Than McIntosh Reviewed-by: Jeremy Faller --- src/cmd/compile/internal/gc/gsubr.go | 6 ++++++ test/fixedbugs/issue42401.dir/a.go | 11 +++++++++++ test/fixedbugs/issue42401.dir/b.go | 24 ++++++++++++++++++++++++ test/fixedbugs/issue42401.go | 10 ++++++++++ 4 files changed, 51 insertions(+) create mode 100644 test/fixedbugs/issue42401.dir/a.go create mode 100644 test/fixedbugs/issue42401.dir/b.go create mode 100644 test/fixedbugs/issue42401.go diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index 864ada1d3cd..d599a383e7b 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -302,6 +302,12 @@ func ggloblnod(nam *Node) { if nam.Name.LibfuzzerExtraCounter() { s.Type = objabi.SLIBFUZZER_EXTRA_COUNTER } + if nam.Sym.Linkname != "" { + // Make sure linkname'd symbol is non-package. When a symbol is + // both imported and linkname'd, s.Pkg may not set to "_" in + // types.Sym.Linksym because LSym already exists. Set it here. + s.Pkg = "_" + } } func ggloblsym(s *obj.LSym, width int32, flags int16) { diff --git a/test/fixedbugs/issue42401.dir/a.go b/test/fixedbugs/issue42401.dir/a.go new file mode 100644 index 00000000000..75f8e7f91fc --- /dev/null +++ b/test/fixedbugs/issue42401.dir/a.go @@ -0,0 +1,11 @@ +// Copyright 2020 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 a + +var s string + +func init() { s = "a" } + +func Get() string { return s } diff --git a/test/fixedbugs/issue42401.dir/b.go b/test/fixedbugs/issue42401.dir/b.go new file mode 100644 index 00000000000..a834f4efe8d --- /dev/null +++ b/test/fixedbugs/issue42401.dir/b.go @@ -0,0 +1,24 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "./a" + _ "unsafe" +) + +//go:linkname s a.s +var s string + +func main() { + if a.Get() != "a" { + panic("FAIL") + } + + s = "b" + if a.Get() != "b" { + panic("FAIL") + } +} diff --git a/test/fixedbugs/issue42401.go b/test/fixedbugs/issue42401.go new file mode 100644 index 00000000000..794d5b01b55 --- /dev/null +++ b/test/fixedbugs/issue42401.go @@ -0,0 +1,10 @@ +// rundir + +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 42401: linkname doesn't work correctly when a variable symbol +// is both imported (possibly through inlining) and linkname'd. + +package ignored From cfea52b04c18761f9cc3168eff00690155aa6d17 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Tue, 10 Nov 2020 03:42:18 +1100 Subject: [PATCH 395/403] runtime: disable TestCrashDumpsAllThreads on openbsd/mips64 This test fails consistently on openbsd/mips64 - disable it until we can investigate and resolve the issue. Updates #42464 Change-Id: Ie640f776823137a967a12817ff18953207f558a4 Reviewed-on: https://go-review.googlesource.com/c/go/+/268438 Trust: Joel Sing Reviewed-by: Cherry Zhang --- src/runtime/crash_unix_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index fc87f374088..6c42cb9a3df 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -70,6 +70,10 @@ func TestCrashDumpsAllThreads(t *testing.T) { t.Skipf("skipping; not supported on %v", runtime.GOOS) } + if runtime.GOOS == "openbsd" && runtime.GOARCH == "mips64" { + t.Skipf("skipping; test fails on %s/%s - see issue #42464", runtime.GOOS, runtime.GOARCH) + } + if runtime.Sigisblocked(int(syscall.SIGQUIT)) { t.Skip("skipping; SIGQUIT is blocked, see golang.org/issue/19196") } From 51f41688126afa1de7c4621777189bda17fd3090 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Sun, 10 May 2020 11:23:58 -0700 Subject: [PATCH 396/403] crypto/x509: add additional convenience fields to CertificateRequest Adds the following additional convenience fields to CertificateRequest: * KeyUsage * ExtKeyUsage * UnknownExtKeyUsage * IsCA * MaxPathLen * BasicConstraintsValid * MaxPathLenZero * SubjectKeyId * PolicyIdentifier These fields are parsed during ParseCertificateRequest and marshalled during CreateCertificateRequest. The parsing/marshalling code is factored out of parseCertificate and buildExtensions (which is renamed buildCertExtensions). This has the side effect of making these methods somewhat easier to read. Documentation for the fields is copied from Certificate. Example CSR created with all of these fields parsed with openssl: $ openssl req -in ~/test-csr.pem -noout -text Certificate Request: Data: Version: 0 (0x0) Subject: Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:a4:cb:64:35:8e:dd:8c:2b:a6:f1:aa:39:d1:be: d0:b9:95:1e:59:19:82:76:28:d3:85:1b:c6:88:62: e1:15:33:be:26:18:80:14:fe:f4:d4:91:66:4e:a4: a4:47:bd:53:db:f7:2e:e3:31:ce:5f:86:cb:92:59: 93:bb:d0:7f:a2 ASN1 OID: prime256v1 NIST CURVE: P-256 Attributes: Requested Extensions: X509v3 Key Usage: critical Certificate Sign X509v3 Extended Key Usage: Any Extended Key Usage, 1.2.3 X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Subject Key Identifier: 01:02:03 X509v3 Certificate Policies: Policy: 1.2.3 Signature Algorithm: ecdsa-with-SHA256 30:45:02:21:00:a7:88:e5:96:d4:ad:ae:24:26:ab:5f:15:6a: 3f:22:6d:0e:a6:ba:15:64:8d:78:34:f4:c4:7d:ac:37:b0:2a: 84:02:20:68:44:f0:8e:8a:1b:c1:68:be:14:a6:e3:83:41:fd: 2d:cc:00:aa:bc:50:f6:50:56:12:9e:a4:09:84:5c:bf:c1 Fixes #37172 Change-Id: Ife79d01e203827ef0ac3c787aa13c00d0751a1ec Reviewed-on: https://go-review.googlesource.com/c/go/+/233163 Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Filippo Valsorda Trust: Katie Hockman Trust: Roland Shoemaker --- src/crypto/x509/x509.go | 434 ++++++++++++++++++++++++----------- src/crypto/x509/x509_test.go | 43 ++++ 2 files changed, 349 insertions(+), 128 deletions(-) diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 537c207f38f..60dfac741b8 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -1338,36 +1338,17 @@ func parseCertificate(in *certificate) (*Certificate, error) { if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { switch e.Id[3] { case 15: - // RFC 5280, 4.2.1.3 - var usageBits asn1.BitString - if rest, err := asn1.Unmarshal(e.Value, &usageBits); err != nil { + out.KeyUsage, err = parseKeyUsageExtension(e.Value) + if err != nil { return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 KeyUsage") } - - var usage int - for i := 0; i < 9; i++ { - if usageBits.At(i) != 0 { - usage |= 1 << uint(i) - } - } - out.KeyUsage = KeyUsage(usage) - case 19: - // RFC 5280, 4.2.1.9 - var constraints basicConstraints - if rest, err := asn1.Unmarshal(e.Value, &constraints); err != nil { + out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value) + if err != nil { return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 BasicConstraints") } - out.BasicConstraintsValid = true - out.IsCA = constraints.IsCA - out.MaxPathLen = constraints.MaxPathLen out.MaxPathLenZero = out.MaxPathLen == 0 - // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285) case 17: out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value) if err != nil { @@ -1430,52 +1411,20 @@ func parseCertificate(in *certificate) (*Certificate, error) { out.AuthorityKeyId = a.Id case 37: - // RFC 5280, 4.2.1.12. Extended Key Usage - - // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } - // - // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId - // - // KeyPurposeId ::= OBJECT IDENTIFIER - - var keyUsage []asn1.ObjectIdentifier - if rest, err := asn1.Unmarshal(e.Value, &keyUsage); err != nil { + out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value) + if err != nil { return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 ExtendedKeyUsage") } - - for _, u := range keyUsage { - if extKeyUsage, ok := extKeyUsageFromOID(u); ok { - out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage) - } else { - out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u) - } - } - case 14: - // RFC 5280, 4.2.1.2 - var keyid []byte - if rest, err := asn1.Unmarshal(e.Value, &keyid); err != nil { + out.SubjectKeyId, err = parseSubjectKeyIdExtension(e.Value) + if err != nil { return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 key-id") } - out.SubjectKeyId = keyid - case 32: - // RFC 5280 4.2.1.4: Certificate Policies - var policies []policyInformation - if rest, err := asn1.Unmarshal(e.Value, &policies); err != nil { + out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(e.Value) + if err != nil { return nil, err - } else if len(rest) != 0 { - return nil, errors.New("x509: trailing data after X.509 certificate policies") } - out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies)) - for i, policy := range policies { - out.PolicyIdentifiers[i] = policy.Policy - } - default: // Unknown extensions are recorded if critical. unhandled = true @@ -1513,6 +1462,87 @@ func parseCertificate(in *certificate) (*Certificate, error) { return out, nil } +// parseKeyUsageExtension parses id-ce-keyUsage (2.5.29.15) from RFC 5280 +// Section 4.2.1.3 +func parseKeyUsageExtension(ext []byte) (KeyUsage, error) { + var usageBits asn1.BitString + if rest, err := asn1.Unmarshal(ext, &usageBits); err != nil { + return 0, err + } else if len(rest) != 0 { + return 0, errors.New("x509: trailing data after X.509 KeyUsage") + } + + var usage int + for i := 0; i < 9; i++ { + if usageBits.At(i) != 0 { + usage |= 1 << uint(i) + } + } + return KeyUsage(usage), nil +} + +// parseBasicConstraintsExtension parses id-ce-basicConstraints (2.5.29.19) +// from RFC 5280 Section 4.2.1.9 +func parseBasicConstraintsExtension(ext []byte) (isCA bool, maxPathLen int, err error) { + var constraints basicConstraints + if rest, err := asn1.Unmarshal(ext, &constraints); err != nil { + return false, 0, err + } else if len(rest) != 0 { + return false, 0, errors.New("x509: trailing data after X.509 BasicConstraints") + } + + // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285) + return constraints.IsCA, constraints.MaxPathLen, nil +} + +// parseExtKeyUsageExtension parses id-ce-extKeyUsage (2.5.29.37) from +// RFC 5280 Section 4.2.1.12 +func parseExtKeyUsageExtension(ext []byte) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) { + var keyUsage []asn1.ObjectIdentifier + if rest, err := asn1.Unmarshal(ext, &keyUsage); err != nil { + return nil, nil, err + } else if len(rest) != 0 { + return nil, nil, errors.New("x509: trailing data after X.509 ExtendedKeyUsage") + } + + var extKeyUsages []ExtKeyUsage + var unknownUsages []asn1.ObjectIdentifier + for _, u := range keyUsage { + if extKeyUsage, ok := extKeyUsageFromOID(u); ok { + extKeyUsages = append(extKeyUsages, extKeyUsage) + } else { + unknownUsages = append(unknownUsages, u) + } + } + return extKeyUsages, unknownUsages, nil +} + +// parseSubjectKeyIdExtension parses id-ce-subjectKeyIdentifier (2.5.29.14) +// from RFC 5280 Section 4.2.1.2 +func parseSubjectKeyIdExtension(ext []byte) ([]byte, error) { + var keyid []byte + if rest, err := asn1.Unmarshal(ext, &keyid); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after X.509 key-id") + } + return keyid, nil +} + +func parseCertificatePoliciesExtension(ext []byte) ([]asn1.ObjectIdentifier, error) { + var policies []policyInformation + if rest, err := asn1.Unmarshal(ext, &policies); err != nil { + return nil, err + } else if len(rest) != 0 { + return nil, errors.New("x509: trailing data after X.509 certificate policies") + } + oids := make([]asn1.ObjectIdentifier, len(policies)) + for i, policy := range policies { + oids[i] = policy.Policy + } + return oids, nil +} + // ParseCertificate parses a single certificate from the given ASN.1 DER data. func ParseCertificate(asn1Data []byte) (*Certificate, error) { var cert certificate @@ -1656,68 +1686,32 @@ func isIA5String(s string) error { return nil } -func buildExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId []byte, subjectKeyId []byte) (ret []pkix.Extension, err error) { +func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId []byte, subjectKeyId []byte) (ret []pkix.Extension, err error) { ret = make([]pkix.Extension, 10 /* maximum number of elements. */) n := 0 if template.KeyUsage != 0 && !oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) { - ret[n].Id = oidExtensionKeyUsage - ret[n].Critical = true - - var a [2]byte - a[0] = reverseBitsInAByte(byte(template.KeyUsage)) - a[1] = reverseBitsInAByte(byte(template.KeyUsage >> 8)) - - l := 1 - if a[1] != 0 { - l = 2 - } - - bitString := a[:l] - ret[n].Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)}) + ret[n], err = marshalKeyUsage(template.KeyUsage) if err != nil { - return + return nil, err } n++ } if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) && !oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) { - ret[n].Id = oidExtensionExtendedKeyUsage - - var oids []asn1.ObjectIdentifier - for _, u := range template.ExtKeyUsage { - if oid, ok := oidFromExtKeyUsage(u); ok { - oids = append(oids, oid) - } else { - err = errors.New("x509: unknown extended key usage") - return - } - } - - oids = append(oids, template.UnknownExtKeyUsage...) - - ret[n].Value, err = asn1.Marshal(oids) + ret[n], err = marshalExtKeyUsage(template.ExtKeyUsage, template.UnknownExtKeyUsage) if err != nil { - return + return nil, err } n++ } if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) { - // Leaving MaxPathLen as zero indicates that no maximum path - // length is desired, unless MaxPathLenZero is set. A value of - // -1 causes encoding/asn1 to omit the value as desired. - maxPathLen := template.MaxPathLen - if maxPathLen == 0 && !template.MaxPathLenZero { - maxPathLen = -1 - } - ret[n].Id = oidExtensionBasicConstraints - ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, maxPathLen}) - ret[n].Critical = true + ret[n], err = marshalBasicConstraints(template.IsCA, template.MaxPathLen, template.MaxPathLenZero) if err != nil { - return + return nil, err } n++ } @@ -1779,14 +1773,9 @@ func buildExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId if len(template.PolicyIdentifiers) > 0 && !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) { - ret[n].Id = oidExtensionCertificatePolicies - policies := make([]policyInformation, len(template.PolicyIdentifiers)) - for i, policy := range template.PolicyIdentifiers { - policies[i].Policy = policy - } - ret[n].Value, err = asn1.Marshal(policies) + ret[n], err = marshalCertificatePolicies(template.PolicyIdentifiers) if err != nil { - return + return nil, err } n++ } @@ -1919,6 +1908,141 @@ func buildExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId return append(ret[:n], template.ExtraExtensions...), nil } +func marshalKeyUsage(ku KeyUsage) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionKeyUsage, Critical: true} + + var a [2]byte + a[0] = reverseBitsInAByte(byte(ku)) + a[1] = reverseBitsInAByte(byte(ku >> 8)) + + l := 1 + if a[1] != 0 { + l = 2 + } + + bitString := a[:l] + var err error + ext.Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)}) + if err != nil { + return ext, err + } + return ext, nil +} + +func marshalExtKeyUsage(extUsages []ExtKeyUsage, unknownUsages []asn1.ObjectIdentifier) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionExtendedKeyUsage} + + oids := make([]asn1.ObjectIdentifier, len(extUsages)+len(unknownUsages)) + for i, u := range extUsages { + if oid, ok := oidFromExtKeyUsage(u); ok { + oids[i] = oid + } else { + return ext, errors.New("x509: unknown extended key usage") + } + } + + copy(oids[len(extUsages):], unknownUsages) + + var err error + ext.Value, err = asn1.Marshal(oids) + if err != nil { + return ext, err + } + return ext, nil +} + +func marshalBasicConstraints(isCA bool, maxPathLen int, maxPathLenZero bool) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionBasicConstraints, Critical: true} + // Leaving MaxPathLen as zero indicates that no maximum path + // length is desired, unless MaxPathLenZero is set. A value of + // -1 causes encoding/asn1 to omit the value as desired. + if maxPathLen == 0 && !maxPathLenZero { + maxPathLen = -1 + } + var err error + ext.Value, err = asn1.Marshal(basicConstraints{isCA, maxPathLen}) + if err != nil { + return ext, nil + } + return ext, nil +} + +func marshalCertificatePolicies(policyIdentifiers []asn1.ObjectIdentifier) (pkix.Extension, error) { + ext := pkix.Extension{Id: oidExtensionCertificatePolicies} + policies := make([]policyInformation, len(policyIdentifiers)) + for i, policy := range policyIdentifiers { + policies[i].Policy = policy + } + var err error + ext.Value, err = asn1.Marshal(policies) + if err != nil { + return ext, err + } + return ext, nil +} + +func buildCSRExtensions(template *CertificateRequest) ([]pkix.Extension, error) { + var ret []pkix.Extension + + if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) && + !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { + sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs) + if err != nil { + return nil, err + } + + ret = append(ret, pkix.Extension{ + Id: oidExtensionSubjectAltName, + Value: sanBytes, + }) + } + + if template.KeyUsage != 0 && + !oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) { + ext, err := marshalKeyUsage(template.KeyUsage) + if err != nil { + return nil, err + } + ret = append(ret, ext) + } + + if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) && + !oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) { + ext, err := marshalExtKeyUsage(template.ExtKeyUsage, template.UnknownExtKeyUsage) + if err != nil { + return nil, err + } + ret = append(ret, ext) + } + + if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) { + ext, err := marshalBasicConstraints(template.IsCA, template.MaxPathLen, template.MaxPathLenZero) + if err != nil { + return nil, err + } + ret = append(ret, ext) + } + + if len(template.SubjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) { + skidBytes, err := asn1.Marshal(template.SubjectKeyId) + if err != nil { + return nil, err + } + ret = append(ret, pkix.Extension{Id: oidExtensionSubjectKeyId, Value: skidBytes}) + } + + if len(template.PolicyIdentifiers) > 0 && + !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) { + ext, err := marshalCertificatePolicies(template.PolicyIdentifiers) + if err != nil { + return nil, err + } + ret = append(ret, ext) + } + + return append(ret, template.ExtraExtensions...), nil +} + func subjectBytes(cert *Certificate) ([]byte, error) { if len(cert.RawSubject) > 0 { return cert.RawSubject, nil @@ -2105,7 +2229,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv subjectKeyId = h[:] } - extensions, err := buildExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId) + extensions, err := buildCertExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId) if err != nil { return } @@ -2281,6 +2405,7 @@ type CertificateRequest struct { Version int Signature []byte SignatureAlgorithm SignatureAlgorithm + KeyUsage KeyUsage PublicKeyAlgorithm PublicKeyAlgorithm PublicKey interface{} @@ -2313,6 +2438,37 @@ type CertificateRequest struct { EmailAddresses []string IPAddresses []net.IP URIs []*url.URL + + ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages. + UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package. + + // BasicConstraintsValid indicates whether IsCA, MaxPathLen, + // and MaxPathLenZero are valid. + BasicConstraintsValid bool + IsCA bool + + // MaxPathLen and MaxPathLenZero indicate the presence and + // value of the BasicConstraints' "pathLenConstraint". + // + // When parsing a certificate, a positive non-zero MaxPathLen + // means that the field was specified, -1 means it was unset, + // and MaxPathLenZero being true mean that the field was + // explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false + // should be treated equivalent to -1 (unset). + // + // When generating a certificate, an unset pathLenConstraint + // can be requested with either MaxPathLen == -1 or using the + // zero value for both MaxPathLen and MaxPathLenZero. + MaxPathLen int + // MaxPathLenZero indicates that BasicConstraintsValid==true + // and MaxPathLen==0 should be interpreted as an actual + // maximum path length of zero. Otherwise, that combination is + // interpreted as MaxPathLen not being set. + MaxPathLenZero bool + + SubjectKeyId []byte + + PolicyIdentifiers []asn1.ObjectIdentifier } // These structures reflect the ASN.1 structure of X.509 certificate @@ -2410,6 +2566,15 @@ func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) // - EmailAddresses // - IPAddresses // - URIs +// - KeyUsage +// - ExtKeyUsage +// - UnknownExtKeyUsage +// - BasicConstraintsValid +// - IsCA +// - MaxPathLen +// - MaxPathLenZero +// - SubjectKeyId +// - PolicyIdentifiers // - ExtraExtensions // - Attributes (deprecated) // @@ -2440,23 +2605,11 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv return nil, err } - var extensions []pkix.Extension - - if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) && - !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { - sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs) - if err != nil { - return nil, err - } - - extensions = append(extensions, pkix.Extension{ - Id: oidExtensionSubjectAltName, - Value: sanBytes, - }) + extensions, err := buildCSRExtensions(template) + if err != nil { + return nil, err } - extensions = append(extensions, template.ExtraExtensions...) - // Make a copy of template.Attributes because we may alter it below. attributes := make([]pkix.AttributeTypeAndValueSET, 0, len(template.Attributes)) for _, attr := range template.Attributes { @@ -2640,11 +2793,36 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error } for _, extension := range out.Extensions { - if extension.Id.Equal(oidExtensionSubjectAltName) { + switch { + case extension.Id.Equal(oidExtensionSubjectAltName): out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(extension.Value) if err != nil { return nil, err } + case extension.Id.Equal(oidExtensionKeyUsage): + out.KeyUsage, err = parseKeyUsageExtension(extension.Value) + case extension.Id.Equal(oidExtensionExtendedKeyUsage): + out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(extension.Value) + if err != nil { + return nil, err + } + case extension.Id.Equal(oidExtensionBasicConstraints): + out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(extension.Value) + if err != nil { + return nil, err + } + out.BasicConstraintsValid = true + out.MaxPathLenZero = out.MaxPathLen == 0 + case extension.Id.Equal(oidExtensionSubjectKeyId): + out.SubjectKeyId, err = parseSubjectKeyIdExtension(extension.Value) + if err != nil { + return nil, err + } + case extension.Id.Equal(oidExtensionCertificatePolicies): + out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(extension.Value) + if err != nil { + return nil, err + } } } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 1ba31aeff32..65d105db344 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -2962,3 +2962,46 @@ func certPoolEqual(a, b *CertPool) bool { return true } + +func TestCertificateRequestRoundtripFields(t *testing.T) { + in := &CertificateRequest{ + KeyUsage: KeyUsageCertSign, + ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageAny}, + UnknownExtKeyUsage: []asn1.ObjectIdentifier{{1, 2, 3}}, + BasicConstraintsValid: true, + IsCA: true, + MaxPathLen: 0, + MaxPathLenZero: true, + SubjectKeyId: []byte{1, 2, 3}, + PolicyIdentifiers: []asn1.ObjectIdentifier{{1, 2, 3}}, + } + out := marshalAndParseCSR(t, in) + + if in.KeyUsage != out.KeyUsage { + t.Fatalf("Unexpected KeyUsage: got %v, want %v", out.KeyUsage, in.KeyUsage) + } + if !reflect.DeepEqual(in.ExtKeyUsage, out.ExtKeyUsage) { + t.Fatalf("Unexpected ExtKeyUsage: got %v, want %v", out.ExtKeyUsage, in.ExtKeyUsage) + } + if !reflect.DeepEqual(in.UnknownExtKeyUsage, out.UnknownExtKeyUsage) { + t.Fatalf("Unexpected UnknownExtKeyUsage: got %v, want %v", out.UnknownExtKeyUsage, in.UnknownExtKeyUsage) + } + if in.BasicConstraintsValid != out.BasicConstraintsValid { + t.Fatalf("Unexpected BasicConstraintsValid: got %v, want %v", out.BasicConstraintsValid, in.BasicConstraintsValid) + } + if in.IsCA != out.IsCA { + t.Fatalf("Unexpected IsCA: got %v, want %v", out.IsCA, in.IsCA) + } + if in.MaxPathLen != out.MaxPathLen { + t.Fatalf("Unexpected MaxPathLen: got %v, want %v", out.MaxPathLen, in.MaxPathLen) + } + if in.MaxPathLenZero != out.MaxPathLenZero { + t.Fatalf("Unexpected MaxPathLenZero: got %v, want %v", out.MaxPathLenZero, in.MaxPathLenZero) + } + if !reflect.DeepEqual(in.SubjectKeyId, out.SubjectKeyId) { + t.Fatalf("Unexpected SubjectKeyId: got %v, want %v", out.SubjectKeyId, in.SubjectKeyId) + } + if !reflect.DeepEqual(in.PolicyIdentifiers, out.PolicyIdentifiers) { + t.Fatalf("Unexpected PolicyIdentifiers: got %v, want %v", out.PolicyIdentifiers, in.PolicyIdentifiers) + } +} From a07e4360a80b3ff2490879e4b4065ecc7b1b9098 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 5 Nov 2020 12:59:16 -0500 Subject: [PATCH 397/403] cmd/go: prefer 'go get -d' instead of 'go get' in script tests 'get -d' has somewhat narrower semantics and is generally faster. We're deprecating the non-'-d' mode in CL 266360. For #26472 Change-Id: Id4a324771f77b83e5f47043fd50b74e1c062390b Reviewed-on: https://go-review.googlesource.com/c/go/+/267883 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/get_go_file.txt | 18 +++++++++--------- src/cmd/go/testdata/script/mod_case.txt | 2 +- src/cmd/go/testdata/script/mod_case_cgo.txt | 4 +++- src/cmd/go/testdata/script/mod_get_commit.txt | 4 ++-- .../go/testdata/script/mod_get_downgrade.txt | 14 ++++++++------ .../script/mod_get_downgrade_missing.txt | 8 ++++---- .../testdata/script/mod_get_incompatible.txt | 4 ++-- src/cmd/go/testdata/script/mod_get_moved.txt | 4 ++-- src/cmd/go/testdata/script/mod_get_none.txt | 4 ++-- .../go/testdata/script/mod_get_sum_noroot.txt | 2 +- src/cmd/go/testdata/script/mod_get_test.txt | 2 +- src/cmd/go/testdata/script/mod_get_upgrade.txt | 2 +- src/cmd/go/testdata/script/mod_gonoproxy.txt | 14 +++++++------- .../go/testdata/script/mod_gopkg_unstable.txt | 2 +- src/cmd/go/testdata/script/mod_issue35317.txt | 2 +- src/cmd/go/testdata/script/mod_proxy_list.txt | 14 +++++++------- src/cmd/go/testdata/script/mod_readonly.txt | 2 +- .../go/testdata/script/mod_tidy_replace.txt | 2 +- src/cmd/go/testdata/script/mod_vendor_auto.txt | 2 +- .../go/testdata/script/mod_vendor_build.txt | 2 +- .../testdata/script/vendor_list_issue11977.txt | 2 +- 21 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/cmd/go/testdata/script/get_go_file.txt b/src/cmd/go/testdata/script/get_go_file.txt index 97e0f1ac926..bed87209876 100644 --- a/src/cmd/go/testdata/script/get_go_file.txt +++ b/src/cmd/go/testdata/script/get_go_file.txt @@ -5,46 +5,46 @@ env GO111MODULE=off # argument doesn't have .go suffix -go get test +go get -d test # argument has .go suffix, is a file and exists -! go get test.go +! go get -d test.go stderr 'go get test.go: arguments must be package or module paths' # argument has .go suffix, doesn't exist and has no slashes -! go get test_missing.go +! go get -d test_missing.go stderr 'go get test_missing.go: arguments must be package or module paths' # argument has .go suffix, is a file and exists in sub-directory -! go get test/test.go +! go get -d test/test.go stderr 'go get: test/test.go exists as a file, but ''go get'' requires package arguments' # argument has .go suffix, doesn't exist and has slashes -! go get test/test_missing.go +! go get -d test/test_missing.go ! stderr 'arguments must be package or module paths' ! stderr 'exists as a file, but ''go get'' requires package arguments' # argument has .go suffix, is a symlink and exists [symlink] symlink test_sym.go -> test.go -[symlink] ! go get test_sym.go +[symlink] ! go get -d test_sym.go [symlink] stderr 'go get test_sym.go: arguments must be package or module paths' [symlink] rm test_sym.go # argument has .go suffix, is a symlink and exists in sub-directory [symlink] symlink test/test_sym.go -> test.go -[symlink] ! go get test/test_sym.go +[symlink] ! go get -d test/test_sym.go [symlink] stderr 'go get: test/test_sym.go exists as a file, but ''go get'' requires package arguments' [symlink] rm test_sym.go # argument has .go suffix, is a directory and exists mkdir test_dir.go -! go get test_dir.go +! go get -d test_dir.go stderr 'go get test_dir.go: arguments must be package or module paths' rm test_dir.go # argument has .go suffix, is a directory and exists in sub-directory mkdir test/test_dir.go -! go get test/test_dir.go +! go get -d test/test_dir.go ! stderr 'arguments must be package or module paths' ! stderr 'exists as a file, but ''go get'' requires package arguments' rm test/test_dir.go diff --git a/src/cmd/go/testdata/script/mod_case.txt b/src/cmd/go/testdata/script/mod_case.txt index 6f8d869c447..4a4698600f7 100644 --- a/src/cmd/go/testdata/script/mod_case.txt +++ b/src/cmd/go/testdata/script/mod_case.txt @@ -9,7 +9,7 @@ go list -f 'DIR {{.Dir}} DEPS {{.Deps}}' rsc.io/QUOTE/QUOTE stdout 'DEPS.*rsc.io/quote' stdout 'DIR.*!q!u!o!t!e' -go get rsc.io/QUOTE@v1.5.3-PRE +go get -d rsc.io/QUOTE@v1.5.3-PRE go list -m all stdout '^rsc.io/QUOTE v1.5.3-PRE' diff --git a/src/cmd/go/testdata/script/mod_case_cgo.txt b/src/cmd/go/testdata/script/mod_case_cgo.txt index 917bce92d88..f3d6aaa5abc 100644 --- a/src/cmd/go/testdata/script/mod_case_cgo.txt +++ b/src/cmd/go/testdata/script/mod_case_cgo.txt @@ -2,7 +2,9 @@ env GO111MODULE=on -go get rsc.io/CGO +go get -d rsc.io/CGO +[short] stop + go build rsc.io/CGO -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_get_commit.txt b/src/cmd/go/testdata/script/mod_get_commit.txt index 857740ae6cb..4649491a532 100644 --- a/src/cmd/go/testdata/script/mod_get_commit.txt +++ b/src/cmd/go/testdata/script/mod_get_commit.txt @@ -32,11 +32,11 @@ go install -x golang.org/x/text/language ! go get -d -x golang.org/x/text/foo@14c0d48 # get pseudo-version should record that version -go get rsc.io/quote@v0.0.0-20180214005840-23179ee8a569 +go get -d rsc.io/quote@v0.0.0-20180214005840-23179ee8a569 grep 'rsc.io/quote v0.0.0-20180214005840-23179ee8a569' go.mod # but as commit should record as v1.5.1 -go get rsc.io/quote@23179ee8 +go get -d rsc.io/quote@23179ee8 grep 'rsc.io/quote v1.5.1' go.mod # go mod edit -require does not interpret commits diff --git a/src/cmd/go/testdata/script/mod_get_downgrade.txt b/src/cmd/go/testdata/script/mod_get_downgrade.txt index 77dad2b3853..a954c10344b 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade.txt @@ -3,31 +3,33 @@ env GO111MODULE=on # downgrade sampler should downgrade quote cp go.mod.orig go.mod -go get rsc.io/sampler@v1.0.0 +go get -d rsc.io/sampler@v1.0.0 go list -m all stdout 'rsc.io/quote v1.4.0' stdout 'rsc.io/sampler v1.0.0' # downgrade sampler away should downgrade quote further -go get rsc.io/sampler@none +go get -d rsc.io/sampler@none go list -m all stdout 'rsc.io/quote v1.3.0' # downgrade should report inconsistencies and not change go.mod -go get rsc.io/quote@v1.5.1 +go get -d rsc.io/quote@v1.5.1 go list -m all stdout 'rsc.io/quote v1.5.1' stdout 'rsc.io/sampler v1.3.0' -! go get rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none + +! go get -d rsc.io/sampler@v1.0.0 rsc.io/quote@v1.5.2 golang.org/x/text@none stderr '^go get: rsc.io/quote@v1.5.2 requires rsc.io/sampler@v1.3.0, not rsc.io/sampler@v1.0.0$' stderr '^go get: rsc.io/quote@v1.5.2 requires golang.org/x/text@v0.0.0-20170915032832-14c0d48ead0c, not golang.org/x/text@none$' + go list -m all stdout 'rsc.io/quote v1.5.1' stdout 'rsc.io/sampler v1.3.0' # go get -u args should limit upgrades cp go.mod.empty go.mod -go get -u rsc.io/quote@v1.4.0 rsc.io/sampler@v1.0.0 +go get -d -u rsc.io/quote@v1.4.0 rsc.io/sampler@v1.0.0 go list -m all stdout 'rsc.io/quote v1.4.0' stdout 'rsc.io/sampler v1.0.0' @@ -38,7 +40,7 @@ stdout 'rsc.io/sampler v1.0.0' cp go.mod.orig go.mod go list -m -versions example.com/latemigrate/v2 stdout v2.0.0 # proxy may serve incompatible versions -go get rsc.io/quote@none +go get -d rsc.io/quote@none go list -m all ! stdout 'example.com/latemigrate/v2' diff --git a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt index f1167fb578a..5b768faeb18 100644 --- a/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt +++ b/src/cmd/go/testdata/script/mod_get_downgrade_missing.txt @@ -4,7 +4,7 @@ cp go.mod go.mod.orig # not yet present in that module should report the version mismatch # rather than a "matched no packages" warning. -! go get example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... +! go get -d example.net/pkgadded@v1.1.0 example.net/pkgadded/subpkg/... stderr '^go get: example.net/pkgadded@v1.1.0 conflicts with example.net/pkgadded/subpkg/...@upgrade \(v1.2.0\)$' ! stderr 'matched no packages' cmp go.mod.orig go.mod @@ -12,7 +12,7 @@ cmp go.mod.orig go.mod # A wildcard pattern should match the pattern with that path. -go get example.net/pkgadded/...@v1.0.0 +go get -d example.net/pkgadded/...@v1.0.0 go list -m all stdout '^example.net/pkgadded v1.0.0' cp go.mod.orig go.mod @@ -22,12 +22,12 @@ cp go.mod.orig go.mod # and another argument constrains away the version that provides that # package, then 'go get' should fail with a useful error message. -! go get example.net/pkgadded@v1.0.0 . +! go get -d example.net/pkgadded@v1.0.0 . stderr '^example.com/m imports\n\texample.net/pkgadded/subpkg: cannot find module providing package example.net/pkgadded/subpkg$' ! stderr 'example.net/pkgadded v1\.2\.0' cmp go.mod.orig go.mod -go get example.net/pkgadded@v1.0.0 +go get -d example.net/pkgadded@v1.0.0 ! go list -deps -mod=readonly . stderr '^m.go:3:8: cannot find module providing package example\.net/pkgadded/subpkg: ' diff --git a/src/cmd/go/testdata/script/mod_get_incompatible.txt b/src/cmd/go/testdata/script/mod_get_incompatible.txt index b28718a6946..8000ee61481 100644 --- a/src/cmd/go/testdata/script/mod_get_incompatible.txt +++ b/src/cmd/go/testdata/script/mod_get_incompatible.txt @@ -5,11 +5,11 @@ go list -m all stdout 'rsc.io/breaker v2.0.0\+incompatible' cp go.mod2 go.mod -go get rsc.io/breaker@7307b30 +go get -d rsc.io/breaker@7307b30 go list -m all stdout 'rsc.io/breaker v2.0.0\+incompatible' -go get rsc.io/breaker@v2.0.0 +go get -d rsc.io/breaker@v2.0.0 go list -m all stdout 'rsc.io/breaker v2.0.0\+incompatible' diff --git a/src/cmd/go/testdata/script/mod_get_moved.txt b/src/cmd/go/testdata/script/mod_get_moved.txt index e16c1608909..8430a737c40 100644 --- a/src/cmd/go/testdata/script/mod_get_moved.txt +++ b/src/cmd/go/testdata/script/mod_get_moved.txt @@ -9,7 +9,7 @@ go list -m all stdout 'example.com/split v1.0.0' # A 'go get' that simultaneously upgrades away conflicting package defitions is not ambiguous. -go get example.com/split/subpkg@v1.1.0 +go get -d example.com/split/subpkg@v1.1.0 # A 'go get' without an upgrade should find the package. rm go.mod @@ -30,7 +30,7 @@ stdout 'example.com/join/subpkg v1.0.0' # A 'go get' that simultaneously upgrades away conflicting package definitions is not ambiguous. # (A wildcard pattern applies to both packages and modules, # because we define wildcard matching to apply after version resolution.) -go get example.com/join/subpkg/...@v1.1.0 +go get -d example.com/join/subpkg/...@v1.1.0 # A 'go get' without an upgrade should find the package. rm go.mod diff --git a/src/cmd/go/testdata/script/mod_get_none.txt b/src/cmd/go/testdata/script/mod_get_none.txt index 5aec209f59f..b358f05af36 100644 --- a/src/cmd/go/testdata/script/mod_get_none.txt +++ b/src/cmd/go/testdata/script/mod_get_none.txt @@ -3,10 +3,10 @@ env GO111MODULE=on go mod init example.com/foo # 'go get bar@none' should be a no-op if module bar is not active. -go get example.com/bar@none +go get -d example.com/bar@none go list -m all ! stdout example.com/bar -go get example.com/bar@none +go get -d example.com/bar@none go list -m all ! stdout example.com/bar diff --git a/src/cmd/go/testdata/script/mod_get_sum_noroot.txt b/src/cmd/go/testdata/script/mod_get_sum_noroot.txt index 0d9a840e779..4f1cf032777 100644 --- a/src/cmd/go/testdata/script/mod_get_sum_noroot.txt +++ b/src/cmd/go/testdata/script/mod_get_sum_noroot.txt @@ -2,7 +2,7 @@ # it should add sums for the module's go.mod file and its content to go.sum. # Verifies golang.org/issue/41103. go mod init m -go get rsc.io/QUOTE +go get -d rsc.io/QUOTE grep '^rsc.io/QUOTE v1.5.2/go.mod ' go.sum grep '^rsc.io/QUOTE v1.5.2 ' go.sum diff --git a/src/cmd/go/testdata/script/mod_get_test.txt b/src/cmd/go/testdata/script/mod_get_test.txt index 3680ca273d9..23722bd4e4d 100644 --- a/src/cmd/go/testdata/script/mod_get_test.txt +++ b/src/cmd/go/testdata/script/mod_get_test.txt @@ -2,7 +2,7 @@ env GO111MODULE=on # By default, 'go get' should ignore tests cp go.mod.empty go.mod -go get m/a +go get -d m/a ! grep rsc.io/quote go.mod # 'go get -t' should consider test dependencies of the named package. diff --git a/src/cmd/go/testdata/script/mod_get_upgrade.txt b/src/cmd/go/testdata/script/mod_get_upgrade.txt index 6a14dfdc45d..eeb6d6f6af6 100644 --- a/src/cmd/go/testdata/script/mod_get_upgrade.txt +++ b/src/cmd/go/testdata/script/mod_get_upgrade.txt @@ -1,6 +1,6 @@ env GO111MODULE=on -go get rsc.io/quote@v1.5.1 +go get -d rsc.io/quote@v1.5.1 go list -m all stdout 'rsc.io/quote v1.5.1' grep 'rsc.io/quote v1.5.1$' go.mod diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt index a9e0ca40108..7ead946c24a 100644 --- a/src/cmd/go/testdata/script/mod_gonoproxy.txt +++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt @@ -7,26 +7,26 @@ env dbname=localhost.localdev/sumdb # disagree with sumdb fails cp go.mod.orig go.mod env GOSUMDB=$sumdb' '$proxy/sumdb-wrong -! go get rsc.io/quote +! go get -d rsc.io/quote stderr 'SECURITY ERROR' # GONOSUMDB bypasses sumdb, for rsc.io/quote, rsc.io/sampler, golang.org/x/text env GONOSUMDB='*/quote,*/*mple*,golang.org/x' -go get rsc.io/quote +go get -d rsc.io/quote rm go.sum env GOPRIVATE='*/quote,*/*mple*,golang.org/x' env GONOPROXY=none # that is, proxy all despite GOPRIVATE -go get rsc.io/quote +go get -d rsc.io/quote # When GOPROXY is not empty but contains no entries, an error should be reported. env GOPROXY=',' -! go get golang.org/x/text +! go get -d golang.org/x/text stderr '^go get golang.org/x/text: GOPROXY list is not the empty string, but contains no entries$' # When GOPROXY=off, fetching modules not matched by GONOPROXY fails. env GONOPROXY=*/fortune env GOPROXY=off -! go get golang.org/x/text +! go get -d golang.org/x/text stderr '^go get golang.org/x/text: module lookup disabled by GOPROXY=off$' # GONOPROXY bypasses proxy @@ -34,13 +34,13 @@ stderr '^go get golang.org/x/text: module lookup disabled by GOPROXY=off$' [!exec:git] skip env GOPRIVATE=none env GONOPROXY='*/fortune' -! go get rsc.io/fortune # does not exist in real world, only on test proxy +! go get -d rsc.io/fortune # does not exist in real world, only on test proxy stderr 'git ls-remote' env GOSUMDB= env GONOPROXY= env GOPRIVATE='*/x' -go get golang.org/x/text +go get -d golang.org/x/text go list -m all ! stdout 'text.*v0.0.0-2017' # should not have the version from the proxy diff --git a/src/cmd/go/testdata/script/mod_gopkg_unstable.txt b/src/cmd/go/testdata/script/mod_gopkg_unstable.txt index 9d288a64d45..5ad9106378f 100644 --- a/src/cmd/go/testdata/script/mod_gopkg_unstable.txt +++ b/src/cmd/go/testdata/script/mod_gopkg_unstable.txt @@ -12,7 +12,7 @@ go list env GOPROXY=direct env GOSUMDB=off -go get gopkg.in/macaroon-bakery.v2-unstable/bakery +go get -d gopkg.in/macaroon-bakery.v2-unstable/bakery go list -m all stdout 'gopkg.in/macaroon-bakery.v2-unstable v2.0.0-[0-9]+-[0-9a-f]+$' diff --git a/src/cmd/go/testdata/script/mod_issue35317.txt b/src/cmd/go/testdata/script/mod_issue35317.txt index 92416a54e47..b1852ab0319 100644 --- a/src/cmd/go/testdata/script/mod_issue35317.txt +++ b/src/cmd/go/testdata/script/mod_issue35317.txt @@ -5,4 +5,4 @@ env GO111MODULE=on [short] skip go mod init example.com -go get golang.org/x/text@v0.3.0 golang.org/x/internal@v0.1.0 golang.org/x/exp@none +go get -d golang.org/x/text@v0.3.0 golang.org/x/internal@v0.1.0 golang.org/x/exp@none diff --git a/src/cmd/go/testdata/script/mod_proxy_list.txt b/src/cmd/go/testdata/script/mod_proxy_list.txt index 849cf2c4764..89129f4fe23 100644 --- a/src/cmd/go/testdata/script/mod_proxy_list.txt +++ b/src/cmd/go/testdata/script/mod_proxy_list.txt @@ -3,34 +3,34 @@ env proxy=$GOPROXY # Proxy that can't serve should fail. env GOPROXY=$proxy/404 -! go get rsc.io/quote@v1.0.0 +! go get -d rsc.io/quote@v1.0.0 stderr '404 Not Found' # get should walk down the proxy list past 404 and 410 responses. env GOPROXY=$proxy/404,$proxy/410,$proxy -go get rsc.io/quote@v1.1.0 +go get -d rsc.io/quote@v1.1.0 # get should not walk past other 4xx errors if proxies are separated with ','. env GOPROXY=$proxy/403,$proxy -! go get rsc.io/quote@v1.2.0 +! go get -d rsc.io/quote@v1.2.0 stderr 'reading.*/403/rsc.io/.*: 403 Forbidden' # get should not walk past non-4xx errors if proxies are separated with ','. env GOPROXY=$proxy/500,$proxy -! go get rsc.io/quote@v1.3.0 +! go get -d rsc.io/quote@v1.3.0 stderr 'reading.*/500/rsc.io/.*: 500 Internal Server Error' # get should walk past other 4xx errors if proxies are separated with '|'. env GOPROXY=$proxy/403|https://0.0.0.0|$proxy -go get rsc.io/quote@v1.2.0 +go get -d rsc.io/quote@v1.2.0 # get should walk past non-4xx errors if proxies are separated with '|'. env GOPROXY=$proxy/500|https://0.0.0.0|$proxy -go get rsc.io/quote@v1.3.0 +go get -d rsc.io/quote@v1.3.0 # get should return the final error if that's all we have. env GOPROXY=$proxy/404,$proxy/410 -! go get rsc.io/quote@v1.4.0 +! go get -d rsc.io/quote@v1.4.0 stderr 'reading.*/410/rsc.io/.*: 410 Gone' -- go.mod -- diff --git a/src/cmd/go/testdata/script/mod_readonly.txt b/src/cmd/go/testdata/script/mod_readonly.txt index f2c77de8062..ca8cd6e0689 100644 --- a/src/cmd/go/testdata/script/mod_readonly.txt +++ b/src/cmd/go/testdata/script/mod_readonly.txt @@ -19,7 +19,7 @@ cmp go.mod go.mod.empty env GOFLAGS=-mod=readonly # update go.mod - go get allowed -go get rsc.io/quote +go get -d rsc.io/quote grep rsc.io/quote go.mod # update go.mod - go mod tidy allowed diff --git a/src/cmd/go/testdata/script/mod_tidy_replace.txt b/src/cmd/go/testdata/script/mod_tidy_replace.txt index 7b00bf13842..dd994388910 100644 --- a/src/cmd/go/testdata/script/mod_tidy_replace.txt +++ b/src/cmd/go/testdata/script/mod_tidy_replace.txt @@ -35,7 +35,7 @@ grep 'golang.org/x/text' go.mod # 'go get' and 'go mod tidy' should follow the requirements of the replacements, # not the originals, even if that results in a set of versions that are # misleading or redundant without those replacements. -go get rsc.io/sampler@v1.2.0 +go get -d rsc.io/sampler@v1.2.0 go mod tidy go list -m all stdout 'rsc.io/quote/v3 v3.0.0' diff --git a/src/cmd/go/testdata/script/mod_vendor_auto.txt b/src/cmd/go/testdata/script/mod_vendor_auto.txt index e71db96643a..1b362eda0bd 100644 --- a/src/cmd/go/testdata/script/mod_vendor_auto.txt +++ b/src/cmd/go/testdata/script/mod_vendor_auto.txt @@ -177,7 +177,7 @@ stdout '^'$WORK'[/\\]auto[/\\]vendor[/\\]example.com[/\\]version$' # 'go get' should update from the network or module cache, # even if a vendor directory is present. -go get example.com/version@v1.1.0 +go get -d example.com/version@v1.1.0 ! go list -f {{.Dir}} -tags tools all stderr '^go: inconsistent vendoring' diff --git a/src/cmd/go/testdata/script/mod_vendor_build.txt b/src/cmd/go/testdata/script/mod_vendor_build.txt index 4efda55e08f..3b8eec0119b 100644 --- a/src/cmd/go/testdata/script/mod_vendor_build.txt +++ b/src/cmd/go/testdata/script/mod_vendor_build.txt @@ -10,7 +10,7 @@ stdout rsc.io/sampler ! grep 'rsc.io/sampler v1.3.0' go.mod # update to v1.3.1, now indirect in go.mod. -go get rsc.io/sampler@v1.3.1 +go get -d rsc.io/sampler@v1.3.1 grep 'rsc.io/sampler v1.3.1 // indirect' go.mod cp go.mod go.mod.good diff --git a/src/cmd/go/testdata/script/vendor_list_issue11977.txt b/src/cmd/go/testdata/script/vendor_list_issue11977.txt index cdab33c0892..ce2e29f99a7 100644 --- a/src/cmd/go/testdata/script/vendor_list_issue11977.txt +++ b/src/cmd/go/testdata/script/vendor_list_issue11977.txt @@ -2,7 +2,7 @@ [!exec:git] skip env GO111MODULE=off -go get github.com/rsc/go-get-issue-11864 +go get -d github.com/rsc/go-get-issue-11864 go list -f '{{join .TestImports "\n"}}' github.com/rsc/go-get-issue-11864/t stdout 'go-get-issue-11864/vendor/vendor.org/p' From a6462a608d60b6175db9dd9a7244b9609a12e7fc Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 5 Nov 2020 15:11:09 -0500 Subject: [PATCH 398/403] cmd/go: set FOSSIL_HOME in TestScript/mod_get_fossil Without HOME or FOSSIL_HOME set, this test fails for me when run with fossil 2.12.1. Also verify that the 'go get' command produces an executable, which helps to verify that the files extracted by fossil are not corrupted. Updates #42323 Change-Id: Ie6f5d2eab6a6338e997a4f85591195e5bd9a0d37 Reviewed-on: https://go-review.googlesource.com/c/go/+/267884 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/testdata/script/mod_get_fossil.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/testdata/script/mod_get_fossil.txt b/src/cmd/go/testdata/script/mod_get_fossil.txt index 3482e68da1d..baad544557a 100644 --- a/src/cmd/go/testdata/script/mod_get_fossil.txt +++ b/src/cmd/go/testdata/script/mod_get_fossil.txt @@ -13,14 +13,17 @@ env GOSUMDB=off # 'go get' for the fossil repo will fail if fossil # is unable to determine your fossil user. Easiest -# way to set it for use by 'go get' is specifying +# way to set it for use by 'go get' is specifying # a any non-empty $USER; the value doesn't otherwise matter. env USER=fossiluser +env FOSSIL_HOME=$WORK/home # Attempting to get the latest version of a fossil repo. go get vcs-test.golang.org/fossil/hello.fossil ! stderr 'unexpected response from fossil info' grep 'vcs-test.golang.org/fossil/hello.fossil' go.mod +exists $GOPATH/bin/hello.fossil$GOEXE -- go.mod -- module x +-- $WORK/home/.fossil -- From 65607683f531e30071e450858ef6bdc283a0280c Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 29 Oct 2020 15:49:05 -0400 Subject: [PATCH 399/403] cmd/go: print deprecation messages for 'go get' installing executables For #40276 Change-Id: I5e631a4c9ce07f23640fb56eb455457bc55072c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/266360 Run-TryBot: Jay Conrod TryBot-Result: Go Bot Trust: Jay Conrod Reviewed-by: Bryan C. Mills --- doc/go1.16.html | 10 ++++ src/cmd/go/alldocs.go | 15 ++++-- src/cmd/go/internal/modget/get.go | 49 +++++++++++++++---- .../script/mod_get_deprecate_install.txt | 22 +++++++++ 4 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 src/cmd/go/testdata/script/mod_get_deprecate_install.txt diff --git a/doc/go1.16.html b/doc/go1.16.html index a97c3698855..c6e217e7268 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -71,6 +71,16 @@ Do not send CLs removing the interior tags from such phrases. TODO: write and link to blog post

+

+ go install, with or without a version suffix (as + described above), is now the recommended way to build and install packages in + module mode. go get should be used with the + -d flag to adjust the current module's dependencies without + building packages, and use of go get to build and + install packages is deprecated. In a future release, the -d flag + will always be enabled. +

+

retract directives may now be used in a go.mod file to indicate that certain published versions of the module should not be used diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index e68fa55d09b..4461be2d092 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -673,6 +673,17 @@ // The second step is to download (if needed), build, and install // the named packages. // +// The -d flag instructs get to skip this step, downloading source code +// needed to build the named packages and their dependencies, but not +// building or installing. +// +// Building and installing packages with get is deprecated. In a future release, +// the -d flag will be enabled by default, and 'go get' will be only be used to +// adjust dependencies of the current module. To install a package using +// dependencies from the current module, use 'go install'. To install a package +// ignoring the current module, use 'go install' with an @version suffix like +// "@latest" after each argument. +// // If an argument names a module but not a package (because there is no // Go source code in the module's root directory), then the install step // is skipped for that argument, instead of causing a build failure. @@ -684,10 +695,6 @@ // adds the latest golang.org/x/perf and then installs the commands in that // latest version. // -// The -d flag instructs get to download the source code needed to build -// the named packages, including downloading necessary dependencies, -// but not to build and install them. -// // With no package arguments, 'go get' applies to Go package in the // current directory, if any. In particular, 'go get -u' and // 'go get -u=patch' update all the dependencies of that package. diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index 6ab242944ac..5b8eebf7cb2 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -144,6 +144,17 @@ GONOSUMDB. See 'go help environment' for details. The second step is to download (if needed), build, and install the named packages. +The -d flag instructs get to skip this step, downloading source code +needed to build the named packages and their dependencies, but not +building or installing. + +Building and installing packages with get is deprecated. In a future release, +the -d flag will be enabled by default, and 'go get' will be only be used to +adjust dependencies of the current module. To install a package using +dependencies from the current module, use 'go install'. To install a package +ignoring the current module, use 'go install' with an @version suffix like +"@latest" after each argument. + If an argument names a module but not a package (because there is no Go source code in the module's root directory), then the install step is skipped for that argument, instead of causing a build failure. @@ -155,10 +166,6 @@ the module versions. For example, 'go get golang.org/x/perf/cmd/...' adds the latest golang.org/x/perf and then installs the commands in that latest version. -The -d flag instructs get to download the source code needed to build -the named packages, including downloading necessary dependencies, -but not to build and install them. - With no package arguments, 'go get' applies to Go package in the current directory, if any. In particular, 'go get -u' and 'go get -u=patch' update all the dependencies of that package. @@ -436,12 +443,36 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { // Note that 'go get -u' without arguments is equivalent to // 'go get -u .', so we'll typically build the package in the current // directory. - if !*getD { - if len(pkgPatterns) > 0 { - work.BuildInit() - pkgs := load.PackagesForBuild(ctx, pkgPatterns) - work.InstallPackages(ctx, pkgPatterns, pkgs) + if !*getD && len(pkgPatterns) > 0 { + work.BuildInit() + pkgs := load.PackagesForBuild(ctx, pkgPatterns) + work.InstallPackages(ctx, pkgPatterns, pkgs) + + haveExe := false + for _, pkg := range pkgs { + if pkg.Name == "main" { + haveExe = true + break + } } + if haveExe { + fmt.Fprint(os.Stderr, "go get: installing executables with 'go get' in module mode is deprecated.") + var altMsg string + if modload.HasModRoot() { + altMsg = ` + To adjust dependencies of the current module, use 'go get -d'. + To install using requirements of the current module, use 'go install'. + To install ignoring the current module, use 'go install' with a version, + like 'go install example.com/cmd@latest'. +` + } else { + altMsg = "\n\tUse 'go install pkg@version' instead.\n" + } + fmt.Fprint(os.Stderr, altMsg) + fmt.Fprint(os.Stderr, "\tSee 'go help get' and 'go help install' for more information.\n") + } + // TODO(golang.org/issue/40276): link to HTML documentation explaining + // what's changing and gives more examples. } // Everything succeeded. Update go.mod. diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt new file mode 100644 index 00000000000..7f5bcad410c --- /dev/null +++ b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt @@ -0,0 +1,22 @@ +[short] skip + +env GO111MODULE=on + +# 'go get' outside a module with an executable prints a deprecation message. +go get example.com/cmd/a +stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' +stderr 'Use ''go install pkg@version'' instead.' + + +go mod init m + +# 'go get' inside a module with a non-main package does not print a message. +# This will stop building in the future, but it's the command we want to use. +go get rsc.io/quote +! stderr deprecated + +# 'go get' inside a module with an executable prints a different +# deprecation message. +go get example.com/cmd/a +stderr '^go get: installing executables with ''go get'' in module mode is deprecated.$' +stderr 'To adjust dependencies of the current module, use ''go get -d''' From 8a368c63ec2d48e1c8965341c982987de96164fd Mon Sep 17 00:00:00 2001 From: Jay Conrod Date: Thu, 29 Oct 2020 16:34:32 -0400 Subject: [PATCH 400/403] cmd/go: print deprecation messages for -i build, install, and test will now print deprecation messages when the -i flag is used. clean will continue to support -i. For #41696 Change-Id: I956c235c487a872c5e6c1395388b4d6cd5ef817a Reviewed-on: https://go-review.googlesource.com/c/go/+/266368 Trust: Jay Conrod Reviewed-by: Bryan C. Mills --- doc/go1.16.html | 12 ++++++++ src/cmd/go/alldocs.go | 7 +++-- src/cmd/go/internal/test/test.go | 2 ++ src/cmd/go/internal/work/build.go | 30 +++++++++++++++++-- .../go/testdata/script/build_i_deprecate.txt | 24 +++++++++++++++ 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 src/cmd/go/testdata/script/build_i_deprecate.txt diff --git a/doc/go1.16.html b/doc/go1.16.html index c6e217e7268..6c4d076d502 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -151,6 +151,18 @@ Do not send CLs removing the interior tags from such phrases. being built.

+

The -i build flag

+ +

+ The -i flag accepted by go build, + go install, and go test is + now deprecated. The -i flag instructs the go command + to install packages imported by packages named on the command line. Since + the build cache was introduced in Go 1.10, the -i flag no longer + has a significant effect on build times, and it causes errors when the install + directory is not writable. +

+

The list command

diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 4461be2d092..e8bfff1e699 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -72,7 +72,7 @@ // // Usage: // -// go build [-o output] [-i] [build flags] [packages] +// go build [-o output] [build flags] [packages] // // Build compiles the packages named by the import paths, // along with their dependencies, but it does not install the results. @@ -99,6 +99,7 @@ // will be written to that directory. // // The -i flag installs the packages that are dependencies of the target. +// The -i flag is deprecated. Compiled packages are cached automatically. // // The build flags are shared by the build, clean, get, install, list, run, // and test commands: @@ -717,7 +718,7 @@ // // Usage: // -// go install [-i] [build flags] [packages] +// go install [build flags] [packages] // // Install compiles and installs the packages named by the import paths. // @@ -758,6 +759,7 @@ // other packages are built and cached but not installed. // // The -i flag installs the dependencies of the named packages as well. +// The -i flag is deprecated. Compiled packages are cached automatically. // // For more about the build flags, see 'go help build'. // For more about specifying packages, see 'go help packages'. @@ -1459,6 +1461,7 @@ // -i // Install packages that are dependencies of the test. // Do not run the test. +// The -i flag is deprecated. Compiled packages are cached automatically. // // -json // Convert test output to JSON suitable for automated processing. diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go index 00da9770dfe..24601dc0614 100644 --- a/src/cmd/go/internal/test/test.go +++ b/src/cmd/go/internal/test/test.go @@ -150,6 +150,7 @@ In addition to the build flags, the flags handled by 'go test' itself are: -i Install packages that are dependencies of the test. Do not run the test. + The -i flag is deprecated. Compiled packages are cached automatically. -json Convert test output to JSON suitable for automated processing. @@ -640,6 +641,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) { b.Init() if cfg.BuildI { + fmt.Fprint(os.Stderr, "go test: -i flag is deprecated\n") cfg.BuildV = testV deps := make(map[string]bool) diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 181bb3b8744..7e26d4e6a37 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -31,7 +31,7 @@ import ( ) var CmdBuild = &base.Command{ - UsageLine: "go build [-o output] [-i] [build flags] [packages]", + UsageLine: "go build [-o output] [build flags] [packages]", Short: "compile packages and dependencies", Long: ` Build compiles the packages named by the import paths, @@ -59,6 +59,7 @@ ends with a slash or backslash, then any resulting executables will be written to that directory. The -i flag installs the packages that are dependencies of the target. +The -i flag is deprecated. Compiled packages are cached automatically. The build flags are shared by the build, clean, get, install, list, run, and test commands: @@ -381,6 +382,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { depMode := ModeBuild if cfg.BuildI { depMode = ModeInstall + fmt.Fprint(os.Stderr, "go build: -i flag is deprecated\n") } pkgs = omitTestOnly(pkgsFilter(load.Packages(ctx, args))) @@ -444,7 +446,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) { } var CmdInstall = &base.Command{ - UsageLine: "go install [-i] [build flags] [packages]", + UsageLine: "go install [build flags] [packages]", Short: "compile and install packages and dependencies", Long: ` Install compiles and installs the packages named by the import paths. @@ -486,6 +488,7 @@ directory $GOPATH/pkg/$GOOS_$GOARCH. When module-aware mode is enabled, other packages are built and cached but not installed. The -i flag installs the dependencies of the named packages as well. +The -i flag is deprecated. Compiled packages are cached automatically. For more about the build flags, see 'go help build'. For more about specifying packages, see 'go help packages'. @@ -551,14 +554,35 @@ func libname(args []string, pkgs []*load.Package) (string, error) { } func runInstall(ctx context.Context, cmd *base.Command, args []string) { + // TODO(golang.org/issue/41696): print a deprecation message for the -i flag + // whenever it's set (or just remove it). For now, we don't print a message + // if all named packages are in GOROOT. cmd/dist (run by make.bash) uses + // 'go install -i' when bootstrapping, and we don't want to show deprecation + // messages in that case. for _, arg := range args { if strings.Contains(arg, "@") && !build.IsLocalImport(arg) && !filepath.IsAbs(arg) { + if cfg.BuildI { + fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n") + } installOutsideModule(ctx, args) return } } BuildInit() - InstallPackages(ctx, args, load.PackagesForBuild(ctx, args)) + pkgs := load.PackagesForBuild(ctx, args) + if cfg.BuildI { + allGoroot := true + for _, pkg := range pkgs { + if !pkg.Goroot { + allGoroot = false + break + } + } + if !allGoroot { + fmt.Fprint(os.Stderr, "go install: -i flag is deprecated\n") + } + } + InstallPackages(ctx, args, pkgs) } // omitTestOnly returns pkgs with test-only packages removed. diff --git a/src/cmd/go/testdata/script/build_i_deprecate.txt b/src/cmd/go/testdata/script/build_i_deprecate.txt new file mode 100644 index 00000000000..71356e5321e --- /dev/null +++ b/src/cmd/go/testdata/script/build_i_deprecate.txt @@ -0,0 +1,24 @@ +# Check that deprecation warnings are printed when the -i flag is used. +# TODO(golang.org/issue/41696): remove the -i flag after Go 1.16, and this test. + +go build -n -i +stderr '^go build: -i flag is deprecated$' + +go install -n -i +stderr '^go install: -i flag is deprecated$' + +go test -n -i +stderr '^go test: -i flag is deprecated$' + + +# 'go clean -i' should not print a deprecation warning. +# It will continue working. +go clean -i . +! stderr . + +-- go.mod -- +module m + +go 1.16 +-- m.go -- +package m From 858fa061aed447527fa5f451e7d611d8735f8cb6 Mon Sep 17 00:00:00 2001 From: Koen Date: Wed, 14 Oct 2020 01:05:43 +0200 Subject: [PATCH 401/403] crypto/x509: return additional chains from Verify on Windows Previously windows only returned the certificate-chain with the highest quality. This change makes it so chains with a potentially lower quality originating from other root certificates are also returned by verify. Tests in verify_test flagged with systemLax are now allowed to pass if the system returns additional chains Fixes #40604 Change-Id: I66edc233219f581039d47a15f2200ff627154691 Reviewed-on: https://go-review.googlesource.com/c/go/+/257257 Reviewed-by: Tobias Klauser Reviewed-by: Filippo Valsorda Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Go Bot --- src/crypto/x509/root_windows.go | 112 ++++++++++++++++++-------------- src/crypto/x509/verify_test.go | 65 +++++++++++------- 2 files changed, 105 insertions(+), 72 deletions(-) diff --git a/src/crypto/x509/root_windows.go b/src/crypto/x509/root_windows.go index 22e5a9382be..1e9be80b7dd 100644 --- a/src/crypto/x509/root_windows.go +++ b/src/crypto/x509/root_windows.go @@ -155,6 +155,44 @@ func init() { } } +func verifyChain(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) (chain []*Certificate, err error) { + err = checkChainTrustStatus(c, chainCtx) + if err != nil { + return nil, err + } + + if opts != nil && len(opts.DNSName) > 0 { + err = checkChainSSLServerPolicy(c, chainCtx, opts) + if err != nil { + return nil, err + } + } + + chain, err = extractSimpleChain(chainCtx.Chains, int(chainCtx.ChainCount)) + if err != nil { + return nil, err + } + if len(chain) == 0 { + return nil, errors.New("x509: internal error: system verifier returned an empty chain") + } + + // Mitigate CVE-2020-0601, where the Windows system verifier might be + // tricked into using custom curve parameters for a trusted root, by + // double-checking all ECDSA signatures. If the system was tricked into + // using spoofed parameters, the signature will be invalid for the correct + // ones we parsed. (We don't support custom curves ourselves.) + for i, parent := range chain[1:] { + if parent.PublicKeyAlgorithm != ECDSA { + continue + } + if err := parent.CheckSignature(chain[i].SignatureAlgorithm, + chain[i].RawTBSCertificate, chain[i].Signature); err != nil { + return nil, err + } + } + return chain, nil +} + // systemVerify is like Verify, except that it uses CryptoAPI calls // to build certificate chains and verify them. func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { @@ -202,67 +240,41 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate verifyTime = &ft } - // CertGetCertificateChain will traverse Windows's root stores - // in an attempt to build a verified certificate chain. Once - // it has found a verified chain, it stops. MSDN docs on - // CERT_CHAIN_CONTEXT: - // - // When a CERT_CHAIN_CONTEXT is built, the first simple chain - // begins with an end certificate and ends with a self-signed - // certificate. If that self-signed certificate is not a root - // or otherwise trusted certificate, an attempt is made to - // build a new chain. CTLs are used to create the new chain - // beginning with the self-signed certificate from the original - // chain as the end certificate of the new chain. This process - // continues building additional simple chains until the first - // self-signed certificate is a trusted certificate or until - // an additional simple chain cannot be built. - // - // The result is that we'll only get a single trusted chain to - // return to our caller. - var chainCtx *syscall.CertChainContext - err = syscall.CertGetCertificateChain(syscall.Handle(0), storeCtx, verifyTime, storeCtx.Store, para, 0, 0, &chainCtx) + // The default is to return only the highest quality chain, + // setting this flag will add additional lower quality contexts. + // These are returned in the LowerQualityChains field. + const CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS = 0x00000080 + + // CertGetCertificateChain will traverse Windows's root stores in an attempt to build a verified certificate chain + var topCtx *syscall.CertChainContext + err = syscall.CertGetCertificateChain(syscall.Handle(0), storeCtx, verifyTime, storeCtx.Store, para, CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS, 0, &topCtx) if err != nil { return nil, err } - defer syscall.CertFreeCertificateChain(chainCtx) + defer syscall.CertFreeCertificateChain(topCtx) - err = checkChainTrustStatus(c, chainCtx) - if err != nil { - return nil, err + chain, topErr := verifyChain(c, topCtx, opts) + if topErr == nil { + chains = append(chains, chain) } - if opts != nil && len(opts.DNSName) > 0 { - err = checkChainSSLServerPolicy(c, chainCtx, opts) - if err != nil { - return nil, err + if lqCtxCount := topCtx.LowerQualityChainCount; lqCtxCount > 0 { + lqCtxs := (*[1 << 20]*syscall.CertChainContext)(unsafe.Pointer(topCtx.LowerQualityChains))[:lqCtxCount:lqCtxCount] + + for _, ctx := range lqCtxs { + chain, err := verifyChain(c, ctx, opts) + if err == nil { + chains = append(chains, chain) + } } } - chain, err := extractSimpleChain(chainCtx.Chains, int(chainCtx.ChainCount)) - if err != nil { - return nil, err - } - if len(chain) < 1 { - return nil, errors.New("x509: internal error: system verifier returned an empty chain") + if len(chains) == 0 { + // Return the error from the highest quality context. + return nil, topErr } - // Mitigate CVE-2020-0601, where the Windows system verifier might be - // tricked into using custom curve parameters for a trusted root, by - // double-checking all ECDSA signatures. If the system was tricked into - // using spoofed parameters, the signature will be invalid for the correct - // ones we parsed. (We don't support custom curves ourselves.) - for i, parent := range chain[1:] { - if parent.PublicKeyAlgorithm != ECDSA { - continue - } - if err := parent.CheckSignature(chain[i].SignatureAlgorithm, - chain[i].RawTBSCertificate, chain[i].Signature); err != nil { - return nil, err - } - } - - return [][]*Certificate{chain}, nil + return chains, nil } func loadSystemRoots() (*CertPool, error) { diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go index 9cc17c7b3d8..8e0a7bef475 100644 --- a/src/crypto/x509/verify_test.go +++ b/src/crypto/x509/verify_test.go @@ -550,34 +550,55 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { } } - if len(chains) != len(test.expectedChains) { - t.Errorf("wanted %d chains, got %d", len(test.expectedChains), len(chains)) + doesMatch := func(expectedChain []string, chain []*Certificate) bool { + if len(chain) != len(expectedChain) { + return false + } + + for k, cert := range chain { + if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) { + return false + } + } + return true } - // We check that each returned chain matches a chain from - // expectedChains but an entry in expectedChains can't match - // two chains. - seenChains := make([]bool, len(chains)) -NextOutputChain: - for _, chain := range chains { - TryNextExpected: - for j, expectedChain := range test.expectedChains { - if seenChains[j] { - continue + // Every expected chain should match 1 returned chain + for _, expectedChain := range test.expectedChains { + nChainMatched := 0 + for _, chain := range chains { + if doesMatch(expectedChain, chain) { + nChainMatched++ } - if len(chain) != len(expectedChain) { - continue - } - for k, cert := range chain { - if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) { - continue TryNextExpected + } + + if nChainMatched != 1 { + t.Errorf("Got %v matches instead of %v for expected chain %v", nChainMatched, 1, expectedChain) + for _, chain := range chains { + if doesMatch(expectedChain, chain) { + t.Errorf("\t matched %v", chainToDebugString(chain)) + } + } + } + } + + // Every returned chain should match 1 expected chain (or <2 if testing against the system) + for _, chain := range chains { + nMatched := 0 + for _, expectedChain := range test.expectedChains { + if doesMatch(expectedChain, chain) { + nMatched++ + } + } + // Allow additional unknown chains if systemLax is set + if nMatched == 0 && test.systemLax == false || nMatched > 1 { + t.Errorf("Got %v matches for chain %v", nMatched, chainToDebugString(chain)) + for _, expectedChain := range test.expectedChains { + if doesMatch(expectedChain, chain) { + t.Errorf("\t matched %v", expectedChain) } } - // we matched - seenChains[j] = true - continue NextOutputChain } - t.Errorf("no expected chain matched %s", chainToDebugString(chain)) } } From fdecb5c5b46a3f0b8f299d9069d428c656576dcb Mon Sep 17 00:00:00 2001 From: Johan Brandhorst Date: Sat, 1 Aug 2020 12:18:31 +0100 Subject: [PATCH 402/403] crypto/tls: add HandshakeContext method to Conn Adds the (*tls.Conn).HandshakeContext method. This allows us to pass the context provided down the call stack to eventually reach the tls.ClientHelloInfo and tls.CertificateRequestInfo structs. These contexts are exposed to the user as read-only via Context() methods. This allows users of (*tls.Config).GetCertificate and (*tls.Config).GetClientCertificate to use the context for request scoped parameters and cancellation. Replace uses of (*tls.Conn).Handshake with (*tls.Conn).HandshakeContext where appropriate, to propagate existing contexts. Fixes #32406 Change-Id: I33c228904fe82dcf57683b63627497d3eb841ff2 Reviewed-on: https://go-review.googlesource.com/c/go/+/246338 Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Trust: Roland Shoemaker Reviewed-by: Filippo Valsorda --- doc/go1.16.html | 22 +++++++++ src/crypto/tls/common.go | 21 ++++++++ src/crypto/tls/conn.go | 62 ++++++++++++++++++++++-- src/crypto/tls/handshake_client.go | 11 +++-- src/crypto/tls/handshake_client_test.go | 36 ++++++++++++++ src/crypto/tls/handshake_client_tls13.go | 3 ++ src/crypto/tls/handshake_server.go | 17 ++++--- src/crypto/tls/handshake_server_test.go | 50 ++++++++++++++++++- src/crypto/tls/handshake_server_tls13.go | 4 +- src/crypto/tls/tls.go | 55 ++++----------------- src/net/http/server.go | 2 +- src/net/http/transport.go | 10 ++-- src/net/http/transport_test.go | 2 +- 13 files changed, 226 insertions(+), 69 deletions(-) diff --git a/doc/go1.16.html b/doc/go1.16.html index 6c4d076d502..bb920a0cb8a 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -271,6 +271,21 @@ Do not send CLs removing the interior tags from such phrases. indefinitely.

+

+ (*Conn).HandshakeContext was added to + allow the user to control cancellation of an in-progress TLS Handshake. + The context provided is propagated into the + ClientHelloInfo + and CertificateRequestInfo + structs and accessible through the new + (*ClientHelloInfo).Context + and + + (*CertificateRequestInfo).Context + methods respectively. Canceling the context after the handshake has finished + has no effect. +

+

crypto/x509

@@ -405,6 +420,13 @@ Do not send CLs removing the interior tags from such phrases. Cookies set with SameSiteDefaultMode now behave according to the current spec (no attribute is set) instead of generating a SameSite key without a value.

+ +

+ The net/http package now uses the new + (*tls.Conn).HandshakeContext + with the Request context + when performing TLS handshakes in the client or server. +

diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go index 86dc0dd3b2e..1370d26fe2c 100644 --- a/src/crypto/tls/common.go +++ b/src/crypto/tls/common.go @@ -7,6 +7,7 @@ package tls import ( "bytes" "container/list" + "context" "crypto" "crypto/ecdsa" "crypto/ed25519" @@ -444,6 +445,16 @@ type ClientHelloInfo struct { // config is embedded by the GetCertificate or GetConfigForClient caller, // for use with SupportsCertificate. config *Config + + // ctx is the context of the handshake that is in progress. + ctx context.Context +} + +// Context returns the context of the handshake that is in progress. +// This context is a child of the context passed to HandshakeContext, +// if any, and is canceled when the handshake concludes. +func (c *ClientHelloInfo) Context() context.Context { + return c.ctx } // CertificateRequestInfo contains information from a server's @@ -462,6 +473,16 @@ type CertificateRequestInfo struct { // Version is the TLS version that was negotiated for this connection. Version uint16 + + // ctx is the context of the handshake that is in progress. + ctx context.Context +} + +// Context returns the context of the handshake that is in progress. +// This context is a child of the context passed to HandshakeContext, +// if any, and is canceled when the handshake concludes. +func (c *CertificateRequestInfo) Context() context.Context { + return c.ctx } // RenegotiationSupport enumerates the different levels of support for TLS diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index b9a1095862a..2f5d4303c25 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -8,6 +8,7 @@ package tls import ( "bytes" + "context" "crypto/cipher" "crypto/subtle" "crypto/x509" @@ -26,7 +27,7 @@ type Conn struct { // constant conn net.Conn isClient bool - handshakeFn func() error // (*Conn).clientHandshake or serverHandshake + handshakeFn func(context.Context) error // (*Conn).clientHandshake or serverHandshake // handshakeStatus is 1 if the connection is currently transferring // application data (i.e. is not currently processing a handshake). @@ -1192,7 +1193,7 @@ func (c *Conn) handleRenegotiation() error { defer c.handshakeMutex.Unlock() atomic.StoreUint32(&c.handshakeStatus, 0) - if c.handshakeErr = c.clientHandshake(); c.handshakeErr == nil { + if c.handshakeErr = c.clientHandshake(context.Background()); c.handshakeErr == nil { c.handshakes++ } return c.handshakeErr @@ -1375,8 +1376,61 @@ func (c *Conn) closeNotify() error { // first Read or Write will call it automatically. // // For control over canceling or setting a timeout on a handshake, use -// the Dialer's DialContext method. +// HandshakeContext or the Dialer's DialContext method instead. func (c *Conn) Handshake() error { + return c.HandshakeContext(context.Background()) +} + +// HandshakeContext runs the client or server handshake +// protocol if it has not yet been run. +// +// The provided Context must be non-nil. If the context is canceled before +// the handshake is complete, the handshake is interrupted and an error is returned. +// Once the handshake has completed, cancellation of the context will not affect the +// connection. +// +// Most uses of this package need not call HandshakeContext explicitly: the +// first Read or Write will call it automatically. +func (c *Conn) HandshakeContext(ctx context.Context) error { + // Delegate to unexported method for named return + // without confusing documented signature. + return c.handshakeContext(ctx) +} + +func (c *Conn) handshakeContext(ctx context.Context) (ret error) { + handshakeCtx, cancel := context.WithCancel(ctx) + // Note: defer this before starting the "interrupter" goroutine + // so that we can tell the difference between the input being canceled and + // this cancellation. In the former case, we need to close the connection. + defer cancel() + + // Start the "interrupter" goroutine, if this context might be canceled. + // (The background context cannot). + // + // The interrupter goroutine waits for the input context to be done and + // closes the connection if this happens before the function returns. + if ctx.Done() != nil { + done := make(chan struct{}) + interruptRes := make(chan error, 1) + defer func() { + close(done) + if ctxErr := <-interruptRes; ctxErr != nil { + // Return context error to user. + ret = ctxErr + } + }() + go func() { + select { + case <-handshakeCtx.Done(): + // Close the connection, discarding the error + _ = c.conn.Close() + interruptRes <- handshakeCtx.Err() + case <-done: + interruptRes <- nil + } + }() + } + c.handshakeMutex.Lock() defer c.handshakeMutex.Unlock() @@ -1390,7 +1444,7 @@ func (c *Conn) Handshake() error { c.in.Lock() defer c.in.Unlock() - c.handshakeErr = c.handshakeFn() + c.handshakeErr = c.handshakeFn(handshakeCtx) if c.handshakeErr == nil { c.handshakes++ } else { diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 46b0a770d53..d09a8c8ccfd 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/ecdsa" "crypto/ed25519" @@ -23,6 +24,7 @@ import ( type clientHandshakeState struct { c *Conn + ctx context.Context serverHello *serverHelloMsg hello *clientHelloMsg suite *cipherSuite @@ -133,7 +135,7 @@ func (c *Conn) makeClientHello() (*clientHelloMsg, ecdheParameters, error) { return hello, params, nil } -func (c *Conn) clientHandshake() (err error) { +func (c *Conn) clientHandshake(ctx context.Context) (err error) { if c.config == nil { c.config = defaultConfig() } @@ -197,6 +199,7 @@ func (c *Conn) clientHandshake() (err error) { if c.vers == VersionTLS13 { hs := &clientHandshakeStateTLS13{ c: c, + ctx: ctx, serverHello: serverHello, hello: hello, ecdheParams: ecdheParams, @@ -211,6 +214,7 @@ func (c *Conn) clientHandshake() (err error) { hs := &clientHandshakeState{ c: c, + ctx: ctx, serverHello: serverHello, hello: hello, session: session, @@ -539,7 +543,7 @@ func (hs *clientHandshakeState) doFullHandshake() error { certRequested = true hs.finishedHash.Write(certReq.marshal()) - cri := certificateRequestInfoFromMsg(c.vers, certReq) + cri := certificateRequestInfoFromMsg(hs.ctx, c.vers, certReq) if chainToSend, err = c.getClientCertificate(cri); err != nil { c.sendAlert(alertInternalError) return err @@ -879,10 +883,11 @@ func (c *Conn) verifyServerCertificate(certificates [][]byte) error { // certificateRequestInfoFromMsg generates a CertificateRequestInfo from a TLS // <= 1.2 CertificateRequest, making an effort to fill in missing information. -func certificateRequestInfoFromMsg(vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { +func certificateRequestInfoFromMsg(ctx context.Context, vers uint16, certReq *certificateRequestMsg) *CertificateRequestInfo { cri := &CertificateRequestInfo{ AcceptableCAs: certReq.certificateAuthorities, Version: vers, + ctx: ctx, } var rsaAvail, ecAvail bool diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index 12b0254123e..8889e2c8c33 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto/rsa" "crypto/x509" "encoding/base64" @@ -20,6 +21,7 @@ import ( "os/exec" "path/filepath" "reflect" + "runtime" "strconv" "strings" "testing" @@ -2511,3 +2513,37 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) { serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps) } } + +func TestClientHandshakeContextCancellation(t *testing.T) { + c, s := localPipe(t) + serverConfig := testConfig.Clone() + serverErr := make(chan error, 1) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go func() { + defer close(serverErr) + defer s.Close() + conn := Server(s, serverConfig) + _, err := conn.readClientHello(ctx) + cancel() + serverErr <- err + }() + cli := Client(c, testConfig) + err := cli.HandshakeContext(ctx) + if err == nil { + t.Fatal("Client handshake did not error when the context was canceled") + } + if err != context.Canceled { + t.Errorf("Unexpected client handshake error: %v", err) + } + if err := <-serverErr; err != nil { + t.Errorf("Unexpected server error: %v", err) + } + if runtime.GOARCH == "wasm" { + t.Skip("conn.Close does not error as expected when called multiple times on WASM") + } + err = cli.Close() + if err == nil { + t.Error("Client connection was not closed when the context was canceled") + } +} diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 9c61105cf73..0e4b3800352 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/hmac" "crypto/rsa" @@ -17,6 +18,7 @@ import ( type clientHandshakeStateTLS13 struct { c *Conn + ctx context.Context serverHello *serverHelloMsg hello *clientHelloMsg ecdheParams ecdheParameters @@ -549,6 +551,7 @@ func (hs *clientHandshakeStateTLS13) sendClientCertificate() error { AcceptableCAs: hs.certReq.certificateAuthorities, SignatureSchemes: hs.certReq.supportedSignatureAlgorithms, Version: c.vers, + ctx: hs.ctx, }) if err != nil { return err diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 16d3e643f0b..1fe026ae0e0 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -5,6 +5,7 @@ package tls import ( + "context" "crypto" "crypto/ecdsa" "crypto/ed25519" @@ -22,6 +23,7 @@ import ( // It's discarded once the handshake has completed. type serverHandshakeState struct { c *Conn + ctx context.Context clientHello *clientHelloMsg hello *serverHelloMsg suite *cipherSuite @@ -36,8 +38,8 @@ type serverHandshakeState struct { } // serverHandshake performs a TLS handshake as a server. -func (c *Conn) serverHandshake() error { - clientHello, err := c.readClientHello() +func (c *Conn) serverHandshake(ctx context.Context) error { + clientHello, err := c.readClientHello(ctx) if err != nil { return err } @@ -45,6 +47,7 @@ func (c *Conn) serverHandshake() error { if c.vers == VersionTLS13 { hs := serverHandshakeStateTLS13{ c: c, + ctx: ctx, clientHello: clientHello, } return hs.handshake() @@ -52,6 +55,7 @@ func (c *Conn) serverHandshake() error { hs := serverHandshakeState{ c: c, + ctx: ctx, clientHello: clientHello, } return hs.handshake() @@ -123,7 +127,7 @@ func (hs *serverHandshakeState) handshake() error { } // readClientHello reads a ClientHello message and selects the protocol version. -func (c *Conn) readClientHello() (*clientHelloMsg, error) { +func (c *Conn) readClientHello(ctx context.Context) (*clientHelloMsg, error) { msg, err := c.readHandshake() if err != nil { return nil, err @@ -137,7 +141,7 @@ func (c *Conn) readClientHello() (*clientHelloMsg, error) { var configForClient *Config originalConfig := c.config if c.config.GetConfigForClient != nil { - chi := clientHelloInfo(c, clientHello) + chi := clientHelloInfo(ctx, c, clientHello) if configForClient, err = c.config.GetConfigForClient(chi); err != nil { c.sendAlert(alertInternalError) return nil, err @@ -219,7 +223,7 @@ func (hs *serverHandshakeState) processClientHello() error { } } - hs.cert, err = c.config.getCertificate(clientHelloInfo(c, hs.clientHello)) + hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) if err != nil { if err == errNoCertificates { c.sendAlert(alertUnrecognizedName) @@ -813,7 +817,7 @@ func (c *Conn) processCertsFromClient(certificate Certificate) error { return nil } -func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { +func clientHelloInfo(ctx context.Context, c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { supportedVersions := clientHello.supportedVersions if len(clientHello.supportedVersions) == 0 { supportedVersions = supportedVersionsFromMax(clientHello.vers) @@ -829,5 +833,6 @@ func clientHelloInfo(c *Conn, clientHello *clientHelloMsg) *ClientHelloInfo { SupportedVersions: supportedVersions, Conn: c.conn, config: c.config, + ctx: ctx, } } diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index a7a53243129..c4416c379a4 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/elliptic" "crypto/x509" @@ -17,6 +18,7 @@ import ( "os" "os/exec" "path/filepath" + "runtime" "strings" "testing" "time" @@ -36,10 +38,12 @@ func testClientHelloFailure(t *testing.T, serverConfig *Config, m handshakeMessa cli.writeRecord(recordTypeHandshake, m.marshal()) c.Close() }() + ctx := context.Background() conn := Server(s, serverConfig) - ch, err := conn.readClientHello() + ch, err := conn.readClientHello(ctx) hs := serverHandshakeState{ c: conn, + ctx: ctx, clientHello: ch, } if err == nil { @@ -1418,9 +1422,11 @@ func TestSNIGivenOnFailure(t *testing.T) { c.Close() }() conn := Server(s, serverConfig) - ch, err := conn.readClientHello() + ctx := context.Background() + ch, err := conn.readClientHello(ctx) hs := serverHandshakeState{ c: conn, + ctx: ctx, clientHello: ch, } if err == nil { @@ -1673,3 +1679,43 @@ func TestMultipleCertificates(t *testing.T) { t.Errorf("expected RSA certificate, got %v", got) } } + +func TestServerHandshakeContextCancellation(t *testing.T) { + c, s := localPipe(t) + clientConfig := testConfig.Clone() + clientErr := make(chan error, 1) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go func() { + defer close(clientErr) + defer c.Close() + clientHello := &clientHelloMsg{ + vers: VersionTLS10, + random: make([]byte, 32), + cipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA}, + compressionMethods: []uint8{compressionNone}, + } + cli := Client(c, clientConfig) + _, err := cli.writeRecord(recordTypeHandshake, clientHello.marshal()) + cancel() + clientErr <- err + }() + conn := Server(s, testConfig) + err := conn.HandshakeContext(ctx) + if err == nil { + t.Fatal("Server handshake did not error when the context was canceled") + } + if err != context.Canceled { + t.Errorf("Unexpected server handshake error: %v", err) + } + if err := <-clientErr; err != nil { + t.Errorf("Unexpected client error: %v", err) + } + if runtime.GOARCH == "wasm" { + t.Skip("conn.Close does not error as expected when called multiple times on WASM") + } + err = conn.Close() + if err == nil { + t.Error("Server connection was not closed when the context was canceled") + } +} diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index 92d55e0293a..25c37b92c54 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -6,6 +6,7 @@ package tls import ( "bytes" + "context" "crypto" "crypto/hmac" "crypto/rsa" @@ -23,6 +24,7 @@ const maxClientPSKIdentities = 5 type serverHandshakeStateTLS13 struct { c *Conn + ctx context.Context clientHello *clientHelloMsg hello *serverHelloMsg sentDummyCCS bool @@ -361,7 +363,7 @@ func (hs *serverHandshakeStateTLS13) pickCertificate() error { return c.sendAlert(alertMissingExtension) } - certificate, err := c.config.getCertificate(clientHelloInfo(c, hs.clientHello)) + certificate, err := c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello)) if err != nil { if err == errNoCertificates { c.sendAlert(alertUnrecognizedName) diff --git a/src/crypto/tls/tls.go b/src/crypto/tls/tls.go index 454aa0bbbc0..bf577cadeaa 100644 --- a/src/crypto/tls/tls.go +++ b/src/crypto/tls/tls.go @@ -25,7 +25,6 @@ import ( "io/ioutil" "net" "strings" - "time" ) // Server returns a new TLS server side connection @@ -116,28 +115,16 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (* } func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { - // We want the Timeout and Deadline values from dialer to cover the - // whole process: TCP connection and TLS handshake. This means that we - // also need to start our own timers now. - timeout := netDialer.Timeout + if netDialer.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout) + defer cancel() + } if !netDialer.Deadline.IsZero() { - deadlineTimeout := time.Until(netDialer.Deadline) - if timeout == 0 || deadlineTimeout < timeout { - timeout = deadlineTimeout - } - } - - // hsErrCh is non-nil if we might not wait for Handshake to complete. - var hsErrCh chan error - if timeout != 0 || ctx.Done() != nil { - hsErrCh = make(chan error, 2) - } - if timeout != 0 { - timer := time.AfterFunc(timeout, func() { - hsErrCh <- timeoutError{} - }) - defer timer.Stop() + var cancel context.CancelFunc + ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline) + defer cancel() } rawConn, err := netDialer.DialContext(ctx, network, addr) @@ -164,34 +151,10 @@ func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, conf } conn := Client(rawConn, config) - - if hsErrCh == nil { - err = conn.Handshake() - } else { - go func() { - hsErrCh <- conn.Handshake() - }() - - select { - case <-ctx.Done(): - err = ctx.Err() - case err = <-hsErrCh: - if err != nil { - // If the error was due to the context - // closing, prefer the context's error, rather - // than some random network teardown error. - if e := ctx.Err(); e != nil { - err = e - } - } - } - } - - if err != nil { + if err := conn.HandshakeContext(ctx); err != nil { rawConn.Close() return nil, err } - return conn, nil } diff --git a/src/net/http/server.go b/src/net/http/server.go index 4776d960e57..6c7d2817051 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -1831,7 +1831,7 @@ func (c *conn) serve(ctx context.Context) { if d := c.server.WriteTimeout; d != 0 { c.rwc.SetWriteDeadline(time.Now().Add(d)) } - if err := tlsConn.Handshake(); err != nil { + if err := tlsConn.HandshakeContext(ctx); err != nil { // If the handshake failed due to the client not speaking // TLS, assume they're speaking plaintext HTTP and write a // 400 response on the TLS conn's underlying net.Conn. diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 29d7434f2a8..65ba6644154 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -1502,7 +1502,7 @@ func (t *Transport) decConnsPerHost(key connectMethodKey) { // Add TLS to a persistent connection, i.e. negotiate a TLS session. If pconn is already a TLS // tunnel, this function establishes a nested TLS session inside the encrypted channel. // The remote endpoint's name may be overridden by TLSClientConfig.ServerName. -func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) error { +func (pconn *persistConn) addTLS(ctx context.Context, name string, trace *httptrace.ClientTrace) error { // Initiate TLS and check remote host name against certificate. cfg := cloneTLSConfig(pconn.t.TLSClientConfig) if cfg.ServerName == "" { @@ -1524,7 +1524,7 @@ func (pconn *persistConn) addTLS(name string, trace *httptrace.ClientTrace) erro if trace != nil && trace.TLSHandshakeStart != nil { trace.TLSHandshakeStart() } - err := tlsConn.Handshake() + err := tlsConn.HandshakeContext(ctx) if timer != nil { timer.Stop() } @@ -1580,7 +1580,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers if trace != nil && trace.TLSHandshakeStart != nil { trace.TLSHandshakeStart() } - if err := tc.Handshake(); err != nil { + if err := tc.HandshakeContext(ctx); err != nil { go pconn.conn.Close() if trace != nil && trace.TLSHandshakeDone != nil { trace.TLSHandshakeDone(tls.ConnectionState{}, err) @@ -1604,7 +1604,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers if firstTLSHost, _, err = net.SplitHostPort(cm.addr()); err != nil { return nil, wrapErr(err) } - if err = pconn.addTLS(firstTLSHost, trace); err != nil { + if err = pconn.addTLS(ctx, firstTLSHost, trace); err != nil { return nil, wrapErr(err) } } @@ -1718,7 +1718,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers } if cm.proxyURL != nil && cm.targetScheme == "https" { - if err := pconn.addTLS(cm.tlsHost(), trace); err != nil { + if err := pconn.addTLS(ctx, cm.tlsHost(), trace); err != nil { return nil, err } } diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index e69133e7868..9086507d576 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -3735,7 +3735,7 @@ func TestTransportDialTLSContext(t *testing.T) { if err != nil { return nil, err } - return c, c.Handshake() + return c, c.HandshakeContext(ctx) } req, err := NewRequest("GET", ts.URL, nil) From 01cdd365a9c9e934d878553016377dc476c3fa4f Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Mon, 31 Aug 2020 17:09:57 -0400 Subject: [PATCH 403/403] crypto/tls: drop macFunction abstraction Since we dropped SSLv3, there is only one MAC scheme, and it doesn't need any state beyond a keyed HMAC, so we can replace the macFunction with the hash.Hash it wraps. Pointed out by mtp@. Change-Id: I5545be0e6ccb34a3055fad7f6cb5f628ff748e9f Reviewed-on: https://go-review.googlesource.com/c/go/+/251859 Run-TryBot: Filippo Valsorda TryBot-Result: Go Bot Reviewed-by: Roland Shoemaker Trust: Roland Shoemaker Trust: Filippo Valsorda --- src/crypto/tls/cipher_suites.go | 51 +++++++++--------------------- src/crypto/tls/conn.go | 46 +++++++++++++-------------- src/crypto/tls/handshake_client.go | 7 ++-- src/crypto/tls/handshake_server.go | 7 ++-- 4 files changed, 45 insertions(+), 66 deletions(-) diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go index ea16ef95bf0..9a356758fbf 100644 --- a/src/crypto/tls/cipher_suites.go +++ b/src/crypto/tls/cipher_suites.go @@ -160,7 +160,7 @@ type cipherSuite struct { // flags is a bitmask of the suite* values, above. flags int cipher func(key, iv []byte, isRead bool) interface{} - mac func(version uint16, macKey []byte) macFunction + mac func(key []byte) hash.Hash aead func(key, fixedNonce []byte) aead } @@ -247,24 +247,15 @@ func cipherAES(key, iv []byte, isRead bool) interface{} { return cipher.NewCBCEncrypter(block, iv) } -// macSHA1 returns a macFunction for the given protocol version. -func macSHA1(version uint16, key []byte) macFunction { - return tls10MAC{h: hmac.New(newConstantTimeHash(sha1.New), key)} +// macSHA1 returns a SHA-1 based constant time MAC. +func macSHA1(key []byte) hash.Hash { + return hmac.New(newConstantTimeHash(sha1.New), key) } -// macSHA256 returns a SHA-256 based MAC. These are only supported in TLS 1.2 -// so the given version is ignored. -func macSHA256(version uint16, key []byte) macFunction { - return tls10MAC{h: hmac.New(sha256.New, key)} -} - -type macFunction interface { - // Size returns the length of the MAC. - Size() int - // MAC appends the MAC of (seq, header, data) to out. The extra data is fed - // into the MAC after obtaining the result to normalize timing. The result - // is only valid until the next invocation of MAC as the buffer is reused. - MAC(seq, header, data, extra []byte) []byte +// macSHA256 returns a SHA-256 based MAC. This is only supported in TLS 1.2 and +// is currently only used in disabled-by-default cipher suites. +func macSHA256(key []byte) hash.Hash { + return hmac.New(sha256.New, key) } type aead interface { @@ -412,26 +403,14 @@ func newConstantTimeHash(h func() hash.Hash) func() hash.Hash { } // tls10MAC implements the TLS 1.0 MAC function. RFC 2246, Section 6.2.3. -type tls10MAC struct { - h hash.Hash - buf []byte -} - -func (s tls10MAC) Size() int { - return s.h.Size() -} - -// MAC is guaranteed to take constant time, as long as -// len(seq)+len(header)+len(data)+len(extra) is constant. extra is not fed into -// the MAC, but is only provided to make the timing profile constant. -func (s tls10MAC) MAC(seq, header, data, extra []byte) []byte { - s.h.Reset() - s.h.Write(seq) - s.h.Write(header) - s.h.Write(data) - res := s.h.Sum(s.buf[:0]) +func tls10MAC(h hash.Hash, out, seq, header, data, extra []byte) []byte { + h.Reset() + h.Write(seq) + h.Write(header) + h.Write(data) + res := h.Sum(out) if extra != nil { - s.h.Write(extra) + h.Write(extra) } return res } diff --git a/src/crypto/tls/conn.go b/src/crypto/tls/conn.go index 2f5d4303c25..2788c3c3934 100644 --- a/src/crypto/tls/conn.go +++ b/src/crypto/tls/conn.go @@ -14,6 +14,7 @@ import ( "crypto/x509" "errors" "fmt" + "hash" "io" "net" "sync" @@ -155,15 +156,16 @@ func (c *Conn) SetWriteDeadline(t time.Time) error { type halfConn struct { sync.Mutex - err error // first permanent error - version uint16 // protocol version - cipher interface{} // cipher algorithm - mac macFunction - seq [8]byte // 64-bit sequence number - additionalData [13]byte // to avoid allocs; interface method args escape + err error // first permanent error + version uint16 // protocol version + cipher interface{} // cipher algorithm + mac hash.Hash + seq [8]byte // 64-bit sequence number + + scratchBuf [13]byte // to avoid allocs; interface method args escape nextCipher interface{} // next encryption state - nextMac macFunction // next MAC algorithm + nextMac hash.Hash // next MAC algorithm trafficSecret []byte // current TLS 1.3 traffic secret } @@ -188,7 +190,7 @@ func (hc *halfConn) setErrorLocked(err error) error { // prepareCipherSpec sets the encryption and MAC states // that a subsequent changeCipherSpec will use. -func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac macFunction) { +func (hc *halfConn) prepareCipherSpec(version uint16, cipher interface{}, mac hash.Hash) { hc.version = version hc.nextCipher = cipher hc.nextMac = mac @@ -350,15 +352,14 @@ func (hc *halfConn) decrypt(record []byte) ([]byte, recordType, error) { } payload = payload[explicitNonceLen:] - additionalData := hc.additionalData[:] + var additionalData []byte if hc.version == VersionTLS13 { additionalData = record[:recordHeaderLen] } else { - copy(additionalData, hc.seq[:]) - copy(additionalData[8:], record[:3]) + additionalData = append(hc.scratchBuf[:0], hc.seq[:]...) + additionalData = append(additionalData, record[:3]...) n := len(payload) - c.Overhead() - additionalData[11] = byte(n >> 8) - additionalData[12] = byte(n) + additionalData = append(additionalData, byte(n>>8), byte(n)) } var err error @@ -424,7 +425,7 @@ func (hc *halfConn) decrypt(record []byte) ([]byte, recordType, error) { record[3] = byte(n >> 8) record[4] = byte(n) remoteMAC := payload[n : n+macSize] - localMAC := hc.mac.MAC(hc.seq[0:], record[:recordHeaderLen], payload[:n], payload[n+macSize:]) + localMAC := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload[:n], payload[n+macSize:]) // This is equivalent to checking the MACs and paddingGood // separately, but in constant-time to prevent distinguishing @@ -460,7 +461,7 @@ func sliceForAppend(in []byte, n int) (head, tail []byte) { } // encrypt encrypts payload, adding the appropriate nonce and/or MAC, and -// appends it to record, which contains the record header. +// appends it to record, which must already contain the record header. func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, error) { if hc.cipher == nil { return append(record, payload...), nil @@ -477,7 +478,7 @@ func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, err // an 8 bytes nonce but its nonces must be unpredictable (see RFC // 5246, Appendix F.3), forcing us to use randomness. That's not // 3DES' biggest problem anyway because the birthday bound on block - // collision is reached first due to its simlarly small block size + // collision is reached first due to its similarly small block size // (see the Sweet32 attack). copy(explicitNonce, hc.seq[:]) } else { @@ -487,14 +488,10 @@ func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, err } } - var mac []byte - if hc.mac != nil { - mac = hc.mac.MAC(hc.seq[:], record[:recordHeaderLen], payload, nil) - } - var dst []byte switch c := hc.cipher.(type) { case cipher.Stream: + mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil) record, dst = sliceForAppend(record, len(payload)+len(mac)) c.XORKeyStream(dst[:len(payload)], payload) c.XORKeyStream(dst[len(payload):], mac) @@ -518,11 +515,12 @@ func (hc *halfConn) encrypt(record, payload []byte, rand io.Reader) ([]byte, err record = c.Seal(record[:recordHeaderLen], nonce, record[recordHeaderLen:], record[:recordHeaderLen]) } else { - copy(hc.additionalData[:], hc.seq[:]) - copy(hc.additionalData[8:], record) - record = c.Seal(record, nonce, payload, hc.additionalData[:]) + additionalData := append(hc.scratchBuf[:0], hc.seq[:]...) + additionalData = append(additionalData, record[:recordHeaderLen]...) + record = c.Seal(record, nonce, payload, additionalData) } case cbcMode: + mac := tls10MAC(hc.mac, hc.scratchBuf[:0], hc.seq[:], record[:recordHeaderLen], payload, nil) blockSize := c.BlockSize() plaintextLen := len(payload) + len(mac) paddingLen := blockSize - plaintextLen%blockSize diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index d09a8c8ccfd..123df7b07a0 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -15,6 +15,7 @@ import ( "crypto/x509" "errors" "fmt" + "hash" "io" "net" "strings" @@ -651,12 +652,12 @@ func (hs *clientHandshakeState) establishKeys() error { clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV := keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) var clientCipher, serverCipher interface{} - var clientHash, serverHash macFunction + var clientHash, serverHash hash.Hash if hs.suite.cipher != nil { clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */) - clientHash = hs.suite.mac(c.vers, clientMAC) + clientHash = hs.suite.mac(clientMAC) serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */) - serverHash = hs.suite.mac(c.vers, serverMAC) + serverHash = hs.suite.mac(serverMAC) } else { clientCipher = hs.suite.aead(clientKey, clientIV) serverCipher = hs.suite.aead(serverKey, serverIV) diff --git a/src/crypto/tls/handshake_server.go b/src/crypto/tls/handshake_server.go index 1fe026ae0e0..73df19d10f5 100644 --- a/src/crypto/tls/handshake_server.go +++ b/src/crypto/tls/handshake_server.go @@ -14,6 +14,7 @@ import ( "crypto/x509" "errors" "fmt" + "hash" "io" "sync/atomic" "time" @@ -645,13 +646,13 @@ func (hs *serverHandshakeState) establishKeys() error { keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen) var clientCipher, serverCipher interface{} - var clientHash, serverHash macFunction + var clientHash, serverHash hash.Hash if hs.suite.aead == nil { clientCipher = hs.suite.cipher(clientKey, clientIV, true /* for reading */) - clientHash = hs.suite.mac(c.vers, clientMAC) + clientHash = hs.suite.mac(clientMAC) serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */) - serverHash = hs.suite.mac(c.vers, serverMAC) + serverHash = hs.suite.mac(serverMAC) } else { clientCipher = hs.suite.aead(clientKey, clientIV) serverCipher = hs.suite.aead(serverKey, serverIV)