-
-
Notifications
You must be signed in to change notification settings - Fork 267
/
reflect_abi_patch.go
79 lines (64 loc) · 2.36 KB
/
reflect_abi_patch.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package main
import (
"bytes"
_ "embed"
"fmt"
"maps"
"os"
"slices"
"strconv"
"strings"
)
func abiNamePatch(path string) (string, error) {
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
find := `return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)`
replace := `return _originalNames(unsafe.String(n.DataChecked(1+i, "non-empty string"), l))`
str := strings.Replace(string(data), find, replace, 1)
originalNames := `
//go:linkname _originalNames
func _originalNames(name string) string
//go:linkname _originalNamesInit
func _originalNamesInit()
func init() { _originalNamesInit() }
`
return str + originalNames, nil
}
var reflectPatchFile = ""
// reflectMainPrePatch adds the initial empty name mapping and _originalNames implementation
// to a file in the main package. The name mapping will be populated later after
// analyzing the main package, since we need to know all obfuscated names that need mapping.
// We split this into pre/post steps so that all variable names in the generated code
// can be properly obfuscated - if we added the filled map directly, the obfuscated names
// would appear as plain strings in the binary.
func reflectMainPrePatch(path string) ([]byte, error) {
if reflectPatchFile != "" {
// already patched another file in main
return nil, nil
}
content, err := os.ReadFile(path)
if err != nil {
return nil, err
}
_, code, _ := strings.Cut(reflectAbiCode, "// Injected code below this line.")
code = strings.ReplaceAll(code, "//disabledgo:", "//go:")
// This constant is declared in our hash.go file.
code = strings.ReplaceAll(code, "minHashLength", strconv.Itoa(minHashLength))
return append(content, []byte(code)...), nil
}
// reflectMainPostPatch populates the name mapping with the final obfuscated->real name
// mappings after all packages have been analyzed.
func reflectMainPostPatch(file []byte, lpkg *listedPackage, pkg pkgCache) []byte {
obfVarName := hashWithPackage(lpkg, "_originalNamePairs")
namePairs := fmt.Appendf(nil, "%s = []string{", obfVarName)
keys := slices.Sorted(maps.Keys(pkg.ReflectObjectNames))
namePairsFilled := bytes.Clone(namePairs)
for _, obf := range keys {
namePairsFilled = fmt.Appendf(namePairsFilled, "%q, %q,", obf, pkg.ReflectObjectNames[obf])
}
return bytes.Replace(file, namePairs, namePairsFilled, 1)
}
//go:embed reflect_abi_code.go
var reflectAbiCode string