diff --git a/doc/go1.16.html b/doc/go1.16.html index 6e371b9617..6618240ed1 100644 --- a/doc/go1.16.html +++ b/doc/go1.16.html @@ -80,17 +80,16 @@ Do not send CLs removing the interior tags from such phrases.

Go command

-

- TODO - - - - - -

-

Modules

+

+ Module-aware mode is enabled by default, regardless of whether a + go.mod file is present in the current working directory or a + parent directory. Specifically, the GO111MODULE environment + variable now defaults to on. To switch to the previous behavior, + set GO111MODULE to auto. +

+

Build commands like go build and go test no longer modify go.mod and go.sum @@ -107,9 +106,7 @@ Do not send CLs removing the interior tags from such phrases. install to build and install packages in module-aware mode, ignoring the go.mod file in the current directory or any parent directory, if there is one. This is useful for installing executables without - affecting the dependencies of the main module.
- TODO: write and link to section in golang.org/ref/mod
- TODO: write and link to blog post + affecting the dependencies of the main module.

@@ -127,8 +124,6 @@ Do not send CLs removing the interior tags from such phrases. to indicate that certain published versions of the module should not be used by other modules. A module author may retract a version after a severe problem is discovered or if the version was published unintentionally.
- TODO: write and link to section in golang.org/ref/mod
- TODO: write and link to tutorial or blog post

@@ -138,6 +133,14 @@ Do not send CLs removing the interior tags from such phrases. resolving missing packages.

+

+ The go command now ignores requirements on module versions + excluded by exclude directives in the main module. Previously, + the go command used the next version higher than an excluded + version, but that version could change over time, resulting in + non-reproducible builds. +

+

go test

@@ -150,6 +153,15 @@ Do not send CLs removing the interior tags from such phrases. that is still considered to be a passing test.

+

+ go test reports an error when the -c + or -i flags are used together with unknown flags. Normally, + unknown flags are passed to tests, but when -c or -i + are used, tests are not run. +

+ +

go get

+

The go get -insecure flag is deprecated and will be removed in a future version. This flag permits @@ -161,8 +173,6 @@ 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 @@ -171,6 +181,21 @@ Do not send CLs removing the interior tags from such phrases. to patch even newly-added dependencies.)

+

GOVCS environment variable

+ +

+ GOVCS is a new environment variable that limits which version + control tools the go command may use to download source code. + This mitigates security issues with tools that are typically used in trusted, + authenticated environments. By default, git and hg + may be used to download code from any repository. svn, + bzr, and fossil may only be used to download code + from repositories with module paths or package paths matching patterns in + the GOPRIVATE environment variable. See + go + help vcs for details. +

+

The all pattern

@@ -380,7 +405,8 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/246637: make config.Clone return nil if the source is nil + Config.Clone now returns + a nil *Config if the source is nil, rather than panicking.

@@ -416,7 +442,9 @@ Do not send CLs removing the interior tags from such phrases.

- TODO: https://golang.org/cl/257257: return additional chains from Verify on Windows + On Windows, Certificate.Verify + will now return all certificate chains that are built by the platform + certificate verifier, instead of just the highest ranked chain.

@@ -425,16 +453,26 @@ Do not send CLs removing the interior tags from such phrases. +

encoding/asn1
+
+

+ Unmarshal and + UnmarshalWithParams + now return an error instead of panic when the argument is not + a pointer or is nil. This change matches the behavior of other + encoding packages such as encoding/json. +

+
+
+
encoding/json
-

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

-

- TODO: https://golang.org/cl/234818: allow semicolon in field key / struct tag + The json struct field tags understood by + Marshal, + Unmarshal, + and related functionality now permit semicolon characters within + a JSON object name for a Go struct field.

@@ -580,7 +618,10 @@ Do not send CLs removing the interior tags from such phrases.
os

- TODO: https://golang.org/cl/242998: export errFinished as ErrProcessDone + Process.Signal now + returns ErrProcessDone + instead of the unexported errFinished when the process has + already finished.

@@ -636,7 +677,10 @@ Do not send CLs removing the interior tags from such phrases.
runtime/debug

- TODO: https://golang.org/cl/249677: provide Addr method for errors from SetPanicOnFault + The runtime.Error values + used when SetPanicOnFault is enabled may now have an + Addr method. If that method exists, it returns the memory + address that triggered the fault.

@@ -672,8 +716,9 @@ Do not send CLs removing the interior tags from such phrases.
text/template
-

- TODO: https://golang.org/cl/254257: allow newlines inside action delimiters +

+ Newlines characters are now allowed inside action delimiters, + permitting actions to span multiple lines.

diff --git a/doc/go1.html b/doc/go1.html index 34e305b93c..939ee24df5 100644 --- a/doc/go1.html +++ b/doc/go1.html @@ -1647,14 +1647,14 @@ c := signal.Incoming() is

-c := make(chan os.Signal)
+c := make(chan os.Signal, 1)
 signal.Notify(c) // ask for all signals
 

but most code should list the specific signals it wants to handle instead:

-c := make(chan os.Signal)
+c := make(chan os.Signal, 1)
 signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
 
diff --git a/src/bufio/bufio_test.go b/src/bufio/bufio_test.go index 75086f1f24..d7b34bd0d8 100644 --- a/src/bufio/bufio_test.go +++ b/src/bufio/bufio_test.go @@ -146,7 +146,7 @@ func TestReader(t *testing.T) { for i := 0; i < len(texts)-1; i++ { texts[i] = str + "\n" all += texts[i] - str += string(rune(i)%26 + 'a') + str += string(rune(i%26 + 'a')) } texts[len(texts)-1] = all diff --git a/src/cmd/asm/internal/asm/testdata/riscvenc.s b/src/cmd/asm/internal/asm/testdata/riscvenc.s index e30a576473..9a49d96ca0 100644 --- a/src/cmd/asm/internal/asm/testdata/riscvenc.s +++ b/src/cmd/asm/internal/asm/testdata/riscvenc.s @@ -340,11 +340,11 @@ start: // Branch pseudo-instructions BEQZ X5, start // BEQZ X5, 2 // e38602c0 BGEZ X5, start // BGEZ X5, 2 // e3d402c0 - BGT X5, X6, start // BGT X5, X6, 2 // e3c262c0 - BGTU X5, X6, start // BGTU X5, X6, 2 // e3e062c0 + BGT X5, X6, start // BGT X5, X6, 2 // e34253c0 + BGTU X5, X6, start // BGTU X5, X6, 2 // e36053c0 BGTZ X5, start // BGTZ X5, 2 // e34e50be - BLE X5, X6, start // BLE X5, X6, 2 // e3dc62be - BLEU X5, X6, start // BLEU X5, X6, 2 // e3fa62be + BLE X5, X6, start // BLE X5, X6, 2 // e35c53be + BLEU X5, X6, start // BLEU X5, X6, 2 // e37a53be BLEZ X5, start // BLEZ X5, 2 // e35850be BLTZ X5, start // BLTZ X5, 2 // e3c602be BNEZ X5, start // BNEZ X5, 2 // e39402be diff --git a/src/cmd/buildid/buildid.go b/src/cmd/buildid/buildid.go index 699d977950..8e02a7ae10 100644 --- a/src/cmd/buildid/buildid.go +++ b/src/cmd/buildid/buildid.go @@ -62,7 +62,7 @@ func main() { return } - f, err = os.OpenFile(file, os.O_WRONLY, 0) + f, err = os.OpenFile(file, os.O_RDWR, 0) if err != nil { log.Fatal(err) } diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go index e372259c78..6625ccf5e2 100644 --- a/src/cmd/compile/fmt_test.go +++ b/src/cmd/compile/fmt_test.go @@ -52,6 +52,7 @@ import ( "go/types" "internal/testenv" "io" + "io/fs" "io/ioutil" "log" "os" @@ -89,7 +90,7 @@ func TestFormats(t *testing.T) { testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok // process all directories - filepath.Walk(".", func(path string, info os.FileInfo, err error) error { + filepath.WalkDir(".", func(path string, info fs.DirEntry, err error) error { if info.IsDir() { if info.Name() == "testdata" { return filepath.SkipDir diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index ec2c67c1fa..e6f899a2c7 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -790,10 +790,10 @@ func (f *Func) spSb() (sp, sb *Value) { } } if sb == nil { - sb = f.Entry.NewValue0(initpos, OpSB, f.Config.Types.Uintptr) + sb = f.Entry.NewValue0(initpos.WithNotStmt(), OpSB, f.Config.Types.Uintptr) } if sp == nil { - sp = f.Entry.NewValue0(initpos, OpSP, f.Config.Types.Uintptr) + sp = f.Entry.NewValue0(initpos.WithNotStmt(), OpSP, f.Config.Types.Uintptr) } return } diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules index 946acd4ccc..6637c6cae4 100644 --- a/src/cmd/compile/internal/ssa/gen/ARM.rules +++ b/src/cmd/compile/internal/ssa/gen/ARM.rules @@ -1369,38 +1369,38 @@ (LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftLLreg x y z) yes no) (LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftRLreg x y z) yes no) (LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (CMNshiftRAreg x y z) yes no) -(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LT (TST x y) yes no) -(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LT (TSTconst [c] x) yes no) -(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LT (TSTshiftLL x y [c]) yes no) -(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LT (TSTshiftRL x y [c]) yes no) -(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LT (TSTshiftRA x y [c]) yes no) -(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LT (TSTshiftLLreg x y z) yes no) -(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LT (TSTshiftRLreg x y z) yes no) -(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LT (TSTshiftRAreg x y z) yes no) -(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LE (TST x y) yes no) -(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LE (TSTconst [c] x) yes no) -(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LE (TSTshiftLL x y [c]) yes no) -(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LE (TSTshiftRL x y [c]) yes no) -(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LE (TSTshiftRA x y [c]) yes no) -(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LE (TSTshiftLLreg x y z) yes no) -(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LE (TSTshiftRLreg x y z) yes no) -(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LE (TSTshiftRAreg x y z) yes no) -(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LT (TEQ x y) yes no) -(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LT (TEQconst [c] x) yes no) -(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LT (TEQshiftLL x y [c]) yes no) -(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LT (TEQshiftRL x y [c]) yes no) -(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LT (TEQshiftRA x y [c]) yes no) -(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LT (TEQshiftLLreg x y z) yes no) -(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LT (TEQshiftRLreg x y z) yes no) -(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LT (TEQshiftRAreg x y z) yes no) -(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LE (TEQ x y) yes no) -(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LE (TEQconst [c] x) yes no) -(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LE (TEQshiftLL x y [c]) yes no) -(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LE (TEQshiftRL x y [c]) yes no) -(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LE (TEQshiftRA x y [c]) yes no) -(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LE (TEQshiftLLreg x y z) yes no) -(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LE (TEQshiftRLreg x y z) yes no) -(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LE (TEQshiftRAreg x y z) yes no) +(LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LTnoov (TST x y) yes no) +(LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LTnoov (TSTconst [c] x) yes no) +(LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftLL x y [c]) yes no) +(LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftRL x y [c]) yes no) +(LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (TSTshiftRA x y [c]) yes no) +(LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftLLreg x y z) yes no) +(LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftRLreg x y z) yes no) +(LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (TSTshiftRAreg x y z) yes no) +(LE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (LEnoov (TST x y) yes no) +(LE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (LEnoov (TSTconst [c] x) yes no) +(LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftLL x y [c]) yes no) +(LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftRL x y [c]) yes no) +(LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (TSTshiftRA x y [c]) yes no) +(LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftLLreg x y z) yes no) +(LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftRLreg x y z) yes no) +(LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (TSTshiftRAreg x y z) yes no) +(LT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LTnoov (TEQ x y) yes no) +(LT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LTnoov (TEQconst [c] x) yes no) +(LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftLL x y [c]) yes no) +(LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftRL x y [c]) yes no) +(LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LTnoov (TEQshiftRA x y [c]) yes no) +(LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftLLreg x y z) yes no) +(LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftRLreg x y z) yes no) +(LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LTnoov (TEQshiftRAreg x y z) yes no) +(LE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (LEnoov (TEQ x y) yes no) +(LE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (LEnoov (TEQconst [c] x) yes no) +(LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftLL x y [c]) yes no) +(LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftRL x y [c]) yes no) +(LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (LEnoov (TEQshiftRA x y [c]) yes no) +(LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftLLreg x y z) yes no) +(LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftRLreg x y z) yes no) +(LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (LEnoov (TEQshiftRAreg x y z) yes no) (GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 => (GTnoov (CMP x y) yes no) (GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 => (GTnoov (CMP a (MUL x y)) yes no) (GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 => (GTnoov (CMPconst [c] x) yes no) @@ -1436,39 +1436,39 @@ (GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftLLreg x y z) yes no) (GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftRLreg x y z) yes no) (GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (CMNshiftRAreg x y z) yes no) -(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GT (TST x y) yes no) (GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 => (GTnoov (CMN a (MUL x y)) yes no) -(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GT (TSTconst [c] x) yes no) -(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GT (TSTshiftLL x y [c]) yes no) -(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GT (TSTshiftRL x y [c]) yes no) -(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GT (TSTshiftRA x y [c]) yes no) -(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GT (TSTshiftLLreg x y z) yes no) -(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GT (TSTshiftRLreg x y z) yes no) -(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GT (TSTshiftRAreg x y z) yes no) -(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GE (TST x y) yes no) -(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GE (TSTconst [c] x) yes no) -(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GE (TSTshiftLL x y [c]) yes no) -(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GE (TSTshiftRL x y [c]) yes no) -(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GE (TSTshiftRA x y [c]) yes no) -(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GE (TSTshiftLLreg x y z) yes no) -(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GE (TSTshiftRLreg x y z) yes no) -(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GE (TSTshiftRAreg x y z) yes no) -(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GT (TEQ x y) yes no) -(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GT (TEQconst [c] x) yes no) -(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GT (TEQshiftLL x y [c]) yes no) -(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GT (TEQshiftRL x y [c]) yes no) -(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GT (TEQshiftRA x y [c]) yes no) -(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GT (TEQshiftLLreg x y z) yes no) -(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GT (TEQshiftRLreg x y z) yes no) -(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GT (TEQshiftRAreg x y z) yes no) -(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GE (TEQ x y) yes no) -(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GE (TEQconst [c] x) yes no) -(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GE (TEQshiftLL x y [c]) yes no) -(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GE (TEQshiftRL x y [c]) yes no) -(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GE (TEQshiftRA x y [c]) yes no) -(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GE (TEQshiftLLreg x y z) yes no) -(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GE (TEQshiftRLreg x y z) yes no) -(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GE (TEQshiftRAreg x y z) yes no) +(GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GTnoov (TST x y) yes no) +(GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GTnoov (TSTconst [c] x) yes no) +(GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftLL x y [c]) yes no) +(GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftRL x y [c]) yes no) +(GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (TSTshiftRA x y [c]) yes no) +(GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftLLreg x y z) yes no) +(GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftRLreg x y z) yes no) +(GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (TSTshiftRAreg x y z) yes no) +(GE (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 => (GEnoov (TST x y) yes no) +(GE (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 => (GEnoov (TSTconst [c] x) yes no) +(GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftLL x y [c]) yes no) +(GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftRL x y [c]) yes no) +(GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (TSTshiftRA x y [c]) yes no) +(GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftLLreg x y z) yes no) +(GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftRLreg x y z) yes no) +(GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (TSTshiftRAreg x y z) yes no) +(GT (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GTnoov (TEQ x y) yes no) +(GT (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GTnoov (TEQconst [c] x) yes no) +(GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftLL x y [c]) yes no) +(GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftRL x y [c]) yes no) +(GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GTnoov (TEQshiftRA x y [c]) yes no) +(GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftLLreg x y z) yes no) +(GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftRLreg x y z) yes no) +(GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GTnoov (TEQshiftRAreg x y z) yes no) +(GE (CMPconst [0] l:(XOR x y)) yes no) && l.Uses==1 => (GEnoov (TEQ x y) yes no) +(GE (CMPconst [0] l:(XORconst [c] x)) yes no) && l.Uses==1 => (GEnoov (TEQconst [c] x) yes no) +(GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftLL x y [c]) yes no) +(GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftRL x y [c]) yes no) +(GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) && l.Uses==1 => (GEnoov (TEQshiftRA x y [c]) yes no) +(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftLLreg x y z) yes no) +(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftRLreg x y z) yes no) +(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 => (GEnoov (TEQshiftRAreg x y z) yes no) (MOVBUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVWconst [int32(read8(sym, int64(off)))]) (MOVHUload [off] {sym} (SB) _) && symIsRO(sym) => (MOVWconst [int32(read16(sym, int64(off), config.ctxt.Arch.ByteOrder))]) diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go index 47fd0a94cc..68495c558c 100644 --- a/src/cmd/compile/internal/ssa/rewriteARM.go +++ b/src/cmd/compile/internal/ssa/rewriteARM.go @@ -17389,7 +17389,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (GE (CMPconst [0] l:(AND x y)) yes no) // cond: l.Uses==1 - // result: (GE (TST x y) yes no) + // result: (GEnoov (TST x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17410,14 +17410,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } break } // match: (GE (CMPconst [0] l:(ANDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GE (TSTconst [c] x) yes no) + // result: (GEnoov (TSTconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17435,12 +17435,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (TSTshiftLL x y [c]) yes no) + // result: (GEnoov (TSTshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17459,12 +17459,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (TSTshiftRL x y [c]) yes no) + // result: (GEnoov (TSTshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17483,12 +17483,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (TSTshiftRA x y [c]) yes no) + // result: (GEnoov (TSTshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17507,12 +17507,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (TSTshiftLLreg x y z) yes no) + // result: (GEnoov (TSTshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17530,12 +17530,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (TSTshiftRLreg x y z) yes no) + // result: (GEnoov (TSTshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17553,12 +17553,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (TSTshiftRAreg x y z) yes no) + // result: (GEnoov (TSTshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17576,12 +17576,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(XOR x y)) yes no) // cond: l.Uses==1 - // result: (GE (TEQ x y) yes no) + // result: (GEnoov (TEQ x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17602,14 +17602,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } break } // match: (GE (CMPconst [0] l:(XORconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GE (TEQconst [c] x) yes no) + // result: (GEnoov (TEQconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17627,12 +17627,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (TEQshiftLL x y [c]) yes no) + // result: (GEnoov (TEQshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17651,12 +17651,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (TEQshiftRL x y [c]) yes no) + // result: (GEnoov (TEQshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17675,12 +17675,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GE (TEQshiftRA x y [c]) yes no) + // result: (GEnoov (TEQshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17699,12 +17699,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (TEQshiftLLreg x y z) yes no) + // result: (GEnoov (TEQshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17722,12 +17722,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (TEQshiftRLreg x y z) yes no) + // result: (GEnoov (TEQshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17745,12 +17745,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } // match: (GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GE (TEQshiftRAreg x y z) yes no) + // result: (GEnoov (TEQshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -17768,7 +17768,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGE, v0) + b.resetWithControl(BlockARMGEnoov, v0) return true } case BlockARMGEnoov: @@ -18278,34 +18278,6 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMGTnoov, v0) return true } - // match: (GT (CMPconst [0] l:(AND x y)) yes no) - // cond: l.Uses==1 - // result: (GT (TST x y) yes no) - for b.Controls[0].Op == OpARMCMPconst { - v_0 := b.Controls[0] - if auxIntToInt32(v_0.AuxInt) != 0 { - break - } - l := v_0.Args[0] - if l.Op != OpARMAND { - break - } - _ = l.Args[1] - l_0 := l.Args[0] - l_1 := l.Args[1] - for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 { - x := l_0 - y := l_1 - if !(l.Uses == 1) { - continue - } - v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) - v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) - return true - } - break - } // match: (GT (CMPconst [0] l:(MULA x y a)) yes no) // cond: l.Uses==1 // result: (GTnoov (CMN a (MUL x y)) yes no) @@ -18331,9 +18303,37 @@ func rewriteBlockARM(b *Block) bool { b.resetWithControl(BlockARMGTnoov, v0) return true } + // match: (GT (CMPconst [0] l:(AND x y)) yes no) + // cond: l.Uses==1 + // result: (GTnoov (TST x y) yes no) + for b.Controls[0].Op == OpARMCMPconst { + v_0 := b.Controls[0] + if auxIntToInt32(v_0.AuxInt) != 0 { + break + } + l := v_0.Args[0] + if l.Op != OpARMAND { + break + } + _ = l.Args[1] + l_0 := l.Args[0] + l_1 := l.Args[1] + for _i0 := 0; _i0 <= 1; _i0, l_0, l_1 = _i0+1, l_1, l_0 { + x := l_0 + y := l_1 + if !(l.Uses == 1) { + continue + } + v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) + v0.AddArg2(x, y) + b.resetWithControl(BlockARMGTnoov, v0) + return true + } + break + } // match: (GT (CMPconst [0] l:(ANDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GT (TSTconst [c] x) yes no) + // result: (GTnoov (TSTconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18351,12 +18351,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (TSTshiftLL x y [c]) yes no) + // result: (GTnoov (TSTshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18375,12 +18375,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (TSTshiftRL x y [c]) yes no) + // result: (GTnoov (TSTshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18399,12 +18399,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (TSTshiftRA x y [c]) yes no) + // result: (GTnoov (TSTshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18423,12 +18423,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (TSTshiftLLreg x y z) yes no) + // result: (GTnoov (TSTshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18446,12 +18446,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (TSTshiftRLreg x y z) yes no) + // result: (GTnoov (TSTshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18469,12 +18469,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (TSTshiftRAreg x y z) yes no) + // result: (GTnoov (TSTshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18492,12 +18492,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(XOR x y)) yes no) // cond: l.Uses==1 - // result: (GT (TEQ x y) yes no) + // result: (GTnoov (TEQ x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18518,14 +18518,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } break } // match: (GT (CMPconst [0] l:(XORconst [c] x)) yes no) // cond: l.Uses==1 - // result: (GT (TEQconst [c] x) yes no) + // result: (GTnoov (TEQconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18543,12 +18543,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (TEQshiftLL x y [c]) yes no) + // result: (GTnoov (TEQshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18567,12 +18567,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (TEQshiftRL x y [c]) yes no) + // result: (GTnoov (TEQshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18591,12 +18591,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (GT (TEQshiftRA x y [c]) yes no) + // result: (GTnoov (TEQshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18615,12 +18615,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (TEQshiftLLreg x y z) yes no) + // result: (GTnoov (TEQshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18638,12 +18638,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (TEQshiftRLreg x y z) yes no) + // result: (GTnoov (TEQshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18661,12 +18661,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } // match: (GT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (GT (TEQshiftRAreg x y z) yes no) + // result: (GTnoov (TEQshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -18684,7 +18684,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMGT, v0) + b.resetWithControl(BlockARMGTnoov, v0) return true } case BlockARMGTnoov: @@ -19312,7 +19312,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (LE (CMPconst [0] l:(AND x y)) yes no) // cond: l.Uses==1 - // result: (LE (TST x y) yes no) + // result: (LEnoov (TST x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19333,14 +19333,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } break } // match: (LE (CMPconst [0] l:(ANDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LE (TSTconst [c] x) yes no) + // result: (LEnoov (TSTconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19358,12 +19358,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (TSTshiftLL x y [c]) yes no) + // result: (LEnoov (TSTshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19382,12 +19382,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (TSTshiftRL x y [c]) yes no) + // result: (LEnoov (TSTshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19406,12 +19406,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (TSTshiftRA x y [c]) yes no) + // result: (LEnoov (TSTshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19430,12 +19430,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (TSTshiftLLreg x y z) yes no) + // result: (LEnoov (TSTshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19453,12 +19453,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (TSTshiftRLreg x y z) yes no) + // result: (LEnoov (TSTshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19476,12 +19476,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (TSTshiftRAreg x y z) yes no) + // result: (LEnoov (TSTshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19499,12 +19499,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(XOR x y)) yes no) // cond: l.Uses==1 - // result: (LE (TEQ x y) yes no) + // result: (LEnoov (TEQ x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19525,14 +19525,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } break } // match: (LE (CMPconst [0] l:(XORconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LE (TEQconst [c] x) yes no) + // result: (LEnoov (TEQconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19550,12 +19550,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(XORshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (TEQshiftLL x y [c]) yes no) + // result: (LEnoov (TEQshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19574,12 +19574,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(XORshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (TEQshiftRL x y [c]) yes no) + // result: (LEnoov (TEQshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19598,12 +19598,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(XORshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LE (TEQshiftRA x y [c]) yes no) + // result: (LEnoov (TEQshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19622,12 +19622,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (TEQshiftLLreg x y z) yes no) + // result: (LEnoov (TEQshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19645,12 +19645,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (TEQshiftRLreg x y z) yes no) + // result: (LEnoov (TEQshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19668,12 +19668,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } // match: (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LE (TEQshiftRAreg x y z) yes no) + // result: (LEnoov (TEQshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -19691,7 +19691,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLE, v0) + b.resetWithControl(BlockARMLEnoov, v0) return true } case BlockARMLEnoov: @@ -20228,7 +20228,7 @@ func rewriteBlockARM(b *Block) bool { } // match: (LT (CMPconst [0] l:(AND x y)) yes no) // cond: l.Uses==1 - // result: (LT (TST x y) yes no) + // result: (LTnoov (TST x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20249,14 +20249,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTST, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } break } // match: (LT (CMPconst [0] l:(ANDconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LT (TSTconst [c] x) yes no) + // result: (LTnoov (TSTconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20274,12 +20274,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (TSTshiftLL x y [c]) yes no) + // result: (LTnoov (TSTshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20298,12 +20298,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (TSTshiftRL x y [c]) yes no) + // result: (LTnoov (TSTshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20322,12 +20322,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ANDshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (TSTshiftRA x y [c]) yes no) + // result: (LTnoov (TSTshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20346,12 +20346,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ANDshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (TSTshiftLLreg x y z) yes no) + // result: (LTnoov (TSTshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20369,12 +20369,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ANDshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (TSTshiftRLreg x y z) yes no) + // result: (LTnoov (TSTshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20392,12 +20392,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(ANDshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (TSTshiftRAreg x y z) yes no) + // result: (LTnoov (TSTshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20415,12 +20415,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTSTshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(XOR x y)) yes no) // cond: l.Uses==1 - // result: (LT (TEQ x y) yes no) + // result: (LTnoov (TEQ x y) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20441,14 +20441,14 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQ, types.TypeFlags) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } break } // match: (LT (CMPconst [0] l:(XORconst [c] x)) yes no) // cond: l.Uses==1 - // result: (LT (TEQconst [c] x) yes no) + // result: (LTnoov (TEQconst [c] x) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20466,12 +20466,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQconst, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg(x) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(XORshiftLL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (TEQshiftLL x y [c]) yes no) + // result: (LTnoov (TEQshiftLL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20490,12 +20490,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(XORshiftRL x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (TEQshiftRL x y [c]) yes no) + // result: (LTnoov (TEQshiftRL x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20514,12 +20514,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRL, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(XORshiftRA x y [c])) yes no) // cond: l.Uses==1 - // result: (LT (TEQshiftRA x y [c]) yes no) + // result: (LTnoov (TEQshiftRA x y [c]) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20538,12 +20538,12 @@ func rewriteBlockARM(b *Block) bool { v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRA, types.TypeFlags) v0.AuxInt = int32ToAuxInt(c) v0.AddArg2(x, y) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (TEQshiftLLreg x y z) yes no) + // result: (LTnoov (TEQshiftLLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20561,12 +20561,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftLLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (TEQshiftRLreg x y z) yes no) + // result: (LTnoov (TEQshiftRLreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20584,12 +20584,12 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRLreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } // match: (LT (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) // cond: l.Uses==1 - // result: (LT (TEQshiftRAreg x y z) yes no) + // result: (LTnoov (TEQshiftRAreg x y z) yes no) for b.Controls[0].Op == OpARMCMPconst { v_0 := b.Controls[0] if auxIntToInt32(v_0.AuxInt) != 0 { @@ -20607,7 +20607,7 @@ func rewriteBlockARM(b *Block) bool { } v0 := b.NewValue0(v_0.Pos, OpARMTEQshiftRAreg, types.TypeFlags) v0.AddArg3(x, y, z) - b.resetWithControl(BlockARMLT, v0) + b.resetWithControl(BlockARMLTnoov, v0) return true } case BlockARMLTnoov: diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 839579349a..5e1647cbf0 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -55,6 +55,7 @@ var bootstrapDirs = []string{ "cmd/compile/internal/x86", "cmd/compile/internal/wasm", "cmd/internal/bio", + "cmd/internal/codesign", "cmd/internal/gcprog", "cmd/internal/dwarf", "cmd/internal/edit", diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 2a17ab9cae..955ce2a063 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -1509,6 +1509,7 @@ func (t *tester) makeGOROOTUnwritable() (undo func()) { } gocacheSubdir, _ := filepath.Rel(dir, gocache) + // Note: Can't use WalkDir here, because this has to compile with Go 1.4. filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if suffix := strings.TrimPrefix(path, dir+string(filepath.Separator)); suffix != "" { if suffix == gocacheSubdir { diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go index 1cea9a876a..1cedf992cf 100644 --- a/src/cmd/fix/main.go +++ b/src/cmd/fix/main.go @@ -234,10 +234,10 @@ func report(err error) { } func walkDir(path string) { - filepath.Walk(path, visitFile) + filepath.WalkDir(path, visitFile) } -func visitFile(path string, f fs.FileInfo, err error) error { +func visitFile(path string, f fs.DirEntry, err error) error { if err == nil && isGoFile(f) { err = processFile(path, false) } @@ -247,7 +247,7 @@ func visitFile(path string, f fs.FileInfo, err error) error { return nil } -func isGoFile(f fs.FileInfo) bool { +func isGoFile(f fs.DirEntry) bool { // ignore non-Go files name := f.Name() return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 6f55b2d1c8..bfee2c7f06 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,7 +7,7 @@ require ( github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 // indirect golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 + golang.org/x/mod v0.4.0 golang.org/x/sys v0.0.0-20201110211018-35f3e6cf4a65 // indirect golang.org/x/tools v0.0.0-20201110201400-7099162a900a ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 8775b754d8..7a743d9f73 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -15,8 +15,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 h1:xUIPaMhvROX9dhPvRCenIJtU78+lbEenGbgqB5hfHCQ= -golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index a02231fa98..1b8a21ecfa 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -774,7 +774,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 fs.FileInfo, err error) error { + filepath.WalkDir(dir, func(path string, info fs.DirEntry, 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() { @@ -820,8 +820,8 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { } { srcdir := filepath.Join(testGOROOT, copydir) tg.tempDir(filepath.Join("goroot", copydir)) - err := filepath.Walk(srcdir, - func(path string, info fs.FileInfo, err error) error { + err := filepath.WalkDir(srcdir, + func(path string, info fs.DirEntry, err error) error { if err != nil { return err } @@ -838,8 +838,8 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) { return err } tg.tempFile(dest, string(data)) - if err := os.Chmod(tg.path(dest), info.Mode()|0200); err != nil { - return err + if strings.Contains(copydir, filepath.Join("pkg", "tool")) { + os.Chmod(tg.path(dest), 0777) } return nil }) diff --git a/src/cmd/go/internal/base/signal.go b/src/cmd/go/internal/base/signal.go index 54d11876d0..05befcf7f0 100644 --- a/src/cmd/go/internal/base/signal.go +++ b/src/cmd/go/internal/base/signal.go @@ -15,7 +15,7 @@ var Interrupted = make(chan struct{}) // processSignals setups signal handler. func processSignals() { - sig := make(chan os.Signal) + sig := make(chan os.Signal, 1) signal.Notify(sig, signalsToIgnore...) go func() { <-sig diff --git a/src/cmd/go/internal/modfetch/codehost/codehost.go b/src/cmd/go/internal/modfetch/codehost/codehost.go index c5fbb31b2b..286d3f7220 100644 --- a/src/cmd/go/internal/modfetch/codehost/codehost.go +++ b/src/cmd/go/internal/modfetch/codehost/codehost.go @@ -264,6 +264,9 @@ func RunWithStdin(dir string, stdin io.Reader, cmdline ...interface{}) ([]byte, } cmd := str.StringList(cmdline...) + if os.Getenv("TESTGOVCS") == "panic" { + panic(fmt.Sprintf("use of vcs: %v", cmd)) + } if cfg.BuildX { text := new(strings.Builder) if dir != "" { diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index a3e2cd1f9d..2ee78de5b2 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -318,9 +318,10 @@ func makeDirsReadOnly(dir string) { mode fs.FileMode } var dirs []pathMode // in lexical order - filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { - if err == nil && info.Mode()&0222 != 0 { - if info.IsDir() { + filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { + if err == nil && d.IsDir() { + info, err := d.Info() + if err == nil && info.Mode()&0222 != 0 { dirs = append(dirs, pathMode{path, info.Mode()}) } } @@ -337,7 +338,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 fs.FileInfo, err error) error { + filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error { if err != nil { return nil // ignore errors walking in file system } diff --git a/src/cmd/go/internal/modget/get.go b/src/cmd/go/internal/modget/get.go index ecb0142524..e5f55879ee 100644 --- a/src/cmd/go/internal/modget/get.go +++ b/src/cmd/go/internal/modget/get.go @@ -436,32 +436,9 @@ func runGet(ctx context.Context, cmd *base.Command, args []string) { 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. + // TODO(#40276): After Go 1.16, print a deprecation notice when building + // and installing main packages. 'go install pkg' or + // 'go install pkg@version' should be used instead. } if !modload.HasModRoot() { diff --git a/src/cmd/go/internal/modload/init.go b/src/cmd/go/internal/modload/init.go index a9b77c82b3..1c31a5f90a 100644 --- a/src/cmd/go/internal/modload/init.go +++ b/src/cmd/go/internal/modload/init.go @@ -1018,7 +1018,7 @@ func keepSums(addDirect bool) map[module.Version]bool { } } for _, pkg := range loaded.pkgs { - if pkg.testOf != nil || pkg.inStd { + if pkg.testOf != nil || pkg.inStd || module.CheckImportPath(pkg.path) != nil { continue } for prefix := pkg.path; prefix != "."; prefix = path.Dir(prefix) { diff --git a/src/cmd/go/internal/vcs/vcs.go b/src/cmd/go/internal/vcs/vcs.go index e7bef9f591..4894ecdc35 100644 --- a/src/cmd/go/internal/vcs/vcs.go +++ b/src/cmd/go/internal/vcs/vcs.go @@ -23,6 +23,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/search" + "cmd/go/internal/str" "cmd/go/internal/web" "golang.org/x/mod/module" @@ -539,7 +540,7 @@ func (v *Cmd) TagSync(dir, tag string) error { // A vcsPath describes how to convert an import path into a // version control system and repository name. type vcsPath struct { - prefix string // prefix this description applies to + pathPrefix string // prefix this description applies to regexp *lazyregexp.Regexp // compiled pattern for import path repo string // repository to use (expand with match of re) vcs string // version control system to use (expand with match of re) @@ -826,6 +827,20 @@ var errUnknownSite = errors.New("dynamic lookup required to find mapping") // repoRootFromVCSPaths attempts to map importPath to a repoRoot // using the mappings defined in vcsPaths. func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths []*vcsPath) (*RepoRoot, error) { + if str.HasPathPrefix(importPath, "example.net") { + // TODO(rsc): This should not be necessary, but it's required to keep + // tests like ../../testdata/script/mod_get_extra.txt from using the network. + // That script has everything it needs in the replacement set, but it is still + // doing network calls. + return nil, fmt.Errorf("no modules on example.net") + } + if importPath == "rsc.io" { + // This special case allows tests like ../../testdata/script/govcs.txt + // to avoid making any network calls. The module lookup for a path + // like rsc.io/nonexist.svn/foo needs to not make a network call for + // a lookup on rsc.io. + return nil, fmt.Errorf("rsc.io is not a module") + } // A common error is to use https://packagepath because that's what // hg and git require. Diagnose this helpfully. if prefix := httpPrefix(importPath); prefix != "" { @@ -834,20 +849,20 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths return nil, fmt.Errorf("%q not allowed in import path", prefix+"//") } for _, srv := range vcsPaths { - if !strings.HasPrefix(importPath, srv.prefix) { + if !str.HasPathPrefix(importPath, srv.pathPrefix) { continue } m := srv.regexp.FindStringSubmatch(importPath) if m == nil { - if srv.prefix != "" { - return nil, importErrorf(importPath, "invalid %s import path %q", srv.prefix, importPath) + if srv.pathPrefix != "" { + return nil, importErrorf(importPath, "invalid %s import path %q", srv.pathPrefix, importPath) } continue } // Build map of named subexpression matches for expand. match := map[string]string{ - "prefix": srv.prefix, + "prefix": srv.pathPrefix + "/", "import": importPath, } for i, name := range srv.regexp.SubexpNames() { @@ -1098,18 +1113,6 @@ type metaImport struct { Prefix, VCS, RepoRoot string } -// pathPrefix reports whether sub is a prefix of s, -// only considering entire path components. -func pathPrefix(s, sub string) bool { - // strings.HasPrefix is necessary but not sufficient. - if !strings.HasPrefix(s, sub) { - return false - } - // The remainder after the prefix must either be empty or start with a slash. - rem := s[len(sub):] - return rem == "" || rem[0] == '/' -} - // A ImportMismatchError is returned where metaImport/s are present // but none match our import path. type ImportMismatchError struct { @@ -1133,7 +1136,7 @@ func matchGoImport(imports []metaImport, importPath string) (metaImport, error) errImportMismatch := ImportMismatchError{importPath: importPath} for i, im := range imports { - if !pathPrefix(importPath, im.Prefix) { + if !str.HasPathPrefix(importPath, im.Prefix) { errImportMismatch.mismatches = append(errImportMismatch.mismatches, im.Prefix) continue } @@ -1175,52 +1178,52 @@ func expand(match map[string]string, s string) string { var vcsPaths = []*vcsPath{ // Github { - prefix: "github.com/", - regexp: lazyregexp.New(`^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`), - vcs: "git", - repo: "https://{root}", - check: noVCSSuffix, + pathPrefix: "github.com", + regexp: lazyregexp.New(`^(?Pgithub\.com/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`), + vcs: "git", + repo: "https://{root}", + check: noVCSSuffix, }, // Bitbucket { - prefix: "bitbucket.org/", - regexp: lazyregexp.New(`^(?Pbitbucket\.org/(?P[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`), - repo: "https://{root}", - check: bitbucketVCS, + pathPrefix: "bitbucket.org", + regexp: lazyregexp.New(`^(?Pbitbucket\.org/(?P[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`), + repo: "https://{root}", + check: bitbucketVCS, }, // IBM DevOps Services (JazzHub) { - prefix: "hub.jazz.net/git/", - regexp: lazyregexp.New(`^(?Phub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`), - vcs: "git", - repo: "https://{root}", - check: noVCSSuffix, + pathPrefix: "hub.jazz.net/git", + regexp: lazyregexp.New(`^(?Phub\.jazz\.net/git/[a-z0-9]+/[A-Za-z0-9_.\-]+)(/[A-Za-z0-9_.\-]+)*$`), + vcs: "git", + repo: "https://{root}", + check: noVCSSuffix, }, // Git at Apache { - prefix: "git.apache.org/", - regexp: lazyregexp.New(`^(?Pgit\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`), - vcs: "git", - repo: "https://{root}", + pathPrefix: "git.apache.org", + regexp: lazyregexp.New(`^(?Pgit\.apache\.org/[a-z0-9_.\-]+\.git)(/[A-Za-z0-9_.\-]+)*$`), + vcs: "git", + repo: "https://{root}", }, // Git at OpenStack { - prefix: "git.openstack.org/", - regexp: lazyregexp.New(`^(?Pgit\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`), - vcs: "git", - repo: "https://{root}", + pathPrefix: "git.openstack.org", + regexp: lazyregexp.New(`^(?Pgit\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)(\.git)?(/[A-Za-z0-9_.\-]+)*$`), + vcs: "git", + repo: "https://{root}", }, // chiselapp.com for fossil { - prefix: "chiselapp.com/", - regexp: lazyregexp.New(`^(?Pchiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`), - vcs: "fossil", - repo: "https://{root}", + pathPrefix: "chiselapp.com", + regexp: lazyregexp.New(`^(?Pchiselapp\.com/user/[A-Za-z0-9]+/repository/[A-Za-z0-9_.\-]+)$`), + vcs: "fossil", + repo: "https://{root}", }, // General syntax for any server. @@ -1238,11 +1241,11 @@ var vcsPaths = []*vcsPath{ var vcsPathsAfterDynamic = []*vcsPath{ // Launchpad. See golang.org/issue/11436. { - prefix: "launchpad.net/", - regexp: lazyregexp.New(`^(?Plaunchpad\.net/((?P[A-Za-z0-9_.\-]+)(?P/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`), - vcs: "bzr", - repo: "https://{root}", - check: launchpadVCS, + pathPrefix: "launchpad.net", + regexp: lazyregexp.New(`^(?Plaunchpad\.net/((?P[A-Za-z0-9_.\-]+)(?P/[A-Za-z0-9_.\-]+)?|~[A-Za-z0-9_.\-]+/(\+junk|[A-Za-z0-9_.\-]+)/[A-Za-z0-9_.\-]+))(/[A-Za-z0-9_.\-]+)*$`), + vcs: "bzr", + repo: "https://{root}", + check: launchpadVCS, }, } diff --git a/src/cmd/go/internal/version/version.go b/src/cmd/go/internal/version/version.go index 44ac24c62d..58cbd32e78 100644 --- a/src/cmd/go/internal/version/version.go +++ b/src/cmd/go/internal/version/version.go @@ -88,8 +88,15 @@ 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 fs.FileInfo, err error) error { - if info.Mode().IsRegular() || info.Mode()&fs.ModeSymlink != 0 { + filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error { + if d.Type().IsRegular() || d.Type()&fs.ModeSymlink != 0 { + info, err := d.Info() + if err != nil { + if *versionV { + fmt.Fprintf(os.Stderr, "%s: %v\n", path, err) + } + return nil + } scanFile(path, info, *versionV) } return nil @@ -120,6 +127,7 @@ func scanFile(file string, info fs.FileInfo, mustPrint bool) { } info = i } + if !isExe(file, info) { if mustPrint { fmt.Fprintf(os.Stderr, "%s: not executable file\n", file) diff --git a/src/cmd/go/internal/web/http.go b/src/cmd/go/internal/web/http.go index e0509808d6..72fa2b2ca6 100644 --- a/src/cmd/go/internal/web/http.go +++ b/src/cmd/go/internal/web/http.go @@ -80,6 +80,13 @@ func get(security SecurityMode, url *urlpkg.URL) (*Response, error) { return res, nil } + if url.Host == "localhost.localdev" { + return nil, fmt.Errorf("no such host localhost.localdev") + } + if os.Getenv("TESTGONETWORK") == "panic" && !strings.HasPrefix(url.Host, "127.0.0.1") && !strings.HasPrefix(url.Host, "0.0.0.0") { + panic("use of network: " + url.String()) + } + fetch := func(url *urlpkg.URL) (*urlpkg.URL, *http.Response, error) { // Note: The -v build flag does not mean "print logging information", // despite its historical misuse for this in GOPATH-based go get. diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index a88544e1af..3c7be5a3e3 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -647,7 +647,7 @@ func (b *Builder) updateBuildID(a *Action, target string, rewrite bool) error { } if rewrite { - w, err := os.OpenFile(target, os.O_WRONLY, 0) + w, err := os.OpenFile(target, os.O_RDWR, 0) if err != nil { return err } diff --git a/src/cmd/go/script_test.go b/src/cmd/go/script_test.go index b1d1499038..aee3742f13 100644 --- a/src/cmd/go/script_test.go +++ b/src/cmd/go/script_test.go @@ -142,6 +142,9 @@ func (ts *testScript) setup() { "goversion=" + goVersion(ts), ":=" + string(os.PathListSeparator), } + if !testenv.HasExternalNetwork() { + ts.env = append(ts.env, "TESTGONETWORK=panic", "TESTGOVCS=panic") + } if runtime.GOOS == "plan9" { ts.env = append(ts.env, "path="+testBin+string(filepath.ListSeparator)+os.Getenv("path")) diff --git a/src/cmd/go/testdata/addmod.go b/src/cmd/go/testdata/addmod.go index d1b6467c5d..71ac47fdc1 100644 --- a/src/cmd/go/testdata/addmod.go +++ b/src/cmd/go/testdata/addmod.go @@ -122,8 +122,8 @@ func main() { {Name: ".info", Data: info}, } dir = filepath.Clean(dir) - err = filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { - if !info.Mode().IsRegular() { + err = filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error { + if !info.Type().IsRegular() { return nil } name := info.Name() diff --git a/src/cmd/go/testdata/savedir.go b/src/cmd/go/testdata/savedir.go index 04902df61e..75895ee279 100644 --- a/src/cmd/go/testdata/savedir.go +++ b/src/cmd/go/testdata/savedir.go @@ -49,7 +49,7 @@ func main() { a := new(txtar.Archive) dir = filepath.Clean(dir) - filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error { + filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error { if path == dir { return nil } @@ -60,7 +60,7 @@ func main() { } return nil } - if !info.Mode().IsRegular() { + if !info.Type().IsRegular() { return nil } data, err := ioutil.ReadFile(path) diff --git a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt b/src/cmd/go/testdata/script/mod_get_deprecate_install.txt deleted file mode 100644 index 7f5bcad410..0000000000 --- a/src/cmd/go/testdata/script/mod_get_deprecate_install.txt +++ /dev/null @@ -1,22 +0,0 @@ -[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''' diff --git a/src/cmd/go/testdata/script/mod_gonoproxy.txt b/src/cmd/go/testdata/script/mod_gonoproxy.txt index 546605da21..204786969f 100644 --- a/src/cmd/go/testdata/script/mod_gonoproxy.txt +++ b/src/cmd/go/testdata/script/mod_gonoproxy.txt @@ -21,7 +21,7 @@ go get -d rsc.io/quote # Download .info files needed for 'go list -m all' later. # TODO(#42723): either 'go list -m' should not read these files, # or 'go get' and 'go mod tidy' should download them. -go list -m all +go list -m all stdout '^golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c$' # When GOPROXY is not empty but contains no entries, an error should be reported. diff --git a/src/cmd/go/testdata/script/mod_import_issue42891.txt b/src/cmd/go/testdata/script/mod_import_issue42891.txt new file mode 100644 index 0000000000..a78cab29ba --- /dev/null +++ b/src/cmd/go/testdata/script/mod_import_issue42891.txt @@ -0,0 +1,14 @@ +# If an import declaration is an absolute path, most commands should report +# an error instead of going into an infinite loop. +# Verifies golang.org/issue/42891. +go list . +stdout '^m$' + +-- go.mod -- +module m + +go 1.16 +-- m.go -- +package m + +import "/" diff --git a/src/cmd/go/testdata/script/mod_proxy_invalid.txt b/src/cmd/go/testdata/script/mod_proxy_invalid.txt index b9418b4df1..6427cc1527 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'": json: invalid character ''i'' looking for beginning of value$' +stderr '^go list -m: module rsc.io/quote: invalid response from proxy "'$GOPROXY'": 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'": json: 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'": 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 1f13d7ad69..f8b6e3e97e 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: 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 ".+": 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_sumdb_proxy.txt b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt index 7bbc3f9e19..70b8e3fc44 100644 --- a/src/cmd/go/testdata/script/mod_sumdb_proxy.txt +++ b/src/cmd/go/testdata/script/mod_sumdb_proxy.txt @@ -17,14 +17,12 @@ rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum # direct access fails (because localhost.localdev does not exist) -# The text of the error message is hard to predict because some DNS servers -# will resolve unknown domains like localhost.localdev to a real IP -# to serve ads. +# web.get is providing the error message - there's no actual network access. cp go.mod.orig go.mod env GOSUMDB=$sumdb env GOPROXY=direct ! go get -d rsc.io/fortune@v1.0.0 -stderr 'verifying.*localhost.localdev' +stderr 'verifying module: rsc.io/fortune@v1.0.0: .*: no such host localhost.localdev' rm $GOPATH/pkg/mod/cache/download/sumdb rm go.sum diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index dba2411eed..719c681a3e 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -74,7 +74,7 @@ func initParserMode() { } } -func isGoFile(f fs.FileInfo) bool { +func isGoFile(f fs.DirEntry) bool { // ignore non-Go files name := f.Name() return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") @@ -164,7 +164,7 @@ func processFile(filename string, in io.Reader, out io.Writer, stdin bool) error return err } -func visitFile(path string, f fs.FileInfo, err error) error { +func visitFile(path string, f fs.DirEntry, err error) error { if err == nil && isGoFile(f) { err = processFile(path, nil, os.Stdout, false) } @@ -177,7 +177,7 @@ func visitFile(path string, f fs.FileInfo, err error) error { } func walkDir(path string) { - filepath.Walk(path, visitFile) + filepath.WalkDir(path, visitFile) } func main() { diff --git a/src/cmd/gofmt/long_test.go b/src/cmd/gofmt/long_test.go index 28306ce83e..4a821705f1 100644 --- a/src/cmd/gofmt/long_test.go +++ b/src/cmd/gofmt/long_test.go @@ -108,12 +108,12 @@ func testFiles(t *testing.T, filenames <-chan string, done chan<- int) { func genFilenames(t *testing.T, filenames chan<- string) { defer close(filenames) - handleFile := func(filename string, fi fs.FileInfo, err error) error { + handleFile := func(filename string, d fs.DirEntry, err error) error { if err != nil { t.Error(err) return nil } - if isGoFile(fi) { + if isGoFile(d) { filenames <- filename nfiles++ } @@ -124,13 +124,13 @@ func genFilenames(t *testing.T, filenames chan<- string) { if *files != "" { for _, filename := range strings.Split(*files, ",") { fi, err := os.Stat(filename) - handleFile(filename, fi, err) + handleFile(filename, &statDirEntry{fi}, err) } return // ignore files under -root } // otherwise, test all Go files under *root - filepath.Walk(*root, handleFile) + filepath.WalkDir(*root, handleFile) } func TestAll(t *testing.T) { @@ -164,3 +164,12 @@ func TestAll(t *testing.T) { fmt.Printf("processed %d files\n", nfiles) } } + +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 } diff --git a/src/cmd/internal/buildid/buildid_test.go b/src/cmd/internal/buildid/buildid_test.go index 904c2c6f37..e832f9987e 100644 --- a/src/cmd/internal/buildid/buildid_test.go +++ b/src/cmd/internal/buildid/buildid_test.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "os" "reflect" + "strings" "testing" ) @@ -146,3 +147,33 @@ func TestFindAndHash(t *testing.T) { } } } + +func TestExcludedReader(t *testing.T) { + const s = "0123456789abcdefghijklmn" + tests := []struct { + start, end int64 // excluded range + results []string // expected results of reads + }{ + {12, 15, []string{"0123456789", "ab\x00\x00\x00fghij", "klmn"}}, // within one read + {8, 21, []string{"01234567\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "\x00lmn"}}, // across multiple reads + {10, 20, []string{"0123456789", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "klmn"}}, // a whole read + {0, 5, []string{"\x00\x00\x00\x00\x0056789", "abcdefghij", "klmn"}}, // start + {12, 24, []string{"0123456789", "ab\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00"}}, // end + } + p := make([]byte, 10) + for _, test := range tests { + r := &excludedReader{strings.NewReader(s), 0, test.start, test.end} + for _, res := range test.results { + n, err := r.Read(p) + if err != nil { + t.Errorf("read failed: %v", err) + } + if n != len(res) { + t.Errorf("unexpected number of bytes read: want %d, got %d", len(res), n) + } + if string(p[:n]) != res { + t.Errorf("unexpected bytes: want %q, got %q", res, p[:n]) + } + } + } +} diff --git a/src/cmd/internal/buildid/rewrite.go b/src/cmd/internal/buildid/rewrite.go index 5be54552a6..a7928959c4 100644 --- a/src/cmd/internal/buildid/rewrite.go +++ b/src/cmd/internal/buildid/rewrite.go @@ -6,7 +6,9 @@ package buildid import ( "bytes" + "cmd/internal/codesign" "crypto/sha256" + "debug/macho" "fmt" "io" ) @@ -26,6 +28,11 @@ func FindAndHash(r io.Reader, id string, bufSize int) (matches []int64, hash [32 zeros := make([]byte, len(id)) idBytes := []byte(id) + // For Mach-O files, we want to exclude the code signature. + // The code signature contains hashes of the whole file (except the signature + // itself), including the buildid. So the buildid cannot contain the signature. + r = excludeMachoCodeSignature(r) + // The strategy is to read the file through buf, looking for id, // but we need to worry about what happens if id is broken up // and returned in parts by two different reads. @@ -87,5 +94,69 @@ func Rewrite(w io.WriterAt, pos []int64, id string) error { return err } } + + // Update Mach-O code signature, if any. + if f, cmd, ok := findMachoCodeSignature(w); ok { + if codesign.Size(int64(cmd.Dataoff), "a.out") == int64(cmd.Datasize) { + // Update the signature if the size matches, so we don't need to + // fix up headers. Binaries generated by the Go linker should have + // the expected size. Otherwise skip. + text := f.Segment("__TEXT") + cs := make([]byte, cmd.Datasize) + codesign.Sign(cs, w.(io.Reader), "a.out", int64(cmd.Dataoff), int64(text.Offset), int64(text.Filesz), f.Type == macho.TypeExec) + if _, err := w.WriteAt(cs, int64(cmd.Dataoff)); err != nil { + return err + } + } + } + return nil } + +func excludeMachoCodeSignature(r io.Reader) io.Reader { + _, cmd, ok := findMachoCodeSignature(r) + if !ok { + return r + } + return &excludedReader{r, 0, int64(cmd.Dataoff), int64(cmd.Dataoff + cmd.Datasize)} +} + +// excludedReader wraps an io.Reader. Reading from it returns the bytes from +// the underlying reader, except that when the byte offset is within the +// range between start and end, it returns zero bytes. +type excludedReader struct { + r io.Reader + off int64 // current offset + start, end int64 // the range to be excluded (read as zero) +} + +func (r *excludedReader) Read(p []byte) (int, error) { + n, err := r.r.Read(p) + if n > 0 && r.off+int64(n) > r.start && r.off < r.end { + cstart := r.start - r.off + if cstart < 0 { + cstart = 0 + } + cend := r.end - r.off + if cend > int64(n) { + cend = int64(n) + } + zeros := make([]byte, cend-cstart) + copy(p[cstart:cend], zeros) + } + r.off += int64(n) + return n, err +} + +func findMachoCodeSignature(r interface{}) (*macho.File, codesign.CodeSigCmd, bool) { + ra, ok := r.(io.ReaderAt) + if !ok { + return nil, codesign.CodeSigCmd{}, false + } + f, err := macho.NewFile(ra) + if err != nil { + return nil, codesign.CodeSigCmd{}, false + } + cmd, ok := codesign.FindCodeSigCmd(f) + return f, cmd, ok +} diff --git a/src/cmd/internal/codesign/codesign.go b/src/cmd/internal/codesign/codesign.go new file mode 100644 index 0000000000..0517a10640 --- /dev/null +++ b/src/cmd/internal/codesign/codesign.go @@ -0,0 +1,268 @@ +// 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 codesign provides basic functionalities for +// ad-hoc code signing of Mach-O files. +// +// This is not a general tool for code-signing. It is made +// specifically for the Go toolchain. It uses the same +// ad-hoc signing algorithm as the Darwin linker. +package codesign + +import ( + "crypto/sha256" + "debug/macho" + "encoding/binary" + "io" +) + +// Code signature layout. +// +// The code signature is a block of bytes that contains +// a SuperBlob, which contains one or more Blobs. For ad-hoc +// signing, a single CodeDirectory Blob suffices. +// +// A SuperBlob starts with its header (the binary representation +// of the SuperBlob struct), followed by a list of (in our case, +// one) Blobs (offset and size). A CodeDirectory Blob starts +// with its head (the binary representation of CodeDirectory struct), +// followed by the identifier (as a C string) and the hashes, at +// the corresponding offsets. +// +// The signature data must be included in the __LINKEDIT segment. +// In the Mach-O file header, an LC_CODE_SIGNATURE load command +// points to the data. + +const ( + pageSizeBits = 12 + pageSize = 1 << pageSizeBits +) + +const LC_CODE_SIGNATURE = 0x1d + +// Constants and struct layouts are from +// https://opensource.apple.com/source/xnu/xnu-4903.270.47/osfmk/kern/cs_blobs.h + +const ( + CSMAGIC_REQUIREMENT = 0xfade0c00 // single Requirement blob + CSMAGIC_REQUIREMENTS = 0xfade0c01 // Requirements vector (internal requirements) + CSMAGIC_CODEDIRECTORY = 0xfade0c02 // CodeDirectory blob + CSMAGIC_EMBEDDED_SIGNATURE = 0xfade0cc0 // embedded form of signature data + CSMAGIC_DETACHED_SIGNATURE = 0xfade0cc1 // multi-arch collection of embedded signatures + + CSSLOT_CODEDIRECTORY = 0 // slot index for CodeDirectory +) + +const ( + CS_HASHTYPE_SHA1 = 1 + CS_HASHTYPE_SHA256 = 2 + CS_HASHTYPE_SHA256_TRUNCATED = 3 + CS_HASHTYPE_SHA384 = 4 +) + +const ( + CS_EXECSEG_MAIN_BINARY = 0x1 // executable segment denotes main binary + CS_EXECSEG_ALLOW_UNSIGNED = 0x10 // allow unsigned pages (for debugging) + CS_EXECSEG_DEBUGGER = 0x20 // main binary is debugger + CS_EXECSEG_JIT = 0x40 // JIT enabled + CS_EXECSEG_SKIP_LV = 0x80 // skip library validation + CS_EXECSEG_CAN_LOAD_CDHASH = 0x100 // can bless cdhash for execution + CS_EXECSEG_CAN_EXEC_CDHASH = 0x200 // can execute blessed cdhash +) + +type Blob struct { + typ uint32 // type of entry + offset uint32 // offset of entry + // data follows +} + +func (b *Blob) put(out []byte) []byte { + out = put32be(out, b.typ) + out = put32be(out, b.offset) + return out +} + +const blobSize = 2 * 4 + +type SuperBlob struct { + magic uint32 // magic number + length uint32 // total length of SuperBlob + count uint32 // number of index entries following + // blobs []Blob +} + +func (s *SuperBlob) put(out []byte) []byte { + out = put32be(out, s.magic) + out = put32be(out, s.length) + out = put32be(out, s.count) + return out +} + +const superBlobSize = 3 * 4 + +type CodeDirectory struct { + magic uint32 // magic number (CSMAGIC_CODEDIRECTORY) + length uint32 // total length of CodeDirectory blob + version uint32 // compatibility version + flags uint32 // setup and mode flags + hashOffset uint32 // offset of hash slot element at index zero + identOffset uint32 // offset of identifier string + nSpecialSlots uint32 // number of special hash slots + nCodeSlots uint32 // number of ordinary (code) hash slots + codeLimit uint32 // limit to main image signature range + hashSize uint8 // size of each hash in bytes + hashType uint8 // type of hash (cdHashType* constants) + _pad1 uint8 // unused (must be zero) + pageSize uint8 // log2(page size in bytes); 0 => infinite + _pad2 uint32 // unused (must be zero) + scatterOffset uint32 + teamOffset uint32 + _pad3 uint32 + codeLimit64 uint64 + execSegBase uint64 + execSegLimit uint64 + execSegFlags uint64 + // data follows +} + +func (c *CodeDirectory) put(out []byte) []byte { + out = put32be(out, c.magic) + out = put32be(out, c.length) + out = put32be(out, c.version) + out = put32be(out, c.flags) + out = put32be(out, c.hashOffset) + out = put32be(out, c.identOffset) + out = put32be(out, c.nSpecialSlots) + out = put32be(out, c.nCodeSlots) + out = put32be(out, c.codeLimit) + out = put8(out, c.hashSize) + out = put8(out, c.hashType) + out = put8(out, c._pad1) + out = put8(out, c.pageSize) + out = put32be(out, c._pad2) + out = put32be(out, c.scatterOffset) + out = put32be(out, c.teamOffset) + out = put32be(out, c._pad3) + out = put64be(out, c.codeLimit64) + out = put64be(out, c.execSegBase) + out = put64be(out, c.execSegLimit) + out = put64be(out, c.execSegFlags) + return out +} + +const codeDirectorySize = 13*4 + 4 + 4*8 + +// CodeSigCmd is Mach-O LC_CODE_SIGNATURE load command. +type CodeSigCmd struct { + Cmd uint32 // LC_CODE_SIGNATURE + Cmdsize uint32 // sizeof this command (16) + Dataoff uint32 // file offset of data in __LINKEDIT segment + Datasize uint32 // file size of data in __LINKEDIT segment +} + +func FindCodeSigCmd(f *macho.File) (CodeSigCmd, bool) { + get32 := f.ByteOrder.Uint32 + for _, l := range f.Loads { + data := l.Raw() + cmd := get32(data) + if cmd == LC_CODE_SIGNATURE { + return CodeSigCmd{ + cmd, + get32(data[4:]), + get32(data[8:]), + get32(data[12:]), + }, true + } + } + return CodeSigCmd{}, false +} + +func put32be(b []byte, x uint32) []byte { binary.BigEndian.PutUint32(b, x); return b[4:] } +func put64be(b []byte, x uint64) []byte { binary.BigEndian.PutUint64(b, x); return b[8:] } +func put8(b []byte, x uint8) []byte { b[0] = x; return b[1:] } +func puts(b, s []byte) []byte { n := copy(b, s); return b[n:] } + +// Size computes the size of the code signature. +// id is the identifier used for signing (a field in CodeDirectory blob, which +// has no significance in ad-hoc signing). +func Size(codeSize int64, id string) int64 { + nhashes := (codeSize + pageSize - 1) / pageSize + idOff := int64(codeDirectorySize) + hashOff := idOff + int64(len(id)+1) + cdirSz := hashOff + nhashes*sha256.Size + return int64(superBlobSize+blobSize) + cdirSz +} + +// Sign generates an ad-hoc code signature and writes it to out. +// out must have length at least Size(codeSize, id). +// data is the file content without the signature, of size codeSize. +// textOff and textSize is the file offset and size of the text segment. +// isMain is true if this is a main executable. +// id is the identifier used for signing (a field in CodeDirectory blob, which +// has no significance in ad-hoc signing). +func Sign(out []byte, data io.Reader, id string, codeSize, textOff, textSize int64, isMain bool) { + nhashes := (codeSize + pageSize - 1) / pageSize + idOff := int64(codeDirectorySize) + hashOff := idOff + int64(len(id)+1) + sz := Size(codeSize, id) + + // emit blob headers + sb := SuperBlob{ + magic: CSMAGIC_EMBEDDED_SIGNATURE, + length: uint32(sz), + count: 1, + } + blob := Blob{ + typ: CSSLOT_CODEDIRECTORY, + offset: superBlobSize + blobSize, + } + cdir := CodeDirectory{ + magic: CSMAGIC_CODEDIRECTORY, + length: uint32(sz) - (superBlobSize + blobSize), + version: 0x20400, + flags: 0x20002, // adhoc | linkerSigned + hashOffset: uint32(hashOff), + identOffset: uint32(idOff), + nCodeSlots: uint32(nhashes), + codeLimit: uint32(codeSize), + hashSize: sha256.Size, + hashType: CS_HASHTYPE_SHA256, + pageSize: uint8(pageSizeBits), + execSegBase: uint64(textOff), + execSegLimit: uint64(textSize), + } + if isMain { + cdir.execSegFlags = CS_EXECSEG_MAIN_BINARY + } + + outp := out + outp = sb.put(outp) + outp = blob.put(outp) + outp = cdir.put(outp) + + // emit the identifier + outp = puts(outp, []byte(id+"\000")) + + // emit hashes + var buf [pageSize]byte + h := sha256.New() + p := 0 + for p < int(codeSize) { + n, err := io.ReadFull(data, buf[:]) + if err == io.EOF { + break + } + if err != nil && err != io.ErrUnexpectedEOF { + panic(err) + } + if p+n > int(codeSize) { + n = int(codeSize) - p + } + p += n + h.Reset() + h.Write(buf[:n]) + b := h.Sum(nil) + outp = puts(outp, b[:]) + } +} diff --git a/src/cmd/internal/moddeps/moddeps_test.go b/src/cmd/internal/moddeps/moddeps_test.go index 7362e7868b..9ea21873c5 100644 --- a/src/cmd/internal/moddeps/moddeps_test.go +++ b/src/cmd/internal/moddeps/moddeps_test.go @@ -33,7 +33,7 @@ func findGorootModules(t *testing.T) []gorootModule { goBin := testenv.GoToolPath(t) goroot.once.Do(func() { - goroot.err = filepath.Walk(runtime.GOROOT(), func(path string, info fs.FileInfo, err error) error { + goroot.err = filepath.WalkDir(runtime.GOROOT(), func(path string, info fs.DirEntry, err error) error { if err != nil { return err } diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index 0cffa54fa6..9257a6453a 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -1777,15 +1777,15 @@ func instructionsForProg(p *obj.Prog) []*instruction { case ABGEZ: ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg) case ABGT: - ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.Reg), uint32(p.From.Reg) + ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg) case ABGTU: - ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.Reg), uint32(p.From.Reg) + ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg) case ABGTZ: ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO case ABLE: - ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.Reg), uint32(p.From.Reg) + ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg) case ABLEU: - ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.Reg), uint32(p.From.Reg) + ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg) case ABLEZ: ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO case ABLTZ: diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go index 803ba8c77c..279aeb2c32 100644 --- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go +++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go @@ -11,6 +11,8 @@ import ( ) func testBEQZ(a int64) (r bool) +func testBGE(a, b int64) (r bool) +func testBGEU(a, b int64) (r bool) func testBGEZ(a int64) (r bool) func testBGT(a, b int64) (r bool) func testBGTU(a, b int64) (r bool) @@ -18,6 +20,8 @@ func testBGTZ(a int64) (r bool) func testBLE(a, b int64) (r bool) func testBLEU(a, b int64) (r bool) func testBLEZ(a int64) (r bool) +func testBLT(a, b int64) (r bool) +func testBLTU(a, b int64) (r bool) func testBLTZ(a int64) (r bool) func testBNEZ(a int64) (r bool) @@ -29,30 +33,75 @@ func TestBranchCondition(t *testing.T) { fn func(a, b int64) bool want bool }{ - {"BGT", 0, 1, testBGT, true}, + {"BGE", 0, 1, testBGE, false}, + {"BGE", 0, 0, testBGE, true}, + {"BGE", 0, -1, testBGE, true}, + {"BGE", -1, 0, testBGE, false}, + {"BGE", 1, 0, testBGE, true}, + {"BGEU", 0, 1, testBGEU, false}, + {"BGEU", 0, 0, testBGEU, true}, + {"BGEU", 0, -1, testBGEU, false}, + {"BGEU", -1, 0, testBGEU, true}, + {"BGEU", 1, 0, testBGEU, true}, + {"BGT", 0, 1, testBGT, false}, {"BGT", 0, 0, testBGT, false}, - {"BGT", 0, -1, testBGT, false}, - {"BGT", -1, 0, testBGT, true}, - {"BGT", 1, 0, testBGT, false}, - {"BGTU", 0, 1, testBGTU, true}, - {"BGTU", 0, -1, testBGTU, true}, - {"BGTU", -1, 0, testBGTU, false}, - {"BGTU", 1, 0, testBGTU, false}, - {"BLE", 0, 1, testBLE, false}, - {"BLE", 0, -1, testBLE, true}, + {"BGT", 0, -1, testBGT, true}, + {"BGT", -1, 0, testBGT, false}, + {"BGT", 1, 0, testBGT, true}, + {"BGTU", 0, 1, testBGTU, false}, + {"BGTU", 0, 0, testBGTU, false}, + {"BGTU", 0, -1, testBGTU, false}, + {"BGTU", -1, 0, testBGTU, true}, + {"BGTU", 1, 0, testBGTU, true}, + {"BLE", 0, 1, testBLE, true}, {"BLE", 0, 0, testBLE, true}, - {"BLE", -1, 0, testBLE, false}, - {"BLE", 1, 0, testBLE, true}, - {"BLEU", 0, 1, testBLEU, false}, - {"BLEU", 0, -1, testBLEU, false}, + {"BLE", 0, -1, testBLE, false}, + {"BLE", -1, 0, testBLE, true}, + {"BLE", 1, 0, testBLE, false}, + {"BLEU", 0, 1, testBLEU, true}, {"BLEU", 0, 0, testBLEU, true}, - {"BLEU", -1, 0, testBLEU, true}, - {"BLEU", 1, 0, testBLEU, true}, + {"BLEU", 0, -1, testBLEU, true}, + {"BLEU", -1, 0, testBLEU, false}, + {"BLEU", 1, 0, testBLEU, false}, + {"BLT", 0, 1, testBLT, true}, + {"BLT", 0, 0, testBLT, false}, + {"BLT", 0, -1, testBLT, false}, + {"BLT", -1, 0, testBLT, true}, + {"BLT", 1, 0, testBLT, false}, + {"BLTU", 0, 1, testBLTU, true}, + {"BLTU", 0, 0, testBLTU, false}, + {"BLTU", 0, -1, testBLTU, true}, + {"BLTU", -1, 0, testBLTU, false}, + {"BLTU", 1, 0, testBLTU, false}, } for _, test := range tests { t.Run(test.ins, func(t *testing.T) { + var fn func(a, b int64) bool + switch test.ins { + case "BGE": + fn = func(a, b int64) bool { return a >= b } + case "BGEU": + fn = func(a, b int64) bool { return uint64(a) >= uint64(b) } + case "BGT": + fn = func(a, b int64) bool { return a > b } + case "BGTU": + fn = func(a, b int64) bool { return uint64(a) > uint64(b) } + case "BLE": + fn = func(a, b int64) bool { return a <= b } + case "BLEU": + fn = func(a, b int64) bool { return uint64(a) <= uint64(b) } + case "BLT": + fn = func(a, b int64) bool { return a < b } + case "BLTU": + fn = func(a, b int64) bool { return uint64(a) < uint64(b) } + default: + t.Fatalf("Unknown instruction %q", test.ins) + } + if got := fn(test.a, test.b); got != test.want { + t.Errorf("Go %v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want) + } if got := test.fn(test.a, test.b); got != test.want { - t.Errorf("%v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want) + t.Errorf("Assembly %v %v, %v = %v, want %v", test.ins, test.a, test.b, got, test.want) } }) } diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s index 6cff235848..8dd6f563af 100644 --- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s +++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s @@ -16,6 +16,28 @@ b: MOV X6, r+8(FP) RET +// func testBGE(a, b int64) (r bool) +TEXT ·testBGE(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BGE X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + +// func testBGEU(a, b int64) (r bool) +TEXT ·testBGEU(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BGEU X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + // func testBGEZ(a int64) (r bool) TEXT ·testBGEZ(SB),NOSPLIT,$0-0 MOV a+0(FP), X5 @@ -90,6 +112,28 @@ b: MOV X6, r+8(FP) RET +// func testBLT(a, b int64) (r bool) +TEXT ·testBLT(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BLT X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + +// func testBLTU(a, b int64) (r bool) +TEXT ·testBLTU(SB),NOSPLIT,$0-0 + MOV a+0(FP), X5 + MOV b+8(FP), X6 + MOV $1, X7 + BLTU X5, X6, b + MOV $0, X7 +b: + MOV X7, r+16(FP) + RET + // func testBLTZ(a int64) (r bool) TEXT ·testBLTZ(SB),NOSPLIT,$0-0 MOV a+0(FP), X5 diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index 360c5338ba..2d09a6160a 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -413,11 +413,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, case objabi.R_CALL: if siz == 4 { if ldr.SymType(r.Xsym) == sym.SDYNIMPORT { - if ctxt.DynlinkingGo() { - out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32) - } else { - out.Write64(uint64(elf.R_X86_64_GOTPCREL) | uint64(elfsym)<<32) - } + out.Write64(uint64(elf.R_X86_64_PLT32) | uint64(elfsym)<<32) } else { out.Write64(uint64(elf.R_X86_64_PC32) | uint64(elfsym)<<32) } diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 0cb3cc25c0..d1e06239a5 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -35,11 +35,12 @@ func (mode *BuildMode) Set(s string) error { default: return fmt.Errorf("invalid buildmode: %q", s) case "exe": - if objabi.GOOS == "darwin" && objabi.GOARCH == "arm64" { - *mode = BuildModePIE // On darwin/arm64 everything is PIE. - break + switch objabi.GOOS + "/" + objabi.GOARCH { + case "darwin/arm64", "windows/arm": // On these platforms, everything is PIE + *mode = BuildModePIE + default: + *mode = BuildModeExe } - *mode = BuildModeExe case "pie": switch objabi.GOOS { case "aix", "android", "linux", "windows", "darwin", "ios": diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 735b84d37d..e1cc7184de 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -298,6 +298,11 @@ func (ctxt *Link) CanUsePlugins() bool { return ctxt.canUsePlugins } +// NeedCodeSign reports whether we need to code-sign the output binary. +func (ctxt *Link) NeedCodeSign() bool { + return ctxt.IsDarwin() && ctxt.IsARM64() +} + var ( dynlib []string ldflag []string @@ -1642,6 +1647,12 @@ func (ctxt *Link) hostlink() { Exitf("%s: %v", os.Args[0], err) } } + if ctxt.NeedCodeSign() { + err := machoCodeSign(ctxt, *flagOutfile) + if err != nil { + Exitf("%s: code signing failed: %v", os.Args[0], err) + } + } } var createTrivialCOnce sync.Once diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go index 51abefc887..f459576420 100644 --- a/src/cmd/link/internal/ld/macho.go +++ b/src/cmd/link/internal/ld/macho.go @@ -6,6 +6,7 @@ package ld import ( "bytes" + "cmd/internal/codesign" "cmd/internal/objabi" "cmd/internal/sys" "cmd/link/internal/loader" @@ -17,6 +18,7 @@ import ( "os" "sort" "strings" + "unsafe" ) type MachoHdr struct { @@ -245,6 +247,8 @@ const ( BIND_SUBOPCODE_THREADED_APPLY = 0x01 ) +const machoHeaderSize64 = 8 * 4 // size of 64-bit Mach-O header + // Mach-O file writing // https://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html @@ -643,6 +647,8 @@ func asmbMacho(ctxt *Link) { } ctxt.Out.SeekSet(0) + ldr := ctxt.loader + /* apple MACH */ va := *FlagTextAddr - int64(HEADR) @@ -757,25 +763,27 @@ func asmbMacho(ctxt *Link) { } } + var codesigOff int64 if !*FlagD { - ldr := ctxt.loader - - // must match domacholink below + // must match doMachoLink below s1 := ldr.SymSize(ldr.Lookup(".machorebase", 0)) s2 := ldr.SymSize(ldr.Lookup(".machobind", 0)) s3 := ldr.SymSize(ldr.Lookup(".machosymtab", 0)) s4 := ldr.SymSize(ctxt.ArchSyms.LinkEditPLT) s5 := ldr.SymSize(ctxt.ArchSyms.LinkEditGOT) s6 := ldr.SymSize(ldr.Lookup(".machosymstr", 0)) + s7 := ldr.SymSize(ldr.Lookup(".machocodesig", 0)) if ctxt.LinkMode != LinkExternal { ms := newMachoSeg("__LINKEDIT", 0) ms.vaddr = uint64(Rnd(int64(Segdata.Vaddr+Segdata.Length), int64(*FlagRound))) - ms.vsize = uint64(s1 + s2 + s3 + s4 + s5 + s6) + ms.vsize = uint64(s1 + s2 + s3 + s4 + s5 + s6 + s7) ms.fileoffset = uint64(linkoff) ms.filesize = ms.vsize ms.prot1 = 1 ms.prot2 = 1 + + codesigOff = linkoff + s1 + s2 + s3 + s4 + s5 + s6 } if ctxt.LinkMode != LinkExternal && ctxt.IsPIE() { @@ -814,12 +822,31 @@ func asmbMacho(ctxt *Link) { stringtouint32(ml.data[4:], lib) } } + + if ctxt.IsInternal() && ctxt.NeedCodeSign() { + ml := newMachoLoad(ctxt.Arch, LC_CODE_SIGNATURE, 2) + ml.data[0] = uint32(codesigOff) + ml.data[1] = uint32(s7) + } } a := machowrite(ctxt, ctxt.Arch, ctxt.Out, ctxt.LinkMode) if int32(a) > HEADR { Exitf("HEADR too small: %d > %d", a, HEADR) } + + // Now we have written everything. Compute the code signature (which + // is a hash of the file content, so it must be done at last.) + if ctxt.IsInternal() && ctxt.NeedCodeSign() { + cs := ldr.Lookup(".machocodesig", 0) + data := ctxt.Out.Data() + if int64(len(data)) != codesigOff { + panic("wrong size") + } + codesign.Sign(ldr.Data(cs), bytes.NewReader(data), "a.out", codesigOff, int64(Segtext.Fileoff), int64(Segtext.Filelen), ctxt.IsExe() || ctxt.IsPIE()) + ctxt.Out.SeekSet(codesigOff) + ctxt.Out.Write(ldr.Data(cs)) + } } func symkind(ldr *loader.Loader, s loader.Sym) int { @@ -1057,7 +1084,6 @@ func machodysymtab(ctxt *Link, base int64) { func doMachoLink(ctxt *Link) int64 { machosymtab(ctxt) - machoDyldInfo(ctxt) ldr := ctxt.loader @@ -1070,6 +1096,8 @@ func doMachoLink(ctxt *Link) int64 { s5 := ctxt.ArchSyms.LinkEditGOT s6 := ldr.Lookup(".machosymstr", 0) + size := ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4) + ldr.SymSize(s5) + ldr.SymSize(s6) + // Force the linkedit section to end on a 16-byte // boundary. This allows pure (non-cgo) Go binaries // to be code signed correctly. @@ -1087,13 +1115,14 @@ func doMachoLink(ctxt *Link) int64 { // boundary, codesign_allocate will not need to apply // any alignment padding itself, working around the // issue. - s6b := ldr.MakeSymbolUpdater(s6) - for s6b.Size()%16 != 0 { - s6b.AddUint8(0) + if size%16 != 0 { + n := 16 - size%16 + s6b := ldr.MakeSymbolUpdater(s6) + s6b.Grow(s6b.Size() + n) + s6b.SetSize(s6b.Size() + n) + size += n } - size := int(ldr.SymSize(s1) + ldr.SymSize(s2) + ldr.SymSize(s3) + ldr.SymSize(s4) + ldr.SymSize(s5) + ldr.SymSize(s6)) - if size > 0 { linkoff = Rnd(int64(uint64(HEADR)+Segtext.Length), int64(*FlagRound)) + Rnd(int64(Segrelrodata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdata.Filelen), int64(*FlagRound)) + Rnd(int64(Segdwarf.Filelen), int64(*FlagRound)) ctxt.Out.SeekSet(linkoff) @@ -1104,9 +1133,13 @@ func doMachoLink(ctxt *Link) int64 { ctxt.Out.Write(ldr.Data(s4)) ctxt.Out.Write(ldr.Data(s5)) ctxt.Out.Write(ldr.Data(s6)) + + // Add code signature if necessary. This must be the last. + s7 := machoCodeSigSym(ctxt, linkoff+size) + size += ldr.SymSize(s7) } - return Rnd(int64(size), int64(*FlagRound)) + return Rnd(size, int64(*FlagRound)) } func machorelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) { @@ -1378,3 +1411,94 @@ func machoDyldInfo(ctxt *Link) { // e.g. dlsym'd. But internal linking is not the default in that case, so // it is fine. } + +// machoCodeSigSym creates and returns a symbol for code signature. +// The symbol context is left as zeros, which will be generated at the end +// (as it depends on the rest of the file). +func machoCodeSigSym(ctxt *Link, codeSize int64) loader.Sym { + ldr := ctxt.loader + cs := ldr.CreateSymForUpdate(".machocodesig", 0) + if !ctxt.NeedCodeSign() || ctxt.IsExternal() { + return cs.Sym() + } + sz := codesign.Size(codeSize, "a.out") + cs.Grow(sz) + cs.SetSize(sz) + return cs.Sym() +} + +// machoCodeSign code-signs Mach-O file fname with an ad-hoc signature. +// This is used for updating an external linker generated binary. +func machoCodeSign(ctxt *Link, fname string) error { + f, err := os.OpenFile(fname, os.O_RDWR, 0) + if err != nil { + return err + } + defer f.Close() + + mf, err := macho.NewFile(f) + if err != nil { + return err + } + if mf.Magic != macho.Magic64 { + Exitf("not 64-bit Mach-O file: %s", fname) + } + + // Find existing LC_CODE_SIGNATURE and __LINKEDIT segment + var sigOff, sigSz, csCmdOff, linkeditOff int64 + var linkeditSeg, textSeg *macho.Segment + loadOff := int64(machoHeaderSize64) + get32 := mf.ByteOrder.Uint32 + for _, l := range mf.Loads { + data := l.Raw() + cmd, sz := get32(data), get32(data[4:]) + if cmd == LC_CODE_SIGNATURE { + sigOff = int64(get32(data[8:])) + sigSz = int64(get32(data[12:])) + csCmdOff = loadOff + } + if seg, ok := l.(*macho.Segment); ok { + switch seg.Name { + case "__LINKEDIT": + linkeditSeg = seg + linkeditOff = loadOff + case "__TEXT": + textSeg = seg + } + } + loadOff += int64(sz) + } + + if sigOff == 0 { + // The C linker doesn't generate a signed binary, for some reason. + // Skip. + return nil + } + sz := codesign.Size(sigOff, "a.out") + if sz != sigSz { + // Update the load command, + var tmp [8]byte + mf.ByteOrder.PutUint32(tmp[:4], uint32(sz)) + _, err = f.WriteAt(tmp[:4], csCmdOff+12) + if err != nil { + return err + } + + // Uodate the __LINKEDIT segment. + segSz := sigOff + sz - int64(linkeditSeg.Offset) + mf.ByteOrder.PutUint64(tmp[:8], uint64(segSz)) + _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Memsz))) + if err != nil { + return err + } + _, err = f.WriteAt(tmp[:8], int64(linkeditOff)+int64(unsafe.Offsetof(macho.Segment64{}.Filesz))) + if err != nil { + return err + } + } + + cs := make([]byte, sz) + codesign.Sign(cs, f, "a.out", sigOff, int64(textSeg.Offset), int64(textSeg.Filesz), ctxt.IsExe() || ctxt.IsPIE()) + _, err = f.WriteAt(cs, sigOff) + return err +} diff --git a/src/cmd/link/internal/ld/outbuf.go b/src/cmd/link/internal/ld/outbuf.go index 36ec394077..530836ef7c 100644 --- a/src/cmd/link/internal/ld/outbuf.go +++ b/src/cmd/link/internal/ld/outbuf.go @@ -113,6 +113,7 @@ func (out *OutBuf) Close() error { } if out.isMmapped() { out.copyHeap() + out.purgeSignatureCache() out.munmap() } if out.f == nil { @@ -135,6 +136,15 @@ func (out *OutBuf) isMmapped() bool { return len(out.buf) != 0 } +// Data returns the whole written OutBuf as a byte slice. +func (out *OutBuf) Data() []byte { + if out.isMmapped() { + out.copyHeap() + return out.buf + } + return out.heap +} + // copyHeap copies the heap to the mmapped section of memory, returning true if // a copy takes place. func (out *OutBuf) copyHeap() bool { diff --git a/src/cmd/link/internal/ld/outbuf_darwin.go b/src/cmd/link/internal/ld/outbuf_darwin.go index d7e3372230..9444b6567e 100644 --- a/src/cmd/link/internal/ld/outbuf_darwin.go +++ b/src/cmd/link/internal/ld/outbuf_darwin.go @@ -36,3 +36,12 @@ func (out *OutBuf) fallocate(size uint64) error { return nil } + +func (out *OutBuf) purgeSignatureCache() { + // Apparently, the Darwin kernel may cache the code signature at mmap. + // When we mmap the output buffer, it doesn't have a code signature + // (as we haven't generated one). Invalidate the kernel cache now that + // we have generated the signature. See issue #42684. + syscall.Syscall(syscall.SYS_MSYNC, uintptr(unsafe.Pointer(&out.buf[0])), uintptr(len(out.buf)), syscall.MS_INVALIDATE) + // Best effort. Ignore error. +} diff --git a/src/cmd/link/internal/ld/outbuf_notdarwin.go b/src/cmd/link/internal/ld/outbuf_notdarwin.go new file mode 100644 index 0000000000..8c5666f216 --- /dev/null +++ b/src/cmd/link/internal/ld/outbuf_notdarwin.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 !darwin + +package ld + +func (out *OutBuf) purgeSignatureCache() {} diff --git a/src/cmd/vendor/golang.org/x/mod/semver/semver.go b/src/cmd/vendor/golang.org/x/mod/semver/semver.go index 2988e3cf9c..4338f35177 100644 --- a/src/cmd/vendor/golang.org/x/mod/semver/semver.go +++ b/src/cmd/vendor/golang.org/x/mod/semver/semver.go @@ -138,6 +138,9 @@ func Compare(v, w string) int { // Max canonicalizes its arguments and then returns the version string // that compares greater. +// +// Deprecated: use Compare instead. In most cases, returning a canonicalized +// version is not expected or desired. func Max(v, w string) string { v = Canonical(v) w = Canonical(w) diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index f20b6b2be1..21bd6bfe48 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -29,7 +29,7 @@ golang.org/x/arch/x86/x86asm golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 golang.org/x/crypto/ssh/terminal -# golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 +# golang.org/x/mod v0.4.0 ## explicit golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile diff --git a/src/compress/gzip/issue14937_test.go b/src/compress/gzip/issue14937_test.go index 24db3641aa..20da0b6824 100644 --- a/src/compress/gzip/issue14937_test.go +++ b/src/compress/gzip/issue14937_test.go @@ -31,7 +31,7 @@ func TestGZIPFilesHaveZeroMTimes(t *testing.T) { t.Fatal("error evaluating GOROOT: ", err) } var files []string - err = filepath.Walk(goroot, func(path string, info fs.FileInfo, err error) error { + err = filepath.WalkDir(goroot, func(path string, info fs.DirEntry, err error) error { if err != nil { return err } diff --git a/src/crypto/ed25519/internal/edwards25519/edwards25519.go b/src/crypto/ed25519/internal/edwards25519/edwards25519.go index fd03c252af..b091481b77 100644 --- a/src/crypto/ed25519/internal/edwards25519/edwards25519.go +++ b/src/crypto/ed25519/internal/edwards25519/edwards25519.go @@ -722,7 +722,7 @@ func (p *ExtendedGroupElement) FromBytes(s *[32]byte) bool { FeOne(&p.Z) FeSquare(&u, &p.Y) FeMul(&v, &u, &d) - FeSub(&u, &u, &p.Z) // y = y^2-1 + FeSub(&u, &u, &p.Z) // u = y^2-1 FeAdd(&v, &v, &p.Z) // v = dy^2+1 FeSquare(&v3, &v) diff --git a/src/encoding/json/scanner.go b/src/encoding/json/scanner.go index c3f5f6372d..9dc1903e2d 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 "json: " + e.msg } +func (e *SyntaxError) Error() string { return 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/go/build/deps_test.go b/src/go/build/deps_test.go index bf1367355d..e9ed26aa5f 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -510,8 +510,8 @@ func listStdPkgs(goroot string) ([]string, error) { var pkgs []string src := filepath.Join(goroot, "src") + string(filepath.Separator) - walkFn := func(path string, fi fs.FileInfo, err error) error { - if err != nil || !fi.IsDir() || path == src { + walkFn := func(path string, d fs.DirEntry, err error) error { + if err != nil || !d.IsDir() || path == src { return nil } @@ -528,7 +528,7 @@ func listStdPkgs(goroot string) ([]string, error) { pkgs = append(pkgs, strings.TrimPrefix(name, "vendor/")) return nil } - if err := filepath.Walk(src, walkFn); err != nil { + if err := filepath.WalkDir(src, walkFn); err != nil { return nil, err } return pkgs, nil diff --git a/src/go/doc/headscan.go b/src/go/doc/headscan.go index 8ea462366e..fe26a0ea84 100644 --- a/src/go/doc/headscan.go +++ b/src/go/doc/headscan.go @@ -69,8 +69,8 @@ func main() { flag.Parse() fset := token.NewFileSet() nheadings := 0 - err := filepath.Walk(*root, func(path string, fi fs.FileInfo, err error) error { - if !fi.IsDir() { + err := filepath.WalkDir(*root, func(path string, info fs.DirEntry, err error) error { + if !info.IsDir() { return nil } pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments) diff --git a/src/go/parser/interface.go b/src/go/parser/interface.go index cc7e455c4d..d5c18a9e2d 100644 --- a/src/go/parser/interface.go +++ b/src/go/parser/interface.go @@ -140,7 +140,7 @@ func ParseDir(fset *token.FileSet, path string, filter func(fs.FileInfo) bool, m pkgs = make(map[string]*ast.Package) for _, d := range list { - if strings.HasSuffix(d.Name(), ".go") && (filter == nil || filter(d)) { + if !d.IsDir() && strings.HasSuffix(d.Name(), ".go") && (filter == nil || filter(d)) { filename := filepath.Join(path, d.Name()) if src, err := ParseFile(fset, filename, nil, mode); err == nil { name := src.Name.Name diff --git a/src/go/parser/parser_test.go b/src/go/parser/parser_test.go index 7193a329fe..a4f882d368 100644 --- a/src/go/parser/parser_test.go +++ b/src/go/parser/parser_test.go @@ -82,6 +82,14 @@ func TestParseDir(t *testing.T) { } } +func TestIssue42951(t *testing.T) { + path := "./testdata/issue42951" + _, err := ParseDir(token.NewFileSet(), path, nil, 0) + if err != nil { + t.Errorf("ParseDir(%s): %v", path, err) + } +} + func TestParseExpr(t *testing.T) { // just kicking the tires: // a valid arithmetic expression diff --git a/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go b/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go new file mode 100644 index 0000000000..bb698be11c --- /dev/null +++ b/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go @@ -0,0 +1 @@ +This file should not be parsed by ParseDir. diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go index b6031ea60a..fbc84a7592 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", `