replace the -p path when assembling (#247)

The asm tool runs twice for a package with assembly. The second time it
does, the path given to the -p flag matters, just like in the compiler,
as we generate an object file.

We don't have a -buildid flag in the asm tool, so obtaining the action
ID to obfuscate the package path with is a bit tricky. We store it from
transformCompile, and read it from transformAsm. See the detailed docs
for more.

This was the last "skip" line in the tests due to Go 1.16. After all PRs
are merged, one last PR documenting that 1.16 is supported will be sent,
closing the issue for good.

It's unclear why this wasn't an issue in Go 1.15. My best guess is that
the ABI changes only happened in Go 1.16, and this causes exported asm
funcs to start showing up in object files with their package paths.

Updates #124.
pull/249/head
Daniel Martí 3 years ago committed by GitHub
parent a223147093
commit 2ee6604408
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -388,10 +388,46 @@ func toolexecCmd(command string, args []string) (*exec.Cmd, error) {
}
var transformFuncs = map[string]func([]string) (args []string, _ error){
"asm": transformAsm,
"compile": transformCompile,
"link": transformLink,
}
func transformAsm(args []string) ([]string, error) {
flags, paths := splitFlagsFromFiles(args, ".s")
symAbis := false
// Note that flagValue only supports "-foo=true" bool flags, but the std
// flag is generally just "-std".
// TODO: Better support boolean flags for the tools.
for _, flag := range flags {
if flag == "-gensymabis" {
symAbis = true
}
}
curPkgPath = flagValue(flags, "-p")
// If we are generating symbol ABIs, the output does not actually
// contain curPkgPath. Exported APIs show up as "".FooBar.
// Otherwise, we are assembling, and curPkgPath does make its way into
// the output object file.
// To obfuscate the path in the -p flag, we need the current action ID,
// which we recover from the file that transformCompile wrote for us.
if !symAbis && curPkgPath != "main" && isPrivate(curPkgPath) {
savedActionID := filepath.Join(sharedTempDir, strings.ReplaceAll(curPkgPath, "/", ","))
var err error
curActionID, err = ioutil.ReadFile(savedActionID)
if err != nil {
return nil, fmt.Errorf("could not read build ID: %v", err)
}
newPkgPath := hashWith(curActionID, curPkgPath)
flags = flagSetValue(flags, "-p", newPkgPath)
}
return append(flags, paths...), nil
}
func transformCompile(args []string) ([]string, error) {
var err error
flags, paths := splitFlagsFromFiles(args, ".go")
@ -433,6 +469,22 @@ func transformCompile(args []string) ([]string, error) {
return nil, err
}
// Tools which run after the main compile run, such as asm, also need
// the current action ID to obfuscate the package path in their -p flag.
// They lack the -buildid flag, so store it in a unique file here to be
// recovered by the other tools later, such as transformAsm.
// Import paths include slashes, which usually cannot be in filenames,
// so replace those with commas, which should be fine and cannot be part
// of an import path.
// We only write each file once, as we compile each package once.
// Each filename is also unique, since import paths are unique.
// TODO: perhaps error if the file already exists, to double check that
// the assumptions above are correct.
savedActionID := filepath.Join(sharedTempDir, strings.ReplaceAll(curPkgPath, "/", ","))
if err := ioutil.WriteFile(savedActionID, curActionID, 0o666); err != nil {
return nil, fmt.Errorf("could not store action ID: %v", err)
}
var files []*ast.File
for _, path := range paths {
file, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
@ -830,6 +882,7 @@ func fillBuildInfo(flags []string) (newImportCfg string, _ error) {
case "", "true":
return "", fmt.Errorf("could not find -buildid argument")
}
curActionID = decodeHash(splitActionID(buildID))
curImportCfg = flagValue(flags, "-importcfg")
if curImportCfg == "" {

@ -1,5 +1,3 @@
[go1.16] skip 'TODO(mvdan): fix for Go 1.16'
env GOPRIVATE=test/main
garble build

Loading…
Cancel
Save