From 4f743b08618c279a4b01149beb9fb2b0deab9819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Sat, 3 Jun 2023 17:13:33 +0100 Subject: [PATCH] move curPkg and origImporter out of the globals It is true that each garble process only obfuscates up to one package, which is why we made them globals to begin with. However, garble does quite a lot more now, such as reversing the obfuscation of many packages at once. Having a global "current package" variable makes mistakes easier. Some funcs, like those in transformFuncs, are now transformer methods. --- main.go | 196 +++++++++++++++++++++++++++------------------------- position.go | 8 +-- reverse.go | 5 +- shared.go | 12 ++-- 4 files changed, 115 insertions(+), 106 deletions(-) diff --git a/main.go b/main.go index aadd2e2..1c5a9b0 100644 --- a/main.go +++ b/main.go @@ -142,43 +142,40 @@ For more information, see https://github.com/burrowers/garble. func main() { os.Exit(main1()) } var ( - fset = token.NewFileSet() + // Presumably OK to share fset across packages. + fset = token.NewFileSet() + sharedTempDir = os.Getenv("GARBLE_SHARED") parentWorkDir = os.Getenv("GARBLE_PARENT_WORK") - - // origImporter is a go/types importer which uses the original versions - // of packages, without any obfuscation. This is helpful to make - // decisions on how to obfuscate our input code. - origImporter = importerWithMap(importer.ForCompiler(fset, "gc", func(path string) (io.ReadCloser, error) { - pkg, err := listPackage(path) - if err != nil { - return nil, err - } - return os.Open(pkg.Export) - }).(types.ImporterFrom).ImportFrom) - - // Basic information about the package being currently compiled or linked. - curPkg *listedPackage - - // obfRand is initialized by transformCompile and used during obfuscation. - // It is left nil at init time, so that we only use it after it has been - // properly initialized with a deterministic seed. - // It must only be used for deterministic obfuscation; - // if it is used for any other purpose, we may lose determinism. - obfRand *mathrand.Rand ) -type importerWithMap func(path, dir string, mode types.ImportMode) (*types.Package, error) +type importerWithMap struct { + importMap map[string]string + importFrom func(path, dir string, mode types.ImportMode) (*types.Package, error) +} -func (fn importerWithMap) Import(path string) (*types.Package, error) { +func (im importerWithMap) Import(path string) (*types.Package, error) { panic("should never be called") } -func (fn importerWithMap) ImportFrom(path, dir string, mode types.ImportMode) (*types.Package, error) { - if path2 := curPkg.ImportMap[path]; path2 != "" { +func (im importerWithMap) ImportFrom(path, dir string, mode types.ImportMode) (*types.Package, error) { + if path2 := im.importMap[path]; path2 != "" { path = path2 } - return fn(path, dir, mode) + return im.importFrom(path, dir, mode) +} + +func importerForPkg(lpkg *listedPackage) importerWithMap { + return importerWithMap{ + importFrom: importer.ForCompiler(fset, "gc", func(path string) (io.ReadCloser, error) { + pkg, err := listPackage(lpkg, path) + if err != nil { + return nil, err + } + return os.Open(pkg.Export) + }).(types.ImporterFrom).ImportFrom, + importMap: lpkg.ImportMap, + } } // uniqueLineWriter sits underneath log.SetOutput to deduplicate log lines. @@ -423,7 +420,7 @@ func mainErr(args []string) error { if runtime.GOOS == "windows" { tool = strings.TrimSuffix(tool, ".exe") } - transform := transformFuncs[tool] + transform := transformMethods[tool] transformed := args[1:] if transform != nil { startTime := time.Now() @@ -438,15 +435,16 @@ func mainErr(args []string) error { if len(args) == 2 && args[1] == "-V=full" { return alterToolVersion(tool, args) } - + var tf transformer toolexecImportPath := os.Getenv("TOOLEXEC_IMPORTPATH") - curPkg = sharedCache.ListedPackages[toolexecImportPath] - if curPkg == nil { + tf.curPkg = sharedCache.ListedPackages[toolexecImportPath] + if tf.curPkg == nil { return fmt.Errorf("TOOLEXEC_IMPORTPATH not found in listed packages: %s", toolexecImportPath) } + tf.origImporter = importerForPkg(tf.curPkg) var err error - if transformed, err = transform(transformed); err != nil { + if transformed, err = transform(&tf, transformed); err != nil { return err } log.Printf("transformed args for %s in %s: %s", tool, debugSince(startTime), strings.Join(transformed, " ")) @@ -618,18 +616,18 @@ This command wraps "go %s". Below is its help: return exec.Command("go", goArgs...), nil } -var transformFuncs = map[string]func([]string) ([]string, error){ - "asm": transformAsm, - "compile": transformCompile, - "link": transformLink, +var transformMethods = map[string]func(*transformer, []string) ([]string, error){ + "asm": (*transformer).transformAsm, + "compile": (*transformer).transformCompile, + "link": (*transformer).transformLink, } -func transformAsm(args []string) ([]string, error) { +func (tf *transformer) transformAsm(args []string) ([]string, error) { flags, paths := splitFlagsFromFiles(args, ".s") // When assembling, the import path can make its way into the output object file. - if curPkg.Name != "main" && curPkg.ToObfuscate { - flags = flagSetValue(flags, "-p", curPkg.obfuscatedImportPath()) + if tf.curPkg.Name != "main" && tf.curPkg.ToObfuscate { + flags = flagSetValue(flags, "-p", tf.curPkg.obfuscatedImportPath()) } flags = alterTrimpath(flags) @@ -641,8 +639,8 @@ func transformAsm(args []string) ([]string, error) { newPaths := make([]string, 0, len(paths)) if !slices.Contains(args, "-gensymabis") { for _, path := range paths { - name := hashWithPackage(curPkg, filepath.Base(path)) + ".s" - pkgDir := filepath.Join(sharedTempDir, curPkg.obfuscatedImportPath()) + name := hashWithPackage(tf.curPkg, filepath.Base(path)) + ".s" + pkgDir := filepath.Join(sharedTempDir, tf.curPkg.obfuscatedImportPath()) newPath := filepath.Join(pkgDir, name) newPaths = append(newPaths, newPath) } @@ -689,7 +687,7 @@ func transformAsm(args []string) ([]string, error) { } else if err != nil { return nil, err } - replaceAsmNames(&includeBuf, content) + tf.replaceAsmNames(&includeBuf, content) // For now, we replace `foo.h` or `dir/foo.h` with `garbled_foo.h`. // The different name ensures we don't use the unobfuscated file. @@ -698,7 +696,7 @@ func transformAsm(args []string) ([]string, error) { basename := filepath.Base(path) newPath = "garbled_" + basename - if _, err := writeSourceFile(basename, newPath, includeBuf.Bytes()); err != nil { + if _, err := tf.writeSourceFile(basename, newPath, includeBuf.Bytes()); err != nil { return nil, err } newHeaderPaths[path] = newPath @@ -713,7 +711,7 @@ func transformAsm(args []string) ([]string, error) { line, comment, hasComment := strings.Cut(line, "//") // Anything else is regular assembly; replace the names. - replaceAsmNames(&buf, []byte(line)) + tf.replaceAsmNames(&buf, []byte(line)) if hasComment { buf.WriteString("//") @@ -729,8 +727,8 @@ func transformAsm(args []string) ([]string, error) { // directory, as assembly files do not support `/*line` directives. // TODO(mvdan): per cmd/asm/internal/lex, they do support `#line`. basename := filepath.Base(path) - newName := hashWithPackage(curPkg, basename) + ".s" - if path, err := writeSourceFile(basename, newName, buf.Bytes()); err != nil { + newName := hashWithPackage(tf.curPkg, basename) + ".s" + if path, err := tf.writeSourceFile(basename, newName, buf.Bytes()); err != nil { return nil, err } else { newPaths = append(newPaths, path) @@ -741,7 +739,7 @@ func transformAsm(args []string) ([]string, error) { return append(flags, newPaths...), nil } -func replaceAsmNames(buf *bytes.Buffer, remaining []byte) { +func (tf *transformer) replaceAsmNames(buf *bytes.Buffer, remaining []byte) { // We need to replace all function references with their obfuscated name // counterparts. // Luckily, all func names in Go assembly files are immediately followed @@ -806,14 +804,14 @@ func replaceAsmNames(buf *bytes.Buffer, remaining []byte) { // If the name was qualified, fetch the package, and write the // obfuscated import path if needed. // Note that we don't obfuscate the package path "main". - lpkg := curPkg + lpkg := tf.curPkg if asmPkgPath != "" && asmPkgPath != "main" { - if asmPkgPath != curPkg.Name { + if asmPkgPath != tf.curPkg.Name { goPkgPath := asmPkgPath goPkgPath = strings.ReplaceAll(goPkgPath, string(asmPeriod), string(goPeriod)) goPkgPath = strings.ReplaceAll(goPkgPath, string(asmSlash), string(goSlash)) var err error - lpkg, err = listPackage(goPkgPath) + lpkg, err = listPackage(tf.curPkg, goPkgPath) if err != nil { panic(err) // shouldn't happen } @@ -847,7 +845,7 @@ func replaceAsmNames(buf *bytes.Buffer, remaining []byte) { if lpkg.ToObfuscate && !compilerIntrinsicsFuncs[lpkg.ImportPath+"."+name] { newName := hashWithPackage(lpkg, name) if flagDebug { // TODO(mvdan): remove once https://go.dev/issue/53465 if fixed - log.Printf("asm name %q hashed with %x to %q", name, curPkg.GarbleActionID, newName) + log.Printf("asm name %q hashed with %x to %q", name, tf.curPkg.GarbleActionID, newName) } buf.WriteString(newName) } else { @@ -861,12 +859,12 @@ func replaceAsmNames(buf *bytes.Buffer, remaining []byte) { // // Note that the file is created under a directory tree following curPkg's // import path, mimicking how files are laid out in modules and GOROOT. -func writeSourceFile(basename, obfuscated string, content []byte) (string, error) { +func (tf *transformer) writeSourceFile(basename, obfuscated string, content []byte) (string, error) { // Uncomment for some quick debugging. Do not delete. // fmt.Fprintf(os.Stderr, "\n-- %s/%s --\n%s", curPkg.ImportPath, basename, content) if flagDebugDir != "" { - pkgDir := filepath.Join(flagDebugDir, filepath.FromSlash(curPkg.ImportPath)) + pkgDir := filepath.Join(flagDebugDir, filepath.FromSlash(tf.curPkg.ImportPath)) if err := os.MkdirAll(pkgDir, 0o755); err != nil { return "", err } @@ -878,7 +876,7 @@ func writeSourceFile(basename, obfuscated string, content []byte) (string, error // We use the obfuscated import path to hold the temporary files. // Assembly files do not support line directives to set positions, // so the only way to not leak the import path is to replace it. - pkgDir := filepath.Join(sharedTempDir, curPkg.obfuscatedImportPath()) + pkgDir := filepath.Join(sharedTempDir, tf.curPkg.obfuscatedImportPath()) if err := os.MkdirAll(pkgDir, 0o777); err != nil { return "", err } @@ -889,7 +887,7 @@ func writeSourceFile(basename, obfuscated string, content []byte) (string, error return dstPath, nil } -func transformCompile(args []string) ([]string, error) { +func (tf *transformer) transformCompile(args []string) ([]string, error) { var err error flags, paths := splitFlagsFromFiles(args, ".go") @@ -905,18 +903,17 @@ func transformCompile(args []string) ([]string, error) { } files = append(files, file) } - tf := &transformer{} // Even if loadPkgCache below finds a direct cache hit, // other parts of garble still need type information to obfuscate. // We could potentially avoid this by saving the type info we need in the cache, // although in general that wouldn't help much, since it's rare for Go's cache // to miss on a package and for our cache to hit. - if tf.pkg, tf.info, err = typecheck(files); err != nil { + if tf.pkg, tf.info, err = typecheck(tf.curPkg.ImportPath, files, tf.origImporter); err != nil { return nil, err } - if err := loadPkgCache(tf.pkg, files, tf.info); err != nil { + if err := loadPkgCache(tf.curPkg, tf.pkg, files, tf.info); err != nil { return nil, err } @@ -929,26 +926,26 @@ func transformCompile(args []string) ([]string, error) { } flags = alterTrimpath(flags) - newImportCfg, err := processImportCfg(flags) + newImportCfg, err := tf.processImportCfg(flags) if err != nil { return nil, err } // Literal obfuscation uses math/rand, so seed it deterministically. - randSeed := curPkg.GarbleActionID[:] + randSeed := tf.curPkg.GarbleActionID[:] if flagSeed.present() { randSeed = flagSeed.bytes } // log.Printf("seeding math/rand with %x\n", randSeed) - obfRand = mathrand.New(mathrand.NewSource(int64(binary.BigEndian.Uint64(randSeed)))) + tf.obfRand = mathrand.New(mathrand.NewSource(int64(binary.BigEndian.Uint64(randSeed)))) // If this is a package to obfuscate, swap the -p flag with the new package path. // We don't if it's the main package, as that just uses "-p main". // We only set newPkgPath if we're obfuscating the import path, // to replace the original package name in the package clause below. newPkgPath := "" - if curPkg.Name != "main" && curPkg.ToObfuscate { - newPkgPath = curPkg.obfuscatedImportPath() + if tf.curPkg.Name != "main" && tf.curPkg.ToObfuscate { + newPkgPath = tf.curPkg.obfuscatedImportPath() flags = flagSetValue(flags, "-p", newPkgPath) } @@ -957,7 +954,7 @@ func transformCompile(args []string) ([]string, error) { for i, file := range files { basename := filepath.Base(paths[i]) log.Printf("obfuscating %s", basename) - if curPkg.ImportPath == "runtime" { + if tf.curPkg.ImportPath == "runtime" { if flagTiny { // strip unneeded runtime code stripRuntime(basename, file) @@ -974,11 +971,11 @@ func transformCompile(args []string) ([]string, error) { // compilerIntrinsics; we don't want to use slashes in package names. // TODO: when we do away with those edge cases, only check the string is // non-empty. - if newPkgPath != "" && newPkgPath != curPkg.ImportPath { + if newPkgPath != "" && newPkgPath != tf.curPkg.ImportPath { file.Name.Name = newPkgPath } - src, err := printFile(file) + src, err := printFile(tf.curPkg, file) if err != nil { return nil, err } @@ -1000,13 +997,13 @@ func transformCompile(args []string) ([]string, error) { // TODO: can we remove this now with the better caching? if i == 0 { src = append(src, fmt.Sprintf( - "\nvar garbleActionID = %q\n", encodeBuildIDHash(curPkg.GarbleActionID), + "\nvar garbleActionID = %q\n", encodeBuildIDHash(tf.curPkg.GarbleActionID), )...) } // We hide Go source filenames via "//line" directives, // so there is no need to use obfuscated filenames here. - if path, err := writeSourceFile(basename, basename, src); err != nil { + if path, err := tf.writeSourceFile(basename, basename, src); err != nil { return nil, err } else { newPaths = append(newPaths, path) @@ -1058,8 +1055,8 @@ func (tf *transformer) transformDirectives(comments []*ast.CommentGroup) { func (tf *transformer) transformLinkname(localName, newName string) (string, string) { // obfuscate the local name, if the current package is obfuscated - if curPkg.ToObfuscate && !compilerIntrinsicsFuncs[curPkg.ImportPath+"."+localName] { - localName = hashWithPackage(curPkg, localName) + if tf.curPkg.ToObfuscate && !compilerIntrinsicsFuncs[tf.curPkg.ImportPath+"."+localName] { + localName = hashWithPackage(tf.curPkg, localName) } if newName == "" { return localName, "" @@ -1095,7 +1092,7 @@ func (tf *transformer) transformLinkname(localName, newName string) (string, str pkgSplit++ // skip over the dot var err error - lpkg, err = listPackage(pkgPath) + lpkg, err = listPackage(tf.curPkg, pkgPath) if err == nil { foreignName = newName[pkgSplit:] break @@ -1155,7 +1152,7 @@ func (tf *transformer) transformLinkname(localName, newName string) (string, str // processImportCfg parses the importcfg file passed to a compile or link step. // It also builds a new importcfg file to account for obfuscated import paths. -func processImportCfg(flags []string) (newImportCfg string, _ error) { +func (tf *transformer) processImportCfg(flags []string) (newImportCfg string, _ error) { importCfg := flagValue(flags, "-importcfg") if importCfg == "" { return "", fmt.Errorf("could not find -importcfg argument") @@ -1201,7 +1198,7 @@ func processImportCfg(flags []string) (newImportCfg string, _ error) { } for _, pair := range importmaps { beforePath, afterPath := pair[0], pair[1] - lpkg, err := listPackage(beforePath) + lpkg, err := listPackage(tf.curPkg, beforePath) if err != nil { panic(err) // shouldn't happen } @@ -1218,7 +1215,7 @@ func processImportCfg(flags []string) (newImportCfg string, _ error) { } for _, pair := range packagefiles { impPath, pkgfile := pair[0], pair[1] - lpkg, err := listPackage(impPath) + lpkg, err := listPackage(tf.curPkg, impPath) if err != nil { // TODO: it's unclear why an importcfg can include an import path // that's not a dependency in an edge case with "go test ./...". @@ -1226,7 +1223,7 @@ func processImportCfg(flags []string) (newImportCfg string, _ error) { // For now, spot the pattern and avoid the unnecessary error; // the dependency is unused, so the packagefile line is redundant. // This still triggers as of go1.20. - if strings.HasSuffix(curPkg.ImportPath, ".test]") && strings.HasPrefix(curPkg.ImportPath, impPath) { + if strings.HasSuffix(tf.curPkg.ImportPath, ".test]") && strings.HasPrefix(tf.curPkg.ImportPath, impPath) { continue } panic(err) // shouldn't happen @@ -1256,8 +1253,6 @@ type ( } ) -// TODO: read-write globals like these should probably be inside transformer - // pkgCache contains information that will be stored in fsCache. // Note that pkgCache gets loaded from all direct package dependencies, // and gets filled while obfuscating the current package, so it ends up @@ -1316,12 +1311,12 @@ func openCache() (*cache.Cache, error) { return cache.Open(dir) } -func loadPkgCache(pkg *types.Package, files []*ast.File, info *types.Info) error { +func loadPkgCache(lpkg *listedPackage, pkg *types.Package, files []*ast.File, info *types.Info) error { fsCache, err := openCache() if err != nil { return err } - filename, _, err := fsCache.GetFile(curPkg.GarbleActionID) + filename, _, err := fsCache.GetFile(lpkg.GarbleActionID) // Already in the cache; load it directly. if err == nil { f, err := os.Open(filename) @@ -1345,12 +1340,12 @@ func loadPkgCache(pkg *types.Package, files []*ast.File, info *types.Info) error // loading B's gob file would be enough. Is there an easy way to do that? startTime := time.Now() loaded := 0 - for _, path := range curPkg.Imports { + for _, path := range lpkg.Imports { if path == "C" { // `go list -json` shows "C" in Imports but not Deps. A bug? continue } - pkg, err := listPackage(path) + pkg, err := listPackage(lpkg, path) if err != nil { panic(err) // shouldn't happen } @@ -1432,7 +1427,7 @@ func loadPkgCache(pkg *types.Package, files []*ast.File, info *types.Info) error if err := gob.NewEncoder(&buf).Encode(curPkgCache); err != nil { return err } - if err := fsCache.PutBytes(curPkg.GarbleActionID, buf.Bytes()); err != nil { + if err := fsCache.PutBytes(lpkg.GarbleActionID, buf.Bytes()); err != nil { return err } return nil @@ -1479,7 +1474,7 @@ func computeLinkerVariableStrings(pkg *types.Package, files []*ast.File) (map[*t path, name := fullName[:i], fullName[i+1:] // -X represents the main package as "main", not its import path. - if path != curPkg.ImportPath && (path != "main" || curPkg.Name != "main") { + if path != pkg.Path() && (path != "main" || pkg.Name() != "main") { return // not the current package } @@ -1495,6 +1490,9 @@ func computeLinkerVariableStrings(pkg *types.Package, files []*ast.File) (map[*t // transformer holds all the information and state necessary to obfuscate a // single Go package. type transformer struct { + // curPkg holds basic information about the package being currently compiled or linked. + curPkg *listedPackage + // The type-checking results; the package itself, and the Info struct. pkg *types.Package info *types.Info @@ -1507,9 +1505,21 @@ type transformer struct { // fieldToStruct helps locate struct types from any of their field // objects. Useful when obfuscating field names. fieldToStruct map[*types.Var]*types.Struct + + // obfRand is initialized by transformCompile and used during obfuscation. + // It is left nil at init time, so that we only use it after it has been + // properly initialized with a deterministic seed. + // It must only be used for deterministic obfuscation; + // if it is used for any other purpose, we may lose determinism. + obfRand *mathrand.Rand + + // origImporter is a go/types importer which uses the original versions + // of packages, without any obfuscation. This is helpful to make + // decisions on how to obfuscate our input code. + origImporter importerWithMap } -func typecheck(files []*ast.File) (*types.Package, *types.Info, error) { +func typecheck(pkgPath string, files []*ast.File, origImporter importerWithMap) (*types.Package, *types.Info, error) { info := &types.Info{ Types: make(map[ast.Expr]types.TypeAndValue), Defs: make(map[*ast.Ident]types.Object), @@ -1520,7 +1530,7 @@ func typecheck(files []*ast.File) (*types.Package, *types.Info, error) { Instances: make(map[*ast.Ident]types.Instance), } origTypesConfig := types.Config{Importer: origImporter} - pkg, err := origTypesConfig.Check(curPkg.ImportPath, fset, files, info) + pkg, err := origTypesConfig.Check(pkgPath, fset, files, info) if err != nil { return nil, nil, fmt.Errorf("typecheck error: %v", err) } @@ -1687,8 +1697,8 @@ func (tf *transformer) transformGoFile(file *ast.File) *ast.File { // We can't obfuscate literals in the runtime and its dependencies, // because obfuscated literals sometimes escape to heap, // and that's not allowed in the runtime itself. - if flagLiterals && curPkg.ToObfuscate { - file = literals.Obfuscate(obfRand, file, tf.info, tf.linkerVariableStrings) + if flagLiterals && tf.curPkg.ToObfuscate { + file = literals.Obfuscate(tf.obfRand, file, tf.info, tf.linkerVariableStrings) // some imported constants might not be needed anymore, remove unnecessary imports tf.useAllImports(file) @@ -1748,7 +1758,7 @@ func (tf *transformer) transformGoFile(file *ast.File) *ast.File { // because some of the packages under there are incomplete. // ImportFrom will cache complete imports, anyway. var err error - pkg2, err = origImporter.ImportFrom(path, parentWorkDir, 0) + pkg2, err = tf.origImporter.ImportFrom(path, parentWorkDir, 0) if err != nil { panic(err) } @@ -1812,7 +1822,7 @@ func (tf *transformer) transformGoFile(file *ast.File) *ast.File { return true } - lpkg, err := listPackage(path) + lpkg, err := listPackage(tf.curPkg, path) if err != nil { panic(err) // shouldn't happen } @@ -1901,7 +1911,7 @@ func (tf *transformer) transformGoFile(file *ast.File) *ast.File { // Replace the import path with its obfuscated version. // If the import was unnamed, give it the name of the // original package name, to keep references working. - lpkg, err := listPackage(path) + lpkg, err := listPackage(tf.curPkg, path) if err != nil { panic(err) // should never happen } @@ -1955,12 +1965,12 @@ func isTestSignature(sign *types.Signature) bool { return obj != nil && obj.Pkg().Path() == "testing" && obj.Name() == "T" } -func transformLink(args []string) ([]string, error) { +func (tf *transformer) transformLink(args []string) ([]string, error) { // We can't split by the ".a" extension, because cached object files // lack any extension. flags, args := splitFlagsFromArgs(args) - newImportCfg, err := processImportCfg(flags) + newImportCfg, err := tf.processImportCfg(flags) if err != nil { return nil, err } @@ -1985,7 +1995,7 @@ func transformLink(args []string) ([]string, error) { // If the package path is "main", it's the current top-level // package we are linking. // Otherwise, find it in the cache. - lpkg := curPkg + lpkg := tf.curPkg if path != "main" { lpkg = sharedCache.ListedPackages[path] } diff --git a/position.go b/position.go index 097b3a9..beadd01 100644 --- a/position.go +++ b/position.go @@ -18,8 +18,8 @@ var printBuf1, printBuf2 bytes.Buffer // printFile prints a Go file to a buffer, while also removing non-directive // comments and adding extra compiler directives to obfuscate position information. -func printFile(file *ast.File) ([]byte, error) { - if curPkg.ToObfuscate { +func printFile(lpkg *listedPackage, file *ast.File) ([]byte, error) { + if lpkg.ToObfuscate { // Omit comments from the final Go code. // Keep directives, as they affect the build. // We do this before printing to print fewer bytes below. @@ -45,7 +45,7 @@ func printFile(file *ast.File) ([]byte, error) { } src := printBuf1.Bytes() - if !curPkg.ToObfuscate { + if !lpkg.ToObfuscate { // We lightly transform packages which shouldn't be obfuscated, // such as when rewriting go:linkname directives to obfuscated packages. // We still need to print the files, but without obfuscating positions. @@ -127,7 +127,7 @@ func printFile(file *ast.File) ([]byte, error) { newName := "" if !flagTiny { origPos := fmt.Sprintf("%s:%d", filename, origOffset) - newName = hashWithPackage(curPkg, origPos) + ".go" + newName = hashWithPackage(lpkg, origPos) + ".go" // log.Printf("%q hashed with %x to %q", origPos, curPkg.GarbleActionID, newName) } diff --git a/reverse.go b/reverse.go index d2ef874..32d9de7 100644 --- a/reverse.go +++ b/reverse.go @@ -70,8 +70,6 @@ One can reverse a captured panic stack trace as follows: if !lpkg.ToObfuscate { continue } - curPkg = lpkg - addHashedWithPackage := func(str string) { replaces = append(replaces, hashWithPackage(lpkg, str), str) } @@ -93,7 +91,8 @@ One can reverse a captured panic stack trace as follows: } files = append(files, file) } - _, info, err := typecheck(files) + origImporter := importerForPkg(lpkg) + _, info, err := typecheck(lpkg.ImportPath, files, origImporter) if err != nil { return err } diff --git a/shared.go b/shared.go index 479f3fa..b246490 100644 --- a/shared.go +++ b/shared.go @@ -383,15 +383,15 @@ var ErrNotFound = errors.New("not found") var ErrNotDependency = errors.New("not a dependency") // listPackage gets the listedPackage information for a certain package -func listPackage(path string) (*listedPackage, error) { - if path == curPkg.ImportPath { - return curPkg, nil +func listPackage(from *listedPackage, path string) (*listedPackage, error) { + if path == from.ImportPath { + return from, nil } // If the path is listed in the top-level ImportMap, use its mapping instead. // This is a common scenario when dealing with vendored packages in GOROOT. // The map is flat, so we don't need to recurse. - if path2 := curPkg.ImportMap[path]; path2 != "" { + if path2 := from.ImportMap[path]; path2 != "" { path = path2 } @@ -405,7 +405,7 @@ func listPackage(path string) (*listedPackage, error) { // // If ListedPackages lacks such a package we fill it via runtimeLinknamed. // TODO: can we instead add runtimeLinknamed to the top-level "go list" args? - if curPkg.Standard { + if from.Standard { if ok { return pkg, nil } @@ -444,7 +444,7 @@ func listPackage(path string) (*listedPackage, error) { // Packages outside std can list any package, // as long as they depend on it directly or indirectly. - for _, dep := range curPkg.Deps { + for _, dep := range from.Deps { if dep == pkg.ImportPath { return pkg, nil }