avoid patching our reflect code into _cgo_gotypes.go

When obfuscating a main package whose Go files all import "C",
the first Go file in CompiledGoFiles ends up being _cgo_gotypes.go.
We cannot add our code from reflect_abi_code.go there,
as it leads to the following error about its _trieNode type:

    typecheck error: $WORK/b001/_cgo_gotypes.go:185:10: cannot define new methods on non-local type _trieNode

Avoid patching any _cgo_*.go file with our reflect code,
as all of those files are special glue code for cgo.

While here, tweak reflectMainPrePatch to return a string
for consistency with abiNamePatch.

Fixes #916.
pull/942/head
Daniel Martí 2 weeks ago
parent c247675d03
commit 80d666aada
No known key found for this signature in database

@ -922,12 +922,14 @@ func parseFiles(lpkg *listedPackage, dir string, paths []string) (files []*ast.F
var src any
if lpkg.ImportPath == "internal/abi" && filepath.Base(path) == "type.go" {
base := filepath.Base(path)
if lpkg.ImportPath == "internal/abi" && base == "type.go" {
src, err = abiNamePatch(path)
if err != nil {
return nil, err
}
} else if mainPackage && reflectPatchFile == "" {
} else if mainPackage && reflectPatchFile == "" && !strings.HasPrefix(base, "_cgo_") {
// Note that we cannot add our code to e.g. _cgo_gotypes.go.
src, err = reflectMainPrePatch(path)
if err != nil {
return nil, err
@ -941,12 +943,15 @@ func parseFiles(lpkg *listedPackage, dir string, paths []string) (files []*ast.F
return nil, err
}
if mainPackage && src != nil {
if mainPackage && src != "" {
astutil.AddNamedImport(fset, file, "_", "unsafe")
}
files = append(files, file)
}
if mainPackage && reflectPatchFile == "" {
return nil, fmt.Errorf("main packages must get reflect code patched in")
}
return files, nil
}

@ -43,21 +43,21 @@ var reflectPatchFile = ""
// 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) {
func reflectMainPrePatch(path string) (string, error) {
if reflectPatchFile != "" {
// already patched another file in main
return nil, nil
return "", nil
}
content, err := os.ReadFile(path)
if err != nil {
return nil, err
return "", 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
return string(content) + code, nil
}
// reflectMainPostPatch populates the name mapping with the final obfuscated->real name

@ -1,8 +1,6 @@
[!cgo] skip 'this test requires cgo to be enabled'
! exec garble build
stderr 'cannot define new methods on non-local type _trieNode'
stop
exec garble build
! stderr 'warning' # check that the C toolchain is happy
exec ./main
cmp stdout main.stdout

Loading…
Cancel
Save