update gotip and adapt to upstream changes

https://go.dev/cl/466095 lightly refactored the runtime
in a way that broke extractNameOff. In particular, the code

	func cfuncname(f funcInfo) *byte {
		if !f.valid() || f.nameOff == 0 {
			return nil
		}
		return &f.datap.funcnametab[f.nameOff]
	}
	func funcname(f funcInfo) string {
		return gostringnocopy(cfuncname(f))
	}

is now simply

	func funcname(f funcInfo) string {
		if !f.valid() {
			return ""
		}
		return f.datap.funcName(f.nameOff)
	}

Since extractNameOff looked for the func named cfuncname,
and looked for the nameOff selector inside an index expression,
all of that code no longer worked properly.

It all existed to find the name of the field, nameOff,
so that we would automatically adapt if upstream renames it.
Unsurprisingly, the code using the field got refactored first.
It doesn't seem like the extra code on our part is helping us,
and assuming the name of the field works for all Go versions,
so do that instead.

If upstream does rename the field in the future,
the obfuscated Go builds will start failing in an obvious way.
If or when that comes to pass, we can change our constant string.
pull/706/head
Daniel Martí 1 year ago
parent 9d04637009
commit 1f39d0af72

@ -84,7 +84,7 @@ jobs:
steps:
- name: Install Go
env:
GO_COMMIT: ffb07d0c66db2f3f33faedf2927f9aa476d47720 # 2023-02-25
GO_COMMIT: 70f98a251efdbfd619c4ff466a43da299ad04752 # 2023-03-11
run: |
cd $HOME
mkdir $HOME/gotip

@ -66,26 +66,11 @@ func updateMagicValue(file *ast.File, magicValue uint32) {
// is to make it difficult to determine relations between function metadata and function itself in a binary file.
// Difficulty of decryption is based on the difficulty of finding a small (probably inlined) entry() function without obvious patterns.
func updateEntryOffset(file *ast.File, entryOffKey uint32) {
var nameOffField string
// Note that this field could be renamed in future Go versions.
const nameOffField = "nameOff"
entryOffUpdated := false
// The funcInfo.nameoff field can be renamed between versions and for more stability
// we dynamically extract its name from the cfuncname function.
// Note that extractNameOff must be called before updateEntryOff.
extractNameOff := func(node ast.Node) bool {
indexExpr, ok := node.(*ast.IndexExpr)
if !ok {
return true
}
selExpr, ok := indexExpr.Index.(*ast.SelectorExpr)
if !ok {
return true
}
nameOffField = selExpr.Sel.Name
return false
}
// During linker stage we encrypt funcInfo.entryoff using a random number and funcInfo.nameoff,
// During linker stage we encrypt funcInfo.entryoff using a random number and funcInfo.nameOff,
// for correct program functioning we must decrypt funcInfo.entryoff at any access to it.
// In runtime package all references to funcInfo.entryOff are made through one method entry():
// func (f funcInfo) entry() uintptr {
@ -93,7 +78,7 @@ func updateEntryOffset(file *ast.File, entryOffKey uint32) {
// }
// It is enough to inject decryption into entry() method for program to start working transparently with encrypted value of funcInfo.entryOff:
// func (f funcInfo) entry() uintptr {
// return f.datap.textAddr(f.entryoff ^ (uint32(f.nameoff) * <random int>))
// return f.datap.textAddr(f.entryoff ^ (uint32(f.nameOff) * <random int>))
// }
updateEntryOff := func(node ast.Node) bool {
callExpr, ok := node.(*ast.CallExpr)
@ -131,35 +116,19 @@ func updateEntryOffset(file *ast.File, entryOffKey uint32) {
}
var entryFunc *ast.FuncDecl
var cfuncnameFunc *ast.FuncDecl
for _, decl := range file.Decls {
funcDecl, ok := decl.(*ast.FuncDecl)
decl, ok := decl.(*ast.FuncDecl)
if !ok {
continue
}
switch funcDecl.Name.Name {
case "entry":
entryFunc = funcDecl
case "cfuncname":
cfuncnameFunc = funcDecl
}
if entryFunc != nil && cfuncnameFunc != nil {
if decl.Name.Name == "entry" {
entryFunc = decl
break
}
}
if entryFunc == nil {
panic("entry function not found")
}
if cfuncnameFunc == nil {
panic("cfuncname function not found")
}
ast.Inspect(cfuncnameFunc, extractNameOff)
if nameOffField == "" {
panic("nameOff field not found")
}
ast.Inspect(entryFunc, updateEntryOff)
if !entryOffUpdated {

Loading…
Cancel
Save