From 8c03afee953d7e63315c79bc39ba042bbf25bee9 Mon Sep 17 00:00:00 2001 From: Andrew LeFevre Date: Sun, 8 Nov 2020 16:52:42 -0500 Subject: [PATCH] Use latest Binject/debug version to support importmap directives, fixes #146 (#189) * Use latest Binject/debug version to support importmap directives in the importcfg file * Uncomment line in goprivate testscript to test ImportMap * Fixed issue where a package in specified in importmap would be hashed differently in a package that imported it, due to the mapping of import paths. Also commented out the 'net' import in the goprivate testscript (again) due to cgo compile errors --- go.mod | 2 +- go.sum | 6 +-- import_obfuscation.go | 34 +++++++++++------ main.go | 68 +++++++++++++++++++++------------- testdata/scripts/goprivate.txt | 4 +- 5 files changed, 71 insertions(+), 43 deletions(-) diff --git a/go.mod b/go.mod index 7b596c17..605e48fb 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module mvdan.cc/garble go 1.15 require ( - github.com/Binject/debug v0.0.0-20201021202824-cc437dcdb16e + github.com/Binject/debug v0.0.0-20201108185608-2b8504217eb5 github.com/google/go-cmp v0.5.2 github.com/rogpeppe/go-internal v1.6.3-0.20201011174404-9f985d550aa7 golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 diff --git a/go.sum b/go.sum index 7be540bf..8ab6e187 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ -github.com/Binject/debug v0.0.0-20200928131656-23d735563ce7 h1:W9kchICcGYOJQBZNn2P6j739QbY8OKskB3SyFZ/IRIU= -github.com/Binject/debug v0.0.0-20200928131656-23d735563ce7/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ= -github.com/Binject/debug v0.0.0-20201021202824-cc437dcdb16e h1:IQMhZQS5d9OUmcXgv330n31ZnD97HAZE36K7JgIjvog= -github.com/Binject/debug v0.0.0-20201021202824-cc437dcdb16e/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ= +github.com/Binject/debug v0.0.0-20201108185608-2b8504217eb5 h1:P+1sYxfDpfit02rkbNs4QcyF4qlopQwrJ/JNGr3sGZo= +github.com/Binject/debug v0.0.0-20201108185608-2b8504217eb5/go.mod h1:QzgxDLY/qdKlvnbnb65eqTedhvQPbaSP2NqIbcuKvsQ= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= diff --git a/import_obfuscation.go b/import_obfuscation.go index af7c79fc..5c60a29c 100644 --- a/import_obfuscation.go +++ b/import_obfuscation.go @@ -153,12 +153,12 @@ func extractDebugObfSrc(pkgPath string, pkg *goobj2.Package) error { // It returns the path to the modified main object file, to be used for linking. // We also return a map of how the imports were garbled, as well as the private // name map recovered from the archive files, so that we can amend -X flags. -func obfuscateImports(objPath, tempDir, importCfgPath string) (garbledObj string, garbledImports, privateNameMap map[string]string, _ error) { +func obfuscateImports(objPath, tempDir, importCfgPath string, importMap goobj2.ImportMap) (garbledObj string, garbledImports, privateNameMap map[string]string, _ error) { importCfg, err := goobj2.ParseImportCfg(importCfgPath) if err != nil { return "", nil, nil, err } - mainPkg, err := goobj2.Parse(objPath, "main", importCfg) + mainPkg, err := goobj2.Parse(objPath, "main", importMap) if err != nil { return "", nil, nil, fmt.Errorf("error parsing main objfile: %v", err) } @@ -169,11 +169,11 @@ func obfuscateImports(objPath, tempDir, importCfgPath string) (garbledObj string privateNameMap = make(map[string]string) // build list of imported packages that are private - for pkgPath, info := range importCfg { + for pkgPath, info := range importCfg.Packages { // if the '-tiny' flag is passed, we will strip filename // and position info of every package, but not garble anything if private := isPrivate(pkgPath); envGarbleTiny || private { - pkg, err := goobj2.Parse(info.Path, pkgPath, importCfg) + pkg, err := goobj2.Parse(info.Path, pkgPath, importMap) if err != nil { return "", nil, nil, fmt.Errorf("error parsing objfile %s at %s: %v", pkgPath, info.Path, err) } @@ -447,7 +447,6 @@ func hashImport(pkg string, seed []byte, garbledImports map[string]string) strin } garbledPkg := hashWith(seed, pkg) - // log.Printf("\t\t! Hashed %q as %s with seed %q", pkg, garbledPkg, seed) garbledImports[pkg] = garbledPkg return garbledPkg @@ -812,25 +811,38 @@ func garbleImportCfg(path string, importCfg goobj2.ImportCfg, garbledImports, re defer newCfg.Close() newCfgWr := bufio.NewWriter(newCfg) - for pkgPath, info := range importCfg { + for pkgPath, otherPath := range importCfg.ImportMap { + if isPrivate(pkgPath) { + pkgPath = hashImport(pkgPath, nil, garbledImports) + } + if isPrivate(otherPath) { + otherPath = hashImport(otherPath, nil, garbledImports) + } + newCfgWr.WriteString("importmap ") + newCfgWr.WriteString(pkgPath) + newCfgWr.WriteByte('=') + newCfgWr.WriteString(otherPath) + newCfgWr.WriteByte('\n') + } + + for pkgPath, info := range importCfg.Packages { if isPrivate(pkgPath) { pkgPath = hashImport(pkgPath, nil, garbledImports) } if info.IsSharedLib { - newCfgWr.WriteString("packageshlib") + newCfgWr.WriteString("packageshlib ") } else { - newCfgWr.WriteString("packagefile") + newCfgWr.WriteString("packagefile ") } - newCfgWr.WriteRune(' ') newCfgWr.WriteString(pkgPath) - newCfgWr.WriteRune('=') + newCfgWr.WriteByte('=') if replaced := replacedFiles[info.Path]; replaced != "" { newCfgWr.WriteString(replaced) } else { newCfgWr.WriteString(info.Path) } - newCfgWr.WriteRune('\n') + newCfgWr.WriteByte('\n') } if err := newCfgWr.Flush(); err != nil { diff --git a/main.go b/main.go index 596f34c1..a19b770b 100644 --- a/main.go +++ b/main.go @@ -776,12 +776,11 @@ func transformCompile(args []string) ([]string, error) { objPath := flagValue(flags, "-o") deferred = append(deferred, func() error { - importCfg, err := goobj2.ParseImportCfg(buildInfo.importCfg) - if err != nil { - return err + importMap := func(importPath string) (objectPath string) { + return buildInfo.imports[importPath].packagefile } - pkg, err := goobj2.Parse(objPath, pkgPath, importCfg) + pkg, err := goobj2.Parse(objPath, pkgPath, importMap) if err != nil { return err } @@ -851,6 +850,8 @@ func fillBuildInfo(flags []string) error { if err != nil { return err } + + importMap := make(map[string]string) for _, line := range strings.Split(string(data), "\n") { line = strings.TrimSpace(line) if line == "" || strings.HasPrefix(line, "#") { @@ -860,27 +861,41 @@ func fillBuildInfo(flags []string) error { if i < 0 { continue } - if verb := line[:i]; verb != "packagefile" { - continue - } - args := strings.TrimSpace(line[i+1:]) - j := strings.Index(args, "=") - if j < 0 { - continue - } - importPath, objectPath := args[:j], args[j+1:] - buildID, err := buildidOf(objectPath) - if err != nil { - return err - } - // log.Println("buildid:", buildID) + verb := line[:i] + switch verb { + case "importmap": + args := strings.TrimSpace(line[i+1:]) + j := strings.Index(args, "=") + if j < 0 { + continue + } + beforePath, afterPath := args[:j], args[j+1:] + importMap[afterPath] = beforePath + case "packagefile": + args := strings.TrimSpace(line[i+1:]) + j := strings.Index(args, "=") + if j < 0 { + continue + } + importPath, objectPath := args[:j], args[j+1:] + buildID, err := buildidOf(objectPath) + if err != nil { + return err + } + // log.Println("buildid:", buildID) - if len(buildInfo.imports) == 0 { - buildInfo.firstImport = importPath - } - buildInfo.imports[importPath] = importedPkg{ - packagefile: objectPath, - actionID: decodeHash(actionID(buildID)), + if len(buildInfo.imports) == 0 { + buildInfo.firstImport = importPath + } + impPkg := importedPkg{ + packagefile: objectPath, + actionID: decodeHash(actionID(buildID)), + } + buildInfo.imports[importPath] = impPkg + + if otherPath, ok := importMap[importPath]; ok { + buildInfo.imports[otherPath] = impPkg + } } } // log.Printf("%#v", buildInfo) @@ -1305,7 +1320,10 @@ func transformLink(args []string) ([]string, error) { if len(paths) != 1 { return nil, fmt.Errorf("expected exactly one link argument") } - garbledObj, garbledImports, privateNameMap, err := obfuscateImports(paths[0], tempDir, buildInfo.importCfg) + importMap := func(importPath string) (objectPath string) { + return buildInfo.imports[importPath].packagefile + } + garbledObj, garbledImports, privateNameMap, err := obfuscateImports(paths[0], tempDir, buildInfo.importCfg, importMap) if err != nil { return nil, err } diff --git a/testdata/scripts/goprivate.txt b/testdata/scripts/goprivate.txt index 4b79e1af..6e92a78e 100644 --- a/testdata/scripts/goprivate.txt +++ b/testdata/scripts/goprivate.txt @@ -21,8 +21,8 @@ go 1.15 -- standalone/main.go -- package main -// Blocked until https://github.com/Binject/debug/issues/17 is fixed. -// import _ "net" +// TODO: This tests that #146 is fixed, but is blocked by errors garbling 'net' +//import _ "net" func main() {} -- importer/importer.go --