From ffed9e5438e6acb6cf0a72cd7eb25df2c710d296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sun, 13 Apr 2025 19:27:48 +0100 Subject: [PATCH] drop support for Go 1.23 A pretty small patch, given that 1.23 and 1.24 are quite similar in terms of what garble does. --- README.md | 2 +- go.mod | 4 +- go_std_tables.go | 23 +---- .../go1.23/0001-add-custom-magic-value.patch | 47 ---------- ...dd-unexported-function-name-removing.patch | 85 ------------------- .../go1.23/0003-add-entryOff-encryption.patch | 43 ---------- main.go | 4 +- scripts/gen_go_std_tables.go | 13 +-- testdata/script/goversion.txtar | 34 ++++---- 9 files changed, 26 insertions(+), 229 deletions(-) delete mode 100644 internal/linker/patches/go1.23/0001-add-custom-magic-value.patch delete mode 100644 internal/linker/patches/go1.23/0002-add-unexported-function-name-removing.patch delete mode 100644 internal/linker/patches/go1.23/0003-add-entryOff-encryption.patch diff --git a/README.md b/README.md index 2044489..f27a538 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ go install mvdan.cc/garble@latest -Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.23.5 or later. +Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.24 or later. garble build [build flags] [packages] diff --git a/go.mod b/go.mod index 9f88072..a58a8bf 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module mvdan.cc/garble -// Before the .5 bugfix release, alias tracking via go/types -// was broken; see https://go.dev/issue/70517. -go 1.23.5 +go 1.24 require ( github.com/bluekeyes/go-gitdiff v0.8.1 diff --git a/go_std_tables.go b/go_std_tables.go index e0e697e..640f58c 100644 --- a/go_std_tables.go +++ b/go_std_tables.go @@ -1,6 +1,6 @@ // Code generated by scripts/gen_go_std_tables.go; DO NOT EDIT. -// Generated from Go versions [go1.23.7 go1.24.1]. +// Generated from Go versions [go1.24.1]. package main @@ -27,8 +27,6 @@ var runtimeAndDeps = map[string]bool{ "internal/runtime/syscall": true, // go1.24 "internal/stringslite": true, // go1.24 "runtime": true, // go1.24 - "runtime/internal/math": true, // go1.23 - "runtime/internal/sys": true, // go1.23 "unsafe": true, // go1.24 } @@ -49,7 +47,6 @@ var runtimeLinknamed = []string{ "internal/synctest", // go1.24 "internal/syscall/unix", // go1.24 "internal/syscall/windows", // go1.24 - "internal/weak", // go1.23 "maps", // go1.24 "os", // go1.24 "os/signal", // go1.24 @@ -134,8 +131,6 @@ var compilerIntrinsics = map[string]map[string]bool{ "ctrlGroupMatchH2": true, // go1.24 }, "internal/runtime/math": { - "Add64": true, // go1.24 - "Mul64": true, // go1.24 "MulUintptr": true, // go1.24 }, "internal/runtime/sys": { @@ -204,22 +199,6 @@ var compilerIntrinsics = map[string]map[string]bool{ "runtime": { "publicationBarrier": true, // go1.24 }, - "runtime/internal/math": { - "Add64": true, // go1.23 - "Mul64": true, // go1.23 - }, - "runtime/internal/sys": { - "Bswap32": true, // go1.23 - "Bswap64": true, // go1.23 - "Len64": true, // go1.23 - "Len8": true, // go1.23 - "OnesCount64": true, // go1.23 - "Prefetch": true, // go1.23 - "PrefetchStreamed": true, // go1.23 - "TrailingZeros32": true, // go1.23 - "TrailingZeros64": true, // go1.23 - "TrailingZeros8": true, // go1.23 - }, "sync": { "runtime_LoadAcquintptr": true, // go1.24 "runtime_StoreReluintptr": true, // go1.24 diff --git a/internal/linker/patches/go1.23/0001-add-custom-magic-value.patch b/internal/linker/patches/go1.23/0001-add-custom-magic-value.patch deleted file mode 100644 index 12abd2c..0000000 --- a/internal/linker/patches/go1.23/0001-add-custom-magic-value.patch +++ /dev/null @@ -1,47 +0,0 @@ -From a67db18d018b3626e80190cf33b5e7582b6e63cf Mon Sep 17 00:00:00 2001 -From: pagran -Date: Mon, 9 Jan 2023 13:30:00 +0100 -Subject: [PATCH 1/3] add custom magic value - ---- - cmd/link/internal/ld/pcln.go | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/cmd/link/internal/ld/pcln.go b/cmd/link/internal/ld/pcln.go -index 57c88c03af..c09ae07e33 100644 ---- a/cmd/link/internal/ld/pcln.go -+++ b/cmd/link/internal/ld/pcln.go -@@ -4,6 +4,10 @@ - - package ld - -+import ( -+ "os" -+) -+ - import ( - "cmd/internal/goobj" - "cmd/internal/objabi" -@@ -262,6 +266,19 @@ func (state *pclntab) generatePCHeader(ctxt *Link) { - if off != size { - panic(fmt.Sprintf("pcHeader size: %d != %d", off, size)) - } -+ -+ // Use garble prefix in variable names to minimize collision risk -+ garbleMagicStr := os.Getenv("GARBLE_LINK_MAGIC") -+ if garbleMagicStr == "" { -+ panic("[garble] magic value must be set") -+ } -+ var garbleMagicVal uint32 -+ // Use fmt package instead of strconv to avoid importing a new package -+ if _, err := fmt.Sscan(garbleMagicStr, &garbleMagicVal); err != nil { -+ panic(fmt.Errorf("[garble] invalid magic value %s: %v", garbleMagicStr, err)) -+ } -+ -+ header.SetUint32(ctxt.Arch, 0, garbleMagicVal) - } - - state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader) --- -2.46.0 - diff --git a/internal/linker/patches/go1.23/0002-add-unexported-function-name-removing.patch b/internal/linker/patches/go1.23/0002-add-unexported-function-name-removing.patch deleted file mode 100644 index 9cb8373..0000000 --- a/internal/linker/patches/go1.23/0002-add-unexported-function-name-removing.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 05b8be787564fdcd9532e1aac5eca3ef41d4e0a1 Mon Sep 17 00:00:00 2001 -From: pagran -Date: Mon, 9 Jan 2023 13:30:36 +0100 -Subject: [PATCH 2/3] add unexported function name removing - ---- - cmd/link/internal/ld/pcln.go | 43 +++++++++++++++++++++++++++++++++++- - 1 file changed, 42 insertions(+), 1 deletion(-) - -diff --git a/cmd/link/internal/ld/pcln.go b/cmd/link/internal/ld/pcln.go -index c09ae07e33..056a1d3a72 100644 ---- a/cmd/link/internal/ld/pcln.go -+++ b/cmd/link/internal/ld/pcln.go -@@ -8,6 +8,10 @@ import ( - "os" - ) - -+import ( -+ "unicode" -+) -+ - import ( - "cmd/internal/goobj" - "cmd/internal/objabi" -@@ -318,19 +322,56 @@ func walkFuncs(ctxt *Link, funcs []loader.Sym, f func(loader.Sym)) { - func (state *pclntab) generateFuncnametab(ctxt *Link, funcs []loader.Sym) map[loader.Sym]uint32 { - nameOffsets := make(map[loader.Sym]uint32, state.nfunc) - -+ garbleTiny := os.Getenv("GARBLE_LINK_TINY") == "true" -+ - // Write the null terminated strings. - writeFuncNameTab := func(ctxt *Link, s loader.Sym) { - symtab := ctxt.loader.MakeSymbolUpdater(s) -+ if garbleTiny { -+ symtab.AddStringAt(0, "") -+ } -+ - for s, off := range nameOffsets { -+ if garbleTiny && off == 0 { -+ continue -+ } - symtab.AddCStringAt(int64(off), ctxt.loader.SymName(s)) - } - } - - // Loop through the CUs, and calculate the size needed. - var size int64 -+ -+ if garbleTiny { -+ size = 1 // first byte is reserved for empty string used for all non-exportable method names -+ } -+ // Kinds of SymNames found in the wild: -+ // -+ // * reflect.Value.CanAddr -+ // * reflect.(*Value).String -+ // * reflect.w6cEoKc -+ // * internal/abi.(*RegArgs).IntRegArgAddr -+ // * type:.eq.runtime.special -+ // * runtime/internal/atomic.(*Pointer[go.shape.string]).Store -+ // -+ // Checking whether the first rune after the last dot is uppercase seems enough. -+ isExported := func(name string) bool { -+ for _, r := range name[strings.LastIndexByte(name, '.')+1:] { -+ return unicode.IsUpper(r) -+ } -+ return false -+ } -+ - walkFuncs(ctxt, funcs, func(s loader.Sym) { -+ name := ctxt.loader.SymName(s) -+ -+ if garbleTiny && !isExported(name) { -+ nameOffsets[s] = 0 // redirect name to empty string -+ return -+ } -+ - nameOffsets[s] = uint32(size) -- size += int64(len(ctxt.loader.SymName(s)) + 1) // NULL terminate -+ size += int64(len(name) + 1) // NULL terminate - }) - - state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab) --- -2.46.0 - diff --git a/internal/linker/patches/go1.23/0003-add-entryOff-encryption.patch b/internal/linker/patches/go1.23/0003-add-entryOff-encryption.patch deleted file mode 100644 index 83b02b6..0000000 --- a/internal/linker/patches/go1.23/0003-add-entryOff-encryption.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 6bb03c1a0c523530b29fe6fdc48ca8f24f0bb13c Mon Sep 17 00:00:00 2001 -From: pagran -Date: Sat, 14 Jan 2023 21:36:16 +0100 -Subject: [PATCH 3/3] add entryOff encryption - ---- - cmd/link/internal/ld/pcln.go | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/cmd/link/internal/ld/pcln.go b/cmd/link/internal/ld/pcln.go -index 056a1d3a72..37226d0327 100644 ---- a/cmd/link/internal/ld/pcln.go -+++ b/cmd/link/internal/ld/pcln.go -@@ -806,6 +806,26 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym - sb.SetUint32(ctxt.Arch, dataoff, uint32(ldr.SymValue(fdsym)-gofuncBase)) - } - } -+ -+ // Moving next code higher is not recommended. -+ // Only at the end of the current function no edits between go versions -+ garbleEntryOffKeyStr := os.Getenv("GARBLE_LINK_ENTRYOFF_KEY") -+ if garbleEntryOffKeyStr == "" { -+ panic("[garble] entryOff key must be set") -+ } -+ var garbleEntryOffKey uint32 -+ // Use fmt package instead of strconv to avoid importing a new package -+ if _, err := fmt.Sscan(garbleEntryOffKeyStr, &garbleEntryOffKey); err != nil { -+ panic(fmt.Errorf("[garble] invalid entryOff key %s: %v", garbleEntryOffKeyStr, err)) -+ } -+ -+ garbleData := sb.Data() -+ for _, off := range startLocations { -+ entryOff := ctxt.Arch.ByteOrder.Uint32(garbleData[off:]) -+ nameOff := ctxt.Arch.ByteOrder.Uint32(garbleData[off+4:]) -+ -+ sb.SetUint32(ctxt.Arch, int64(off), entryOff^(nameOff*garbleEntryOffKey)) -+ } - } - - // pclntab initializes the pclntab symbol with --- -2.46.0 - diff --git a/main.go b/main.go index 7a96b4a..9874234 100644 --- a/main.go +++ b/main.go @@ -291,8 +291,8 @@ func (e errJustExit) Error() string { return fmt.Sprintf("exit: %d", e) } func goVersionOK() bool { const ( - minGoVersion = "go1.23.5" // the minimum Go version we support; could be a bugfix release if needed - unsupportedGo = "go1.25" // the first major version we don't support + minGoVersion = "go1.24" // the minimum Go version we support; could be a bugfix release if needed + unsupportedGo = "go1.25" // the first major version we don't support ) // rxVersion looks for a version like "go1.2" or "go1.2.3" in `go env GOVERSION`. diff --git a/scripts/gen_go_std_tables.go b/scripts/gen_go_std_tables.go index cb3aa52..9fb1f26 100644 --- a/scripts/gen_go_std_tables.go +++ b/scripts/gen_go_std_tables.go @@ -21,7 +21,7 @@ import ( "text/template" ) -var goVersions = []string{"go1.23.7", "go1.24.1"} +var goVersions = []string{"go1.24.1"} var tmplTables = template.Must(template.New("").Parse(` // Code generated by scripts/gen_go_std_tables.go; DO NOT EDIT. @@ -158,7 +158,7 @@ func main() { panic(err) } for _, goFile := range runtimeGoFiles { - for _, line := range strings.Split(readFile(goFile), "\n") { + for line := range strings.SplitSeq(readFile(goFile), "\n") { m := rxLinkname.FindStringSubmatch(line) if m == nil { continue @@ -189,13 +189,8 @@ func main() { compilerIntrinsicsIndexByPath := make(map[string]int) var compilerIntrinsics []tmplIntrinsic for _, goroot := range goroots { - // Go 1.24 moved the "alias" intrinsic calls from ssa.go to intrinsics.go. - name := "ssa.go" - if goroot.GoVersionLang == "go1.24" { - name = "intrinsics.go" - } - for _, line := range strings.Split(readFile(filepath.Join( - goroot.String, "src", "cmd", "compile", "internal", "ssagen", name, + for line := range strings.SplitSeq(readFile(filepath.Join( + goroot.String, "src", "cmd", "compile", "internal", "ssagen", "intrinsics.go", )), "\n") { m := rxIntrinsic.FindStringSubmatch(line) if m == nil { diff --git a/testdata/script/goversion.txtar b/testdata/script/goversion.txtar index 83b734f..2fcb6d5 100644 --- a/testdata/script/goversion.txtar +++ b/testdata/script/goversion.txtar @@ -7,31 +7,31 @@ env PATH=${WORK}/.bin${:}${PATH} # An empty go version. env TOOLCHAIN_GOVERSION='' ! exec garble build -stderr 'Go version is too old; please upgrade to go1\.23\.5 or newer' +stderr 'Go version is too old; please upgrade to go1\.24 or newer' # We should error on a devel version that's too old. # Note that they lacked the "goN.M-" prefix. env TOOLCHAIN_GOVERSION='devel +afb5fca Sun Aug 07 00:00:00 2020 +0000' ! exec garble build -stderr 'Go version is too old; please upgrade to go1\.23\.5 or newer' +stderr 'Go version is too old; please upgrade to go1\.24 or newer' # Another form of old version; with an old "goN.M-" prefix. env TOOLCHAIN_GOVERSION='devel go1.15-afb5fca Sun Aug 07 00:00:00 2020 +0000' ! exec garble build -stderr 'Go version "devel go1\.15-.*2020.*" is too old; please upgrade to go1\.23' +stderr 'Go version "devel go1\.15-.*2020.*" is too old; please upgrade to go1\.24 or newer' # A current devel version should be fine. # Note that we don't look at devel version timestamps. -env GARBLE_TEST_GOVERSION='go1.23.5' +env GARBLE_TEST_GOVERSION='go1.24.5' # TODO: temporarily disabled while we do not support tip. -# env TOOLCHAIN_GOVERSION='devel go1.23-ad97d204f0 Sun Sep 12 16:46:58 2023 +0000' +# env TOOLCHAIN_GOVERSION='devel go1.24-ad97d204f0 Sun Sep 12 16:46:58 2023 +0000' # ! exec garble build # stderr 'mocking the real build' # We should error on a stable version that's too old. env TOOLCHAIN_GOVERSION='go1.14' ! exec garble build -stderr 'Go version "go1\.14" is too old; please upgrade to go1\.23\.5 or newer' +stderr 'Go version "go1\.14" is too old; please upgrade to go1\.24 or newer' # We should reject a future stable version, as we don't have linker patches yet. # Note that we need to bump the version of Go that supposedly built it, too. @@ -41,39 +41,39 @@ env TOOLCHAIN_GOVERSION='go1.28.2' stderr 'Go version "go1\.28\.2" is too new; Go linker patches aren''t available for go1\.25 or later yet' # We should accept custom devel strings. -env TOOLCHAIN_GOVERSION='devel go1.23.5-somecustomversion' +env TOOLCHAIN_GOVERSION='devel go1.24.5-somecustomversion' ! exec garble build stderr 'mocking the real build' # The current toolchain may be older than the one that built garble. -env GARBLE_TEST_GOVERSION='go1.23.22' -env TOOLCHAIN_GOVERSION='go1.23.21' +env GARBLE_TEST_GOVERSION='go1.24.22' +env TOOLCHAIN_GOVERSION='go1.24.21' ! exec garble build stderr 'mocking the real build' # The current toolchain may be equal to the one that built garble. -env GARBLE_TEST_GOVERSION='go1.23.25' -env TOOLCHAIN_GOVERSION='go1.23.25' +env GARBLE_TEST_GOVERSION='go1.24.25' +env TOOLCHAIN_GOVERSION='go1.24.25' ! exec garble build stderr 'mocking the real build' # The current toolchain must not be newer than the one that built garble. env GARBLE_TEST_GOVERSION='go1.18' -env TOOLCHAIN_GOVERSION='go1.23.25' +env TOOLCHAIN_GOVERSION='go1.24.25' ! exec garble build -stderr 'garble was built with "go1\.18" and can''t be used with the newer "go1\.23\.25"; rebuild ' +stderr 'garble was built with "go1\.18" and can''t be used with the newer "go1\.24\.25"; rebuild ' # We'll error even if the difference is a minor (bugfix) level. # In practice it probably wouldn't matter, but in theory it could still lead to tricky bugs. -env GARBLE_TEST_GOVERSION='go1.23.11' -env TOOLCHAIN_GOVERSION='go1.23.14' +env GARBLE_TEST_GOVERSION='go1.24.11' +env TOOLCHAIN_GOVERSION='go1.24.14' ! exec garble build -stderr 'garble was built with "go1\.23\.11" and can''t be used with the newer "go1\.23\.14"; rebuild ' +stderr 'garble was built with "go1\.24\.11" and can''t be used with the newer "go1\.24\.14"; rebuild ' # If garble builds itself and is then used, it won't know what version built it. # As a fallback, we drop the comparison against the toolchain's version. env GARBLE_TEST_GOVERSION='bogus version' -env TOOLCHAIN_GOVERSION='go1.23.25' +env TOOLCHAIN_GOVERSION='go1.24.25' ! exec garble build stderr 'mocking the real build' -- go.mod --