Skip to content

Commit

Permalink
internal/linker: add Go patches rebased on go1.24rc3
Browse files Browse the repository at this point in the history
  • Loading branch information
mvdan committed Feb 9, 2025
1 parent 561158d commit e73e5d6
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
47 changes: 47 additions & 0 deletions internal/linker/patches/go1.24/0001-add-custom-magic-value.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
From 1eb3d02d33155831067ca7db2c6517108c4305ae 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

---
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 ea08fd3d31..7bae9f18c5 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.48.1

Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
From 2a691e00bc659059133cd5604c7a099981cf684c 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

---
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 7bae9f18c5..b497573b15 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.48.1

43 changes: 43 additions & 0 deletions internal/linker/patches/go1.24/0003-add-entryOff-encryption.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
From 03342e79193875d08bf3f88154e77a453b28c076 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

---
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 b497573b15..f1021fcee3 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.48.1

0 comments on commit e73e5d6

Please sign in to comment.