drop support for Go 1.16.x

We can now use pruned module graphs in go.mod files,
and we no longer need to worry about runtime/internal/sys.

Note that I had to update testdata/mod slightly,
as the new pruned module graphs algorithm downloads an extra go.mod file.

This change also paves the way towards future Go 1.18 support.

Thanks to lu4p for cleaning up two TODOs as well.

Co-Authored-By: lu4p <lu4p@pm.me>
pull/402/head
Daniel Martí 3 years ago committed by Andrew LeFevre
parent 1682e8ee10
commit 7ede21c981

@ -10,7 +10,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.16.x, 1.17.x]
go-version: [1.17.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:

@ -2,7 +2,7 @@
go install mvdan.cc/garble@latest
Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.16 or later.
Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.17 or later.
garble build [build flags] [packages]
@ -41,12 +41,12 @@ what packages to obfuscate, set `GOPRIVATE`, documented at `go help private`.
Note that commands like `garble build` will use the `go` version found in your
`$PATH`. To use different versions of Go, you can
[install them](https://golang.org/doc/manage-install#installing-multiple)
and set up `$PATH` with them. For example, for Go 1.16.1:
and set up `$PATH` with them. For example, for Go 1.17.1:
```sh
$ go install golang.org/dl/go1.16.1@latest
$ go1.16.1 download
$ PATH=$(go1.16.1 env GOROOT)/bin:${PATH} garble build
$ go install golang.org/dl/go1.17.1@latest
$ go1.17.1 download
$ PATH=$(go1.17.1 env GOROOT)/bin:${PATH} garble build
```
### Literal obfuscation

@ -1,6 +1,6 @@
module mvdan.cc/garble
go 1.16
go 1.17
require (
github.com/google/go-cmp v0.5.6
@ -8,3 +8,9 @@ require (
golang.org/x/mod v0.5.0
golang.org/x/tools v0.1.5
)
require (
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/errgo.v2 v2.1.0 // indirect
)

@ -23,11 +23,11 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"runtime"
"runtime/debug"
"strconv"
"strings"
"time"
"unicode"
"unicode/utf8"
@ -248,15 +248,12 @@ func (e errJustExit) Error() string { return fmt.Sprintf("exit: %d", e) }
func goVersionOK() bool {
const (
minGoVersionSemver = "v1.16.0"
suggestedGoVersion = "1.16.x"
gitTimeFormat = "Mon Jan 2 15:04:05 2006 -0700"
minGoVersionSemver = "v1.17.0"
suggestedGoVersion = "1.17.x"
)
// Go 1.16 was released on Febuary 16th, 2021.
minGoVersionDate := time.Date(2021, 2, 16, 0, 0, 0, 0, time.UTC)
version := cache.GoEnv.GOVERSION
rxVersion := regexp.MustCompile(`go\d+\.\d+(\.\d)?`)
version := rxVersion.FindString(cache.GoEnv.GOVERSION)
if version == "" {
// Go 1.15.x and older do not have GOVERSION yet.
// We could go the extra mile and fetch it via 'go version',
@ -265,37 +262,6 @@ func goVersionOK() bool {
return false
}
if strings.HasPrefix(version, "devel ") {
commitAndDate := strings.TrimPrefix(version, "devel ")
// Remove commit hash and architecture from version
startDateIdx := strings.IndexByte(commitAndDate, ' ') + 1
if startDateIdx < 0 {
// Custom version; assume the user knows what they're doing.
// TODO: cover this in a test
return true
}
// TODO: once we support Go 1.17 and later, use the major Go
// version included in its devel versions:
//
// go version devel go1.17-8518aac314 ...
date := commitAndDate[startDateIdx:]
versionDate, err := time.Parse(gitTimeFormat, date)
if err != nil {
// Custom version; assume the user knows what they're doing.
return true
}
if versionDate.After(minGoVersionDate) {
return true
}
fmt.Fprintf(os.Stderr, "Go version %q is too old; please upgrade to Go %s or a newer devel version\n", version, suggestedGoVersion)
return false
}
versionSemver := "v" + strings.TrimPrefix(version, "go")
if semver.Compare(versionSemver, minGoVersionSemver) < 0 {
fmt.Fprintf(os.Stderr, "Go version %q is too old; please upgrade to Go %s\n", version, suggestedGoVersion)
@ -369,23 +335,6 @@ func mainErr(args []string) error {
toolexecImportPath := os.Getenv("TOOLEXEC_IMPORTPATH")
// Workaround for https://github.com/golang/go/issues/44963.
// TODO(mvdan): remove once we only support Go 1.17 and later.
if tool == "compile" && !strings.Contains(toolexecImportPath, ".test]") {
isTestPkg := false
_, paths := splitFlagsFromFiles(args, ".go")
for _, path := range paths {
if strings.HasSuffix(path, "_test.go") {
isTestPkg = true
break
}
}
if isTestPkg {
forPkg := strings.TrimSuffix(toolexecImportPath, "_test")
toolexecImportPath = fmt.Sprintf("%s [%s.test]", toolexecImportPath, forPkg)
}
}
curPkg = cache.ListedPackages[toolexecImportPath]
if curPkg == nil {
return fmt.Errorf("TOOLEXEC_IMPORTPATH not found in listed packages: %s", toolexecImportPath)
@ -673,10 +622,9 @@ func transformCompile(args []string) ([]string, error) {
return nil, err
}
if (curPkg.ImportPath == "runtime" && opts.Tiny) || curPkg.ImportPath == "runtime/internal/sys" {
// Even though these packages aren't private, we will still process
// them later to remove build information and strip code from the
// runtime. However, we only want flags to work on private packages.
if curPkg.ImportPath == "runtime" && opts.Tiny {
// When using -tiny, we call stripRuntime below.
// We don't want -literals and -debugdir to apply, though.
opts.GarbleLiterals = false
opts.DebugDir = ""
} else if !curPkg.Private {
@ -706,29 +654,9 @@ func transformCompile(args []string) ([]string, error) {
for i, file := range files {
name := filepath.Base(paths[i])
switch curPkg.ImportPath {
case "runtime":
if curPkg.ImportPath == "runtime" && opts.Tiny {
// strip unneeded runtime code
stripRuntime(name, file)
case "runtime/internal/sys":
// The first declaration in zversion.go contains the Go
// version as follows. Replace it here, since the
// linker's -X does not work with constants.
//
// const TheVersion = `devel ...`
//
// Don't touch the source in any other way.
// TODO: remove once we only support Go 1.17 and later,
// as from that point we can just rely on linking -X flags.
if name != "zversion.go" {
break
}
spec := file.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec)
if len(spec.Names) != 1 || spec.Names[0].Name != "TheVersion" {
break
}
lit := spec.Values[0].(*ast.BasicLit)
lit.Value = "`unknown`"
}
if strings.HasPrefix(name, "_cgo_") {
// Don't obfuscate cgo code, since it's generated and it gets messy.
@ -848,7 +776,7 @@ func (tf *transformer) handleDirectives(comments []*ast.CommentGroup) {
// Once we support go:linkname well and once we can obfuscate the runtime
// package, this entire map can likely go away.
//
// The list was obtained via scripts/runtime-related.sh on Go 1.16.
// The list was obtained via scripts/runtime-related.sh on Go 1.17.
var runtimeRelated = map[string]bool{
"bufio": true,
"bytes": true,
@ -861,9 +789,12 @@ var runtimeRelated = map[string]bool{
"fmt": true,
"hash": true,
"hash/crc32": true,
"internal/abi": true,
"internal/bytealg": true,
"internal/cpu": true,
"internal/fmtsort": true,
"internal/goexperiment": true,
"internal/itoa": true,
"internal/nettrace": true,
"internal/oserror": true,
"internal/poll": true,
@ -910,11 +841,6 @@ var runtimeRelated = map[string]bool{
"unsafe": true,
"vendor/golang.org/x/net/dns/dnsmessage": true,
"vendor/golang.org/x/net/route": true,
// Manual additions for Go 1.17 as of June 2021.
"internal/abi": true,
"internal/itoa": true,
"internal/goexperiment": true,
}
// isPrivate checks if a package import path should be considered private,
@ -1791,7 +1717,7 @@ func alterTrimpath(flags []string) []string {
return flagSetValue(flags, "-trimpath", sharedTempDir+"=>;"+trimpath)
}
// buildFlags is obtained from 'go help build' as of Go 1.16.
// buildFlags is obtained from 'go help build' as of Go 1.17.
var buildFlags = map[string]bool{
"-a": true,
"-n": true,
@ -1819,7 +1745,7 @@ var buildFlags = map[string]bool{
"-overlay": true,
}
// booleanFlags is obtained from 'go help build' and 'go help testflag' as of Go 1.16.
// booleanFlags is obtained from 'go help build' and 'go help testflag' as of Go 1.17.
var booleanFlags = map[string]bool{
// Shared build flags.
"-a": true,

@ -139,8 +139,8 @@ func stripRuntime(filename string, file *ast.File) {
switch filename {
case "runtime1.go":
// On Go 1.16.x, the code above results in runtime1.go having an
// unused import. Mark it as used via "var _ = pkg.Func".
// On Go 1.17.x, the code above results in runtime1.go having an
// unused import. Make it an underscore import.
// If this is a recurring problem, we could go for a more
// generic solution like x/tools/imports.
for _, imp := range file.Imports {

@ -1,4 +1,4 @@
rsc.io/sampler@v1.99.99
module rsc.io/sampler@v1.99.99
-- .mod --
module "rsc.io/sampler"

@ -0,0 +1,9 @@
rsc.io/testonly v1.0.0
written by hand
-- .mod --
module rsc.io/testonly
-- .info --
{"Version":"v1.0.0"}
-- testonly.go --
package testonly

@ -20,7 +20,7 @@ binsubstr main$exe 'privateAdd' 'PublicAdd'
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -58,7 +58,7 @@ binsubstr main$exe 'garble_main.go' 'globalVar' 'globalFunc' $gofullversion
-- go.mod --
module test/mainfoo
go 1.16
go 1.17
-- garble_main.go --
package main

@ -26,7 +26,7 @@ cmp stdout main.stdout
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -17,7 +17,7 @@ garble build
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -18,7 +18,7 @@ stderr 'test/main' # we force rebuilds with -debugdir
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -14,7 +14,7 @@ cmp stdout main.stdout
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -32,7 +32,7 @@ bincmp out_rebuild out
-- go.mod --
module test/main
go 1.16
go 1.17
-- standalone/main.go --
package main

@ -7,38 +7,44 @@ env PATH=${WORK}/.bin${:}${PATH}
# An empty go version.
env GOVERSION=''
! garble build
stderr 'Go version is too old'
stderr 'Go version is too old; please upgrade to Go 1.17.x or a newer devel version'
# We should error on a devel version that's too old.
# Note that they lacked the "goN.M-" prefix.
env GOVERSION='devel +afb5fca Sun Aug 07 00:00:00 2020 +0000'
! garble build
stderr 'Go version.*Aug 07.*too old; please upgrade to Go 1.16.x or a newer devel version'
stderr 'Go version is too old; please upgrade to Go 1.17.x or a newer devel version'
# A future devel timestamp should be fine.
env GOVERSION='devel +afb5fca Sun Sep 13 07:54:42 2021 +0000'
# Another form of old version; with an old "goN.M-" prefix.
env GOVERSION='devel go1.15-afb5fca Sun Aug 07 00:00:00 2020 +0000'
! garble build
stderr 'Go version "go1.15" is too old; please upgrade to Go 1.17.x'
# A current devel version should be fine
env GOVERSION='devel go1.18-ad97d204f0 Sun Sep 12 16:46:58 2021 +0000'
! garble build
stderr 'mocking the real build'
# We should error on a stable version that's too old.
env GOVERSION='go1.14'
! garble build
stderr 'Go version.*go1.14.*too old; please upgrade to Go 1.16.x'
stderr 'Go version "go1.14" is too old; please upgrade to Go 1.17.x'
! stderr 'or a newer devel version'
# We should accept a future stable version.
env GOVERSION='go1.16.2'
env GOVERSION='go1.18.2'
! garble build
stderr 'mocking the real build'
# We should accept custom devel strings.
env GOVERSION='devel somecustomversion'
env GOVERSION='devel go1.18-somecustomversion'
! garble build
stderr 'mocking the real build'
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -16,7 +16,7 @@ cmp stdout main.stdout
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -44,11 +44,17 @@ cmp stdout main.stdout
-- go.mod --
module test/main
go 1.16
go 1.17
require (
rsc.io/quote v1.5.2
gopkg.in/garbletest.v2 v2.999.0
rsc.io/quote v1.5.2
)
require (
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
rsc.io/sampler v1.3.0 // indirect
rsc.io/testonly v1.0.0 // indirect
)
-- go.sum --
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
@ -59,6 +65,8 @@ rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
-- garble_main.go --
package main

@ -13,7 +13,7 @@ cmp stderr main.stderr
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -23,7 +23,7 @@ binsubstr main$exe 'unexportedVersion'
-- go.mod --
module domain.test/main
go 1.16
go 1.17
-- main.go --
package main

@ -15,7 +15,7 @@ cmp stderr main.stderr
-- go.mod --
module test/main
go 1.16
go 1.17
replace big.chungus/meme => ./big.chungus/meme
@ -99,7 +99,7 @@ func ByteIndex(s string, c byte) int
-- big.chungus/meme/go.mod --
module test/main
go 1.16
go 1.17
-- big.chungus/meme/dante.go --
package meme

@ -57,7 +57,7 @@ garble -literals build std
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -15,7 +15,7 @@ binsubstr main$exe '(devel)'
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -29,7 +29,7 @@ cmp stderr main.stderr
-- go.mod --
module test/main
go 1.16
go 1.17
-- plugin/main.go --
package main

@ -19,7 +19,7 @@ stdout 'varPositions is sorted'
-- go.mod --
module test/main
go 1.16
go 1.17
-- garble_main.go --
package main

@ -17,7 +17,7 @@ cmp stdout main.stdout
-- go.mod --
module test/main
go 1.16
go 1.17
-- garble_main.go --
package main

@ -50,7 +50,7 @@ cmp stdout main-literals.stderr
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -78,7 +78,7 @@ exec ./main$exe funcName
-- go.mod --
module test/main
go 1.16
go 1.17
-- main.go --
package main

@ -19,7 +19,7 @@ binsubstr main$exe 'globalVar' # 'globalType' matches on some, but not all, plat
-- extra/go.mod --
module private.source/extra
go 1.16
go 1.17
-- extra/extra.go --
package extra
@ -29,7 +29,7 @@ func Func() string {
-- go.mod --
module test/main
go 1.16
go 1.17
// We include an extra module to obfuscate, included in the same original source
// code via a replace directive.

@ -41,7 +41,7 @@ stdout 'package bar_test, func name: test/bar\.OriginalFuncName'
-- go.mod --
module test/bar
go 1.16
go 1.17
-- bar.go --
package bar

@ -26,7 +26,7 @@ stderr 'panic: oh noes'
-- go.mod --
module test/main
go 1.16
go 1.17
-- garble_main.go --
package main

Loading…
Cancel
Save