diff --git a/main.go b/main.go index 191ddee..1c5673f 100644 --- a/main.go +++ b/main.go @@ -1741,12 +1741,19 @@ func (tf *transformer) transformGo(file *ast.File) *ast.File { return true // universe scope } - if pkg.Path() == "embed" { - // The Go compiler needs to detect types such as embed.FS. - // That will fail if we change the import path or type name. - // Leave it as is. - // Luckily, the embed package just declares the FS type. - return true + // The Go toolchain needs to detect symbols from these packages, + // so we are not obfuscating their package paths or declared names. + switch pkg.Path() { + case "embed": + // FS is detected by the compiler for //go:embed. + return name == "FS" + case "reflect": + // Per the linker's deadcode.go docs, + // the Method and MethodByName methods are what drive the logic. + switch name { + case "Method", "MethodByName": + return true + } } // The package that declared this object did not obfuscate it. diff --git a/shared.go b/shared.go index 3d2ab2a..bd07e4c 100644 --- a/shared.go +++ b/shared.go @@ -158,9 +158,17 @@ type listedPackage struct { } func (p *listedPackage) obfuscatedImportPath() string { - // We can't obfuscate the embed package's import path, - // as the toolchain expects to recognize the package by it. - if p.ImportPath == "embed" || !p.ToObfuscate { + // We can't obfuscate these standard library import paths, + // as the toolchain expects to recognize the packages by them: + // + // * runtime: it is special in many ways + // * reflect: its presence turns down dead code elimination + // * embed: its presence enables using //go:embed + switch p.ImportPath { + case "runtime", "reflect", "embed": + return p.ImportPath + } + if !p.ToObfuscate { return p.ImportPath } newPath := hashWithPackage(p, p.ImportPath) diff --git a/testdata/script/reflect.txtar b/testdata/script/reflect.txtar index 1ebb71e..194b4c6 100644 --- a/testdata/script/reflect.txtar +++ b/testdata/script/reflect.txtar @@ -41,13 +41,9 @@ func main() { printfWithoutPackage("%T\n", importedpkg.ReflectTypeOf(2)) printfWithoutPackage("%T\n", importedpkg.ReflectTypeOfIndirect(4)) - // More complex use of reflect. v := importedpkg.ReflectValueOfVar printfWithoutPackage("%#v\n", v) - // Keep the method from being unreachable, otherwise Call below may panic. - // TODO(mvdan): This only started being necessary with GOGARBLE=*. Why? - Sink = v.ExportedMethodName method := reflect.ValueOf(&v).MethodByName("ExportedMethodName") if method.IsValid() { fmt.Println(method.Call(nil))