drop Go 1.25, support Go 1.26

Beyond the usual updating of version strings, re-running `go generate`,
and updating the patches for the linker, we needed extra changes.

First, the linker started being stricter about which packages
are allowed to linkname runtime names by import path.
Stop obfuscating import paths in runtimeAndLinknamed.

Second, the compiler's intrinsics code adds an "add" function
much like the existing "addF", so tweak the regular expression.

Third, note that there is a new runtimeAndDeps windows-only package,
which we find thanks to the recent improvement to cover many platforms.

Fourth, the code around magic numbers in the runtime has changed,
so rewrite the code which patches it via go/ast.

Fixes #990.
This commit is contained in:
Daniel Martí
2026-02-11 22:12:25 +00:00
committed by Paul
parent 529ee19380
commit 7114403786
13 changed files with 324 additions and 315 deletions
+9 -9
View File
@@ -25,11 +25,11 @@ jobs:
test:
strategy:
matrix:
go-version: [1.25.x]
go-version: [1.26.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
@@ -53,17 +53,17 @@ jobs:
# Static checks from this point forward. Only run on one Go version and on
# linux, since it's the fastest platform, and the tools behave the same.
- name: Test third-party project builds
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.25.x'
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.26.x'
run: |
go install
./scripts/check-third-party.sh
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.25.x'
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.26.x'
run: ./scripts/crlf-test.sh
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.25.x'
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.26.x'
run: diff <(echo -n) <(gofmt -d .)
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.25.x'
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.26.x'
run: go vet ./...
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.25.x'
- if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.26.x'
uses: dominikh/staticcheck-action@v1
with:
version: "2025.1"
@@ -78,9 +78,9 @@ jobs:
env:
GOARCH: 386
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: actions/setup-go@v5
with:
go-version: 1.25.x
go-version: 1.26.x
cache: false
- run: go test -short ./...
+1 -1
View File
@@ -2,7 +2,7 @@
go install mvdan.cc/garble@latest
Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.25 or later.
Obfuscate Go code by wrapping the Go toolchain. Requires Go 1.26 or later.
garble build [build flags] [packages]
+11 -3
View File
@@ -243,9 +243,6 @@ func (p *listedPackage) obfuscatedImportPath() string {
case "runtime", "reflect", "embed",
// TODO: collect directly from cmd/internal/objabi/pkgspecial.go,
// in this particular case from allowAsmABIPkgs.
"syscall",
"internal/bytealg",
"internal/chacha8rand",
"internal/runtime/syscall/linux",
"internal/runtime/syscall/windows",
"internal/runtime/startlinetest":
@@ -255,6 +252,17 @@ func (p *listedPackage) obfuscatedImportPath() string {
if _, ok := compilerIntrinsics[p.ImportPath]; ok {
return p.ImportPath
}
// The linker forbids linknaming to certain runtime declarations
// unless a package is known to be allowed by import path string.
// The alternative would be to use -checklinkname=false, but that disables all checks entirely.
//
// TODO: we could probably remove this once we obfuscate the runtime,
// because then these runtime package and declaration names will be obfuscated too,
// so the linker will stop recognising them for the extra checks.
if _, ok := runtimeAndLinknamed[p.ImportPath]; ok {
return p.ImportPath
}
newPath := hashWithPackage(p, p.ImportPath)
log.Printf("import path %q hashed with %x to %q", p.ImportPath, p.GarbleActionID, newPath)
return newPath
+1 -1
View File
@@ -1,6 +1,6 @@
module mvdan.cc/garble
go 1.25
go 1.26
require (
github.com/bluekeyes/go-gitdiff v0.8.1
+238 -221
View File
@@ -1,39 +1,43 @@
// Code generated by scripts/gen_go_std_tables.go; DO NOT EDIT.
// Generated from Go versions [go1.25.8].
// Generated from Go versions [go1.26.1].
package main
// runtimeAndDeps contains the runtime package and all of its transitive dependencies
// as reported by 'go list -deps'.
var runtimeAndDeps = map[string]bool{
"internal/abi": true, // go1.25 linux/amd64
"internal/asan": true, // go1.25 linux/amd64
"internal/bytealg": true, // go1.25 linux/amd64
"internal/byteorder": true, // go1.25 linux/amd64
"internal/chacha8rand": true, // go1.25 linux/amd64
"internal/coverage/rtcov": true, // go1.25 linux/amd64
"internal/cpu": true, // go1.25 linux/amd64
"internal/goarch": true, // go1.25 linux/amd64
"internal/godebugs": true, // go1.25 linux/amd64
"internal/goexperiment": true, // go1.25 linux/amd64
"internal/goos": true, // go1.25 linux/amd64
"internal/msan": true, // go1.25 linux/amd64
"internal/profilerecord": true, // go1.25 linux/amd64
"internal/race": true, // go1.25 linux/amd64
"internal/runtime/atomic": true, // go1.25 linux/amd64
"internal/runtime/cgroup": true, // go1.25 linux/amd64
"internal/runtime/exithook": true, // go1.25 linux/amd64
"internal/runtime/gc": true, // go1.25 linux/amd64
"internal/runtime/maps": true, // go1.25 linux/amd64
"internal/runtime/math": true, // go1.25 linux/amd64
"internal/runtime/strconv": true, // go1.25 linux/amd64
"internal/runtime/sys": true, // go1.25 linux/amd64
"internal/runtime/syscall": true, // go1.25 linux/amd64
"internal/stringslite": true, // go1.25 linux/amd64
"internal/trace/tracev2": true, // go1.25 linux/amd64
"runtime": true, // go1.25 linux/amd64
"unsafe": true, // go1.25 linux/amd64
"internal/abi": true, // go1.26 linux/amd64
"internal/asan": true, // go1.26 linux/amd64
"internal/bytealg": true, // go1.26 linux/amd64
"internal/byteorder": true, // go1.26 linux/amd64
"internal/chacha8rand": true, // go1.26 linux/amd64
"internal/coverage/rtcov": true, // go1.26 linux/amd64
"internal/cpu": true, // go1.26 linux/amd64
"internal/goarch": true, // go1.26 linux/amd64
"internal/godebugs": true, // go1.26 linux/amd64
"internal/goexperiment": true, // go1.26 linux/amd64
"internal/goos": true, // go1.26 linux/amd64
"internal/msan": true, // go1.26 linux/amd64
"internal/profilerecord": true, // go1.26 linux/amd64
"internal/race": true, // go1.26 linux/amd64
"internal/runtime/atomic": true, // go1.26 linux/amd64
"internal/runtime/cgroup": true, // go1.26 linux/amd64
"internal/runtime/exithook": true, // go1.26 linux/amd64
"internal/runtime/gc": true, // go1.26 linux/amd64
"internal/runtime/gc/scan": true, // go1.26 linux/amd64
"internal/runtime/maps": true, // go1.26 linux/amd64
"internal/runtime/math": true, // go1.26 linux/amd64
"internal/runtime/pprof/label": true, // go1.26 linux/amd64
"internal/runtime/sys": true, // go1.26 linux/amd64
"internal/runtime/syscall/linux": true, // go1.26 linux/amd64
"internal/runtime/syscall/windows": true, // go1.26 windows/386
"internal/strconv": true, // go1.26 linux/amd64
"internal/stringslite": true, // go1.26 linux/amd64
"internal/trace/tracev2": true, // go1.26 linux/amd64
"math/bits": true, // go1.26 linux/amd64
"runtime": true, // go1.26 linux/amd64
"unsafe": true, // go1.26 linux/amd64
}
// runtimeAndLinknamed contains the runtime package and all the packages
@@ -47,45 +51,48 @@ var runtimeAndDeps = map[string]bool{
// from the runtime package via //go:linkname directives on those platforms.
// To make sure we have coverage on all platforms, we allow duplicates.
var runtimeAndLinknamed = map[string]bool{
"arena": true, // go1.25
"crypto/internal/boring": true, // go1.25
"crypto/internal/boring/bcache": true, // go1.25
"crypto/internal/fips140": true, // go1.25
"crypto/internal/sysrand": true, // go1.25
"crypto/rand": true, // go1.25
"crypto/x509/internal/macos": true, // go1.25
"internal/bytealg": true, // go1.25
"internal/coverage/cfile": true, // go1.25
"internal/cpu": true, // go1.25
"internal/godebug": true, // go1.25
"internal/poll": true, // go1.25
"internal/race": true, // go1.25
"internal/reflectlite": true, // go1.25
"internal/runtime/atomic": true, // go1.25
"internal/runtime/cgroup": true, // go1.25
"internal/runtime/maps": true, // go1.25
"internal/sync": true, // go1.25
"internal/synctest": true, // go1.25
"internal/syscall/unix": true, // go1.25
"internal/syscall/windows": true, // go1.25
"maps": true, // go1.25
"os": true, // go1.25
"os/signal": true, // go1.25
"plugin": true, // go1.25
"reflect": true, // go1.25
"runtime": true, // go1.25
"runtime/debug": true, // go1.25
"runtime/metrics": true, // go1.25
"runtime/pprof": true, // go1.25
"runtime/trace": true, // go1.25
"sync": true, // go1.25
"sync/atomic": true, // go1.25
"sync_test": true, // go1.25
"syscall": true, // go1.25
"syscall/js": true, // go1.25
"time": true, // go1.25
"unique": true, // go1.25
"weak": true, // go1.25
"arena": true, // go1.26
"crypto/fips140": true, // go1.26
"crypto/internal/boring": true, // go1.26
"crypto/internal/boring/bcache": true, // go1.26
"crypto/internal/fips140": true, // go1.26
"crypto/internal/sysrand": true, // go1.26
"crypto/rand": true, // go1.26
"crypto/subtle": true, // go1.26
"crypto/x509/internal/macos": true, // go1.26
"internal/bytealg": true, // go1.26
"internal/coverage/cfile": true, // go1.26
"internal/cpu": true, // go1.26
"internal/godebug": true, // go1.26
"internal/poll": true, // go1.26
"internal/race": true, // go1.26
"internal/reflectlite": true, // go1.26
"internal/runtime/atomic": true, // go1.26
"internal/runtime/cgroup": true, // go1.26
"internal/runtime/maps": true, // go1.26
"internal/sync": true, // go1.26
"internal/synctest": true, // go1.26
"internal/syscall/unix": true, // go1.26
"internal/syscall/windows": true, // go1.26
"maps": true, // go1.26
"os": true, // go1.26
"os/signal": true, // go1.26
"plugin": true, // go1.26
"reflect": true, // go1.26
"runtime": true, // go1.26
"runtime/debug": true, // go1.26
"runtime/metrics": true, // go1.26
"runtime/pprof": true, // go1.26
"runtime/secret": true, // go1.26
"runtime/trace": true, // go1.26
"sync": true, // go1.26
"sync/atomic": true, // go1.26
"sync_test": true, // go1.26
"syscall": true, // go1.26
"syscall/js": true, // go1.26
"time": true, // go1.26
"unique": true, // go1.26
"weak": true, // go1.26
// The net package linknames to the runtime, not the other way around.
"net": true,
// The testing package uses a //go:linkname directive pointing to testing/synctest,
@@ -94,179 +101,189 @@ var runtimeAndLinknamed = map[string]bool{
}
var compilerIntrinsics = map[string]map[string]bool{
"crypto/internal/constanttime": {
"Select": true, // go1.26
"boolToUint8": true, // go1.26
},
"internal/runtime/atomic": {
"And": true, // go1.25
"And32": true, // go1.25
"And64": true, // go1.25
"And8": true, // go1.25
"Anduintptr": true, // go1.25
"Cas": true, // go1.25
"Cas64": true, // go1.25
"CasRel": true, // go1.25
"Casint32": true, // go1.25
"Casint64": true, // go1.25
"Casp1": true, // go1.25
"Casuintptr": true, // go1.25
"Load": true, // go1.25
"Load64": true, // go1.25
"Load8": true, // go1.25
"LoadAcq": true, // go1.25
"LoadAcq64": true, // go1.25
"LoadAcquintptr": true, // go1.25
"Loadint32": true, // go1.25
"Loadint64": true, // go1.25
"Loadp": true, // go1.25
"Loaduint": true, // go1.25
"Loaduintptr": true, // go1.25
"Or": true, // go1.25
"Or32": true, // go1.25
"Or64": true, // go1.25
"Or8": true, // go1.25
"Oruintptr": true, // go1.25
"Store": true, // go1.25
"Store64": true, // go1.25
"Store8": true, // go1.25
"StoreRel": true, // go1.25
"StoreRel64": true, // go1.25
"StoreReluintptr": true, // go1.25
"Storeint32": true, // go1.25
"Storeint64": true, // go1.25
"StorepNoWB": true, // go1.25
"Storeuintptr": true, // go1.25
"Xadd": true, // go1.25
"Xadd64": true, // go1.25
"Xaddint32": true, // go1.25
"Xaddint64": true, // go1.25
"Xadduintptr": true, // go1.25
"Xchg": true, // go1.25
"Xchg64": true, // go1.25
"Xchg8": true, // go1.25
"Xchgint32": true, // go1.25
"Xchgint64": true, // go1.25
"Xchguintptr": true, // go1.25
"And": true, // go1.26
"And32": true, // go1.26
"And64": true, // go1.26
"And8": true, // go1.26
"Anduintptr": true, // go1.26
"Cas": true, // go1.26
"Cas64": true, // go1.26
"CasRel": true, // go1.26
"Casint32": true, // go1.26
"Casint64": true, // go1.26
"Casp1": true, // go1.26
"Casuintptr": true, // go1.26
"Load": true, // go1.26
"Load64": true, // go1.26
"Load8": true, // go1.26
"LoadAcq": true, // go1.26
"LoadAcq64": true, // go1.26
"LoadAcquintptr": true, // go1.26
"Loadint32": true, // go1.26
"Loadint64": true, // go1.26
"Loadp": true, // go1.26
"Loaduint": true, // go1.26
"Loaduintptr": true, // go1.26
"Or": true, // go1.26
"Or32": true, // go1.26
"Or64": true, // go1.26
"Or8": true, // go1.26
"Oruintptr": true, // go1.26
"Store": true, // go1.26
"Store64": true, // go1.26
"Store8": true, // go1.26
"StoreRel": true, // go1.26
"StoreRel64": true, // go1.26
"StoreReluintptr": true, // go1.26
"Storeint32": true, // go1.26
"Storeint64": true, // go1.26
"StorepNoWB": true, // go1.26
"Storeuintptr": true, // go1.26
"Xadd": true, // go1.26
"Xadd64": true, // go1.26
"Xaddint32": true, // go1.26
"Xaddint64": true, // go1.26
"Xadduintptr": true, // go1.26
"Xchg": true, // go1.26
"Xchg64": true, // go1.26
"Xchg8": true, // go1.26
"Xchgint32": true, // go1.26
"Xchgint64": true, // go1.26
"Xchguintptr": true, // go1.26
},
"internal/runtime/maps": {
"bitsetFirst": true, // go1.25
"bitsetLowestSet": true, // go1.25
"bitsetRemoveBelow": true, // go1.25
"bitsetShiftOutLowest": true, // go1.25
"ctrlGroupMatchEmpty": true, // go1.25
"ctrlGroupMatchEmptyOrDeleted": true, // go1.25
"ctrlGroupMatchFull": true, // go1.25
"ctrlGroupMatchH2": true, // go1.25
"bitsetFirst": true, // go1.26
"bitsetLowestSet": true, // go1.26
"bitsetRemoveBelow": true, // go1.26
"bitsetShiftOutLowest": true, // go1.26
"ctrlGroupMatchEmpty": true, // go1.26
"ctrlGroupMatchEmptyOrDeleted": true, // go1.26
"ctrlGroupMatchFull": true, // go1.26
"ctrlGroupMatchH2": true, // go1.26
},
"internal/runtime/math": {
"Add64": true, // go1.25
"Mul64": true, // go1.25
"MulUintptr": true, // go1.25
"Add64": true, // go1.26
"Mul64": true, // go1.26
"MulUintptr": true, // go1.26
},
"internal/runtime/sys": {
"Bswap32": true, // go1.25
"Bswap64": true, // go1.25
"Len64": true, // go1.25
"Len8": true, // go1.25
"OnesCount64": true, // go1.25
"Prefetch": true, // go1.25
"PrefetchStreamed": true, // go1.25
"TrailingZeros32": true, // go1.25
"TrailingZeros64": true, // go1.25
"TrailingZeros8": true, // go1.25
"Bswap32": true, // go1.26
"Bswap64": true, // go1.26
"GetCallerPC": true, // go1.26
"GetCallerSP": true, // go1.26
"GetClosurePtr": true, // go1.26
"Len64": true, // go1.26
"Len8": true, // go1.26
"OnesCount64": true, // go1.26
"Prefetch": true, // go1.26
"PrefetchStreamed": true, // go1.26
"TrailingZeros32": true, // go1.26
"TrailingZeros64": true, // go1.26
"TrailingZeros8": true, // go1.26
},
"math": {
"Abs": true, // go1.25
"Ceil": true, // go1.25
"Copysign": true, // go1.25
"FMA": true, // go1.25
"Floor": true, // go1.25
"Round": true, // go1.25
"RoundToEven": true, // go1.25
"Trunc": true, // go1.25
"sqrt": true, // go1.25
"Abs": true, // go1.26
"Ceil": true, // go1.26
"Copysign": true, // go1.26
"FMA": true, // go1.26
"Floor": true, // go1.26
"Round": true, // go1.26
"RoundToEven": true, // go1.26
"Trunc": true, // go1.26
"sqrt": true, // go1.26
},
"math/big": {
"mulWW": true, // go1.25
"mulWW": true, // go1.26
},
"math/bits": {
"Add": true, // go1.25
"Add64": true, // go1.25
"Div": true, // go1.25
"Div64": true, // go1.25
"Len": true, // go1.25
"Len16": true, // go1.25
"Len32": true, // go1.25
"Len64": true, // go1.25
"Len8": true, // go1.25
"Mul": true, // go1.25
"Mul64": true, // go1.25
"OnesCount": true, // go1.25
"OnesCount16": true, // go1.25
"OnesCount32": true, // go1.25
"OnesCount64": true, // go1.25
"OnesCount8": true, // go1.25
"Reverse": true, // go1.25
"Reverse16": true, // go1.25
"Reverse32": true, // go1.25
"Reverse64": true, // go1.25
"Reverse8": true, // go1.25
"ReverseBytes16": true, // go1.25
"ReverseBytes32": true, // go1.25
"ReverseBytes64": true, // go1.25
"RotateLeft": true, // go1.25
"RotateLeft16": true, // go1.25
"RotateLeft32": true, // go1.25
"RotateLeft64": true, // go1.25
"RotateLeft8": true, // go1.25
"Sub": true, // go1.25
"Sub64": true, // go1.25
"TrailingZeros16": true, // go1.25
"TrailingZeros32": true, // go1.25
"TrailingZeros64": true, // go1.25
"TrailingZeros8": true, // go1.25
"Add": true, // go1.26
"Add64": true, // go1.26
"Div": true, // go1.26
"Div64": true, // go1.26
"Len": true, // go1.26
"Len16": true, // go1.26
"Len32": true, // go1.26
"Len64": true, // go1.26
"Len8": true, // go1.26
"Mul": true, // go1.26
"Mul64": true, // go1.26
"OnesCount": true, // go1.26
"OnesCount16": true, // go1.26
"OnesCount32": true, // go1.26
"OnesCount64": true, // go1.26
"OnesCount8": true, // go1.26
"Reverse": true, // go1.26
"Reverse16": true, // go1.26
"Reverse32": true, // go1.26
"Reverse64": true, // go1.26
"Reverse8": true, // go1.26
"ReverseBytes16": true, // go1.26
"ReverseBytes32": true, // go1.26
"ReverseBytes64": true, // go1.26
"RotateLeft": true, // go1.26
"RotateLeft16": true, // go1.26
"RotateLeft32": true, // go1.26
"RotateLeft64": true, // go1.26
"RotateLeft8": true, // go1.26
"Sub": true, // go1.26
"Sub64": true, // go1.26
"TrailingZeros16": true, // go1.26
"TrailingZeros32": true, // go1.26
"TrailingZeros64": true, // go1.26
"TrailingZeros8": true, // go1.26
},
"runtime": {
"publicationBarrier": true, // go1.25
"KeepAlive": true, // go1.26
"memequal": true, // go1.26
"publicationBarrier": true, // go1.26
"slicebytetostringtmp": true, // go1.26
},
"sync": {
"runtime_LoadAcquintptr": true, // go1.25
"runtime_StoreReluintptr": true, // go1.25
"runtime_LoadAcquintptr": true, // go1.26
"runtime_StoreReluintptr": true, // go1.26
},
"sync/atomic": {
"AddInt32": true, // go1.25
"AddInt64": true, // go1.25
"AddUint32": true, // go1.25
"AddUint64": true, // go1.25
"AddUintptr": true, // go1.25
"AndInt32": true, // go1.25
"AndInt64": true, // go1.25
"AndUint32": true, // go1.25
"AndUint64": true, // go1.25
"AndUintptr": true, // go1.25
"CompareAndSwapInt32": true, // go1.25
"CompareAndSwapInt64": true, // go1.25
"CompareAndSwapUint32": true, // go1.25
"CompareAndSwapUint64": true, // go1.25
"CompareAndSwapUintptr": true, // go1.25
"LoadInt32": true, // go1.25
"LoadInt64": true, // go1.25
"LoadPointer": true, // go1.25
"LoadUint32": true, // go1.25
"LoadUint64": true, // go1.25
"LoadUintptr": true, // go1.25
"OrInt32": true, // go1.25
"OrInt64": true, // go1.25
"OrUint32": true, // go1.25
"OrUint64": true, // go1.25
"OrUintptr": true, // go1.25
"StoreInt32": true, // go1.25
"StoreInt64": true, // go1.25
"StoreUint32": true, // go1.25
"StoreUint64": true, // go1.25
"StoreUintptr": true, // go1.25
"SwapInt32": true, // go1.25
"SwapInt64": true, // go1.25
"SwapUint32": true, // go1.25
"SwapUint64": true, // go1.25
"SwapUintptr": true, // go1.25
"AddInt32": true, // go1.26
"AddInt64": true, // go1.26
"AddUint32": true, // go1.26
"AddUint64": true, // go1.26
"AddUintptr": true, // go1.26
"AndInt32": true, // go1.26
"AndInt64": true, // go1.26
"AndUint32": true, // go1.26
"AndUint64": true, // go1.26
"AndUintptr": true, // go1.26
"CompareAndSwapInt32": true, // go1.26
"CompareAndSwapInt64": true, // go1.26
"CompareAndSwapUint32": true, // go1.26
"CompareAndSwapUint64": true, // go1.26
"CompareAndSwapUintptr": true, // go1.26
"LoadInt32": true, // go1.26
"LoadInt64": true, // go1.26
"LoadPointer": true, // go1.26
"LoadUint32": true, // go1.26
"LoadUint64": true, // go1.26
"LoadUintptr": true, // go1.26
"OrInt32": true, // go1.26
"OrInt64": true, // go1.26
"OrUint32": true, // go1.26
"OrUint64": true, // go1.26
"OrUintptr": true, // go1.26
"StoreInt32": true, // go1.26
"StoreInt64": true, // go1.26
"StoreUint32": true, // go1.26
"StoreUint64": true, // go1.26
"StoreUintptr": true, // go1.26
"SwapInt32": true, // go1.26
"SwapInt64": true, // go1.26
"SwapUint32": true, // go1.26
"SwapUint64": true, // go1.26
"SwapUintptr": true, // go1.26
},
}
@@ -1,4 +1,4 @@
From 1eb3d02d33155831067ca7db2c6517108c4305ae Mon Sep 17 00:00:00 2001
From b59e8e940e82f488d5d688277046f6cd87c75908 Mon Sep 17 00:00:00 2001
From: pagran <pagran@protonmail.com>
Date: Mon, 9 Jan 2023 13:30:00 +0100
Subject: [PATCH 1/3] add custom magic value
@@ -8,7 +8,7 @@ Subject: [PATCH 1/3] add custom magic value
1 file changed, 17 insertions(+)
diff --git a/cmd/link/internal/ld/pcln.go b/cmd/link/internal/ld/pcln.go
index ea08fd3d31..7bae9f18c5 100644
index 08c4d4db83..ffe8fdf7a1 100644
--- a/cmd/link/internal/ld/pcln.go
+++ b/cmd/link/internal/ld/pcln.go
@@ -4,6 +4,10 @@
@@ -22,7 +22,7 @@ index ea08fd3d31..7bae9f18c5 100644
import (
"cmd/internal/goobj"
"cmd/internal/objabi"
@@ -262,6 +266,19 @@ func (state *pclntab) generatePCHeader(ctxt *Link) {
@@ -282,6 +286,19 @@ func (state *pclntab) generatePCHeader(ctxt *Link) {
if off != size {
panic(fmt.Sprintf("pcHeader size: %d != %d", off, size))
}
@@ -41,7 +41,7 @@ index ea08fd3d31..7bae9f18c5 100644
+ header.SetUint32(ctxt.Arch, 0, garbleMagicVal)
}
state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader)
state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, int32(ctxt.Arch.PtrSize), writeHeader)
--
2.48.1
2.53.0
@@ -1,4 +1,4 @@
From 2a691e00bc659059133cd5604c7a099981cf684c Mon Sep 17 00:00:00 2001
From 0d8063d9af410ceb914ba75b19a98686fe5f119c Mon Sep 17 00:00:00 2001
From: pagran <pagran@protonmail.com>
Date: Mon, 9 Jan 2023 13:30:36 +0100
Subject: [PATCH 2/3] add unexported function name removing
@@ -8,7 +8,7 @@ Subject: [PATCH 2/3] add unexported function name removing
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/cmd/link/internal/ld/pcln.go b/cmd/link/internal/ld/pcln.go
index 7bae9f18c5..b497573b15 100644
index ffe8fdf7a1..c47b9eab72 100644
--- a/cmd/link/internal/ld/pcln.go
+++ b/cmd/link/internal/ld/pcln.go
@@ -8,6 +8,10 @@ import (
@@ -22,7 +22,7 @@ index 7bae9f18c5..b497573b15 100644
import (
"cmd/internal/goobj"
"cmd/internal/objabi"
@@ -318,19 +322,56 @@ func walkFuncs(ctxt *Link, funcs []loader.Sym, f func(loader.Sym)) {
@@ -335,19 +339,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)
@@ -79,7 +79,7 @@ index 7bae9f18c5..b497573b15 100644
+ size += int64(len(name) + 1) // NULL terminate
})
state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab)
state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, 1, writeFuncNameTab)
--
2.48.1
2.53.0
@@ -1,4 +1,4 @@
From 03342e79193875d08bf3f88154e77a453b28c076 Mon Sep 17 00:00:00 2001
From 16b978956b323d88ef4a48dbef124304f5206e90 Mon Sep 17 00:00:00 2001
From: pagran <pagran@protonmail.com>
Date: Sat, 14 Jan 2023 21:36:16 +0100
Subject: [PATCH 3/3] add entryOff encryption
@@ -8,11 +8,11 @@ Subject: [PATCH 3/3] add entryOff encryption
1 file changed, 20 insertions(+)
diff --git a/cmd/link/internal/ld/pcln.go b/cmd/link/internal/ld/pcln.go
index b497573b15..f1021fcee3 100644
index c47b9eab72..d58338f7c3 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))
@@ -980,6 +980,26 @@ func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSym
sb.SetUint32(ctxt.Arch, dataoff, uint32(ldr.SymValue(fdsym)))
}
}
+
@@ -39,5 +39,5 @@ index b497573b15..f1021fcee3 100644
// pclntab initializes the pclntab symbol with
--
2.48.1
2.53.0
+2 -2
View File
@@ -544,8 +544,8 @@ func (f *seedFlag) Set(s string) error {
func goVersionOK() bool {
const (
minGoVersion = "go1.25.0" // the minimum Go version we support; could be a bugfix release if needed
unsupportedGo = "go1.26" // the first major version we don't support
minGoVersion = "go1.26.0" // the minimum Go version we support; could be a bugfix release if needed
unsupportedGo = "go1.27" // the first major version we don't support
)
toolchainVersion := sharedCache.GoEnv.GOVERSION
+20 -36
View File
@@ -12,46 +12,30 @@ import (
ah "mvdan.cc/garble/internal/asthelper"
)
// updateMagicValue updates hardcoded value of hdr.magic
// when verifying header in symtab.go
// updateMagicValue updates the global constant
// `Go120PCLnTabMagic PCLnTabMagic = 0xfffffff1`
// to use the provided magic value integer.
// This is the latest magic value in use as of Go 1.26.
func updateMagicValue(file *ast.File, magicValue uint32) {
magicUpdated := false
// Find `hdr.magic != 0xfffffff?` in symtab.go and update to random magicValue
updateMagic := func(node ast.Node) bool {
binExpr, ok := node.(*ast.BinaryExpr)
if !ok || binExpr.Op != token.NEQ {
return true
}
selectorExpr, ok := binExpr.X.(*ast.SelectorExpr)
if !ok {
return true
}
if ident, ok := selectorExpr.X.(*ast.Ident); !ok || ident.Name != "hdr" {
return true
}
if selectorExpr.Sel.Name != "magic" {
return true
}
if _, ok := binExpr.Y.(*ast.BasicLit); !ok {
return true
}
binExpr.Y = &ast.BasicLit{
Kind: token.INT,
Value: strconv.FormatUint(uint64(magicValue), 10),
}
magicUpdated = true
return false
}
for _, decl := range file.Decls {
funcDecl, ok := decl.(*ast.FuncDecl)
if ok && funcDecl.Name.Name == "moduledataverify1" {
ast.Inspect(funcDecl, updateMagic)
break
decl, ok := decl.(*ast.GenDecl)
if !ok || decl.Tok != token.CONST {
continue
}
for _, spec := range decl.Specs {
spec, ok := spec.(*ast.ValueSpec)
if !ok || len(spec.Names) != 1 || len(spec.Values) != 1 {
continue
}
if spec.Names[0].Name == "Go120PCLnTabMagic" {
spec.Values[0] = &ast.BasicLit{
Kind: token.INT,
Value: strconv.FormatUint(uint64(magicValue), 10),
}
magicUpdated = true
}
}
}
+2 -2
View File
@@ -37,7 +37,7 @@ var goPlatforms = []goPlatform{
{"darwin", "arm64", 2},
{"windows", "386", 3},
}
var goVersions = []string{"go1.25.8"}
var goVersions = []string{"go1.26.1"}
var tmplTables = template.Must(template.New("").Parse(`
// Code generated by scripts/gen_go_std_tables.go; DO NOT EDIT.
@@ -173,7 +173,7 @@ func lines(vs versionedString) []versionedString {
}
var rxLinkname = regexp.MustCompile(`^//go:linkname .* ([^.]*)\.[^.]*$`)
var rxIntrinsic = regexp.MustCompile(`\b(addF|alias)\("([^"]*)", "([^"]*)",`)
var rxIntrinsic = regexp.MustCompile(`\b(add|addF|alias)\("([^"]*)", "([^"]*)",`)
func main() {
var runtimeAndDeps []versionedString
+19 -23
View File
@@ -7,12 +7,12 @@ 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\.25\.0 or newer'
stderr 'Go version is too old; please upgrade to go1\.26\.0 or newer'
# A clearly invalid go version.
env TOOLCHAIN_GOVERSION='bogus version'
! exec garble build
stderr 'Go version "bogus" appears to be invalid or too old; use go1\.25\.0 or newer'
stderr 'Go version "bogus" appears to be invalid or too old; use go1\.26\.0 or newer'
# We should error on a devel version that's too old;
# note that they started with the string "devel",
@@ -26,64 +26,60 @@ stderr 'Go version .* appears to be invalid or too old'
# A current devel version should be fine.
# Note that we don't look at devel version timestamps.
env GARBLE_TEST_GOVERSION='go1.25.0'
# TODO: we do not currently bother with supporting tip.
# env TOOLCHAIN_GOVERSION='go version go1.26-devel_36863d6194 2025-10-17 01:07:59 -0700 linux/amd64'
# ! exec garble build
# stderr 'mocking the real build'
env GARBLE_TEST_GOVERSION='go1.26.0'
# 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\.25\.0 or newer'
stderr 'Go version "go1\.14" is too old; please upgrade to go1\.26\.0 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.
env GARBLE_TEST_GOVERSION='go1.28.2'
env TOOLCHAIN_GOVERSION='go1.28.2'
env GARBLE_TEST_GOVERSION='go1.38.2'
env TOOLCHAIN_GOVERSION='go1.38.2'
! exec garble build
stderr 'Go version "go1\.28\.2" is too new; Go linker patches aren''t available for go1\.26 or later yet'
stderr 'Go version "go1\.38\.2" is too new; Go linker patches aren''t available for go1\.27 or later yet'
# We should accept custom devel strings.
env TOOLCHAIN_GOVERSION='go1.25.0-somecustomversion'
env TOOLCHAIN_GOVERSION='go1.26.0-somecustomversion'
! exec garble build
stderr 'mocking the real build'
# A stable version with a build-time GOEXPERIMENT.
# See: https://github.com/golang/go/issues/75953
env TOOLCHAIN_GOVERSION='go1.25.0 X:nodwarf5'
env TOOLCHAIN_GOVERSION='go1.26.0 X:nodwarf5'
! 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.25.1'
env TOOLCHAIN_GOVERSION='go1.25.0'
env GARBLE_TEST_GOVERSION='go1.26.1'
env TOOLCHAIN_GOVERSION='go1.26.0'
! 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.25.0'
env TOOLCHAIN_GOVERSION='go1.25.0'
env GARBLE_TEST_GOVERSION='go1.26.0'
env TOOLCHAIN_GOVERSION='go1.26.0'
! 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.25.0'
env TOOLCHAIN_GOVERSION='go1.26.0'
! exec garble build
stderr 'garble was built with "go1\.18" and can''t be used with the newer "go1\.25\.0"; rebuild '
stderr 'garble was built with "go1\.18" and can''t be used with the newer "go1\.26\.0"; 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.25.11'
env TOOLCHAIN_GOVERSION='go1.25.14'
env GARBLE_TEST_GOVERSION='go1.26.11'
env TOOLCHAIN_GOVERSION='go1.26.14'
! exec garble build
stderr 'garble was built with "go1\.25\.11" and can''t be used with the newer "go1\.25\.14"; rebuild '
stderr 'garble was built with "go1\.26\.11" and can''t be used with the newer "go1\.26\.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.25.0'
env TOOLCHAIN_GOVERSION='go1.26.0'
! exec garble build
stderr 'mocking the real build'
-- go.mod --
+6 -2
View File
@@ -695,16 +695,20 @@ func (tf *transformer) transformCompile(args []string) ([]string, error) {
for i, file := range files {
basename := filepath.Base(paths[i])
log.Printf("obfuscating %s", basename)
if tf.curPkg.ImportPath == "runtime" {
switch tf.curPkg.ImportPath {
case "runtime":
if flagTiny {
// strip unneeded runtime code
stripRuntime(basename, file)
tf.useAllImports(file)
}
if basename == "symtab.go" {
updateMagicValue(file, magicValue())
updateEntryOffset(file, entryOffKey())
}
case "internal/abi":
if basename == "symtab.go" {
updateMagicValue(file, magicValue())
}
}
if err := tf.transformDirectives(file.Comments); err != nil {
return nil, err