1
0
mirror of https://github.com/golang/go synced 2024-11-18 12:04:57 -07:00

cmd/go: trim source paths when compiling C with -trimpath

When then go command is run with -trimpath, it will now use
-fdebug-prefix-map when invoking the C compiler (if supported) to
replace the source root directory with a dummy root directory.

This should prevent source directories from appearing either literally
or in compressed DWARF in linked binaries.

Updates #36072

Change-Id: Iedd08d5e886f81e981f11248a1be4ed4f58bdd29
Reviewed-on: https://go-review.googlesource.com/c/go/+/212101
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
This commit is contained in:
Jay Conrod 2019-12-19 13:43:24 -05:00
parent 5a550b6951
commit 35dce1d67c
3 changed files with 193 additions and 0 deletions

View File

@ -2169,6 +2169,39 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
desc := p.ImportPath
outfile = mkAbs(p.Dir, outfile)
// Elide source directory paths if -trimpath or GOROOT_FINAL is set.
// This is needed for source files (e.g., a .c file in a package directory).
// TODO(golang.org/issue/36072): cgo also generates files with #line
// directives pointing to the source directory. It should not generate those
// when -trimpath is enabled.
if b.gccSupportsFlag(compiler, "-fdebug-prefix-map=a=b") {
if cfg.BuildTrimpath {
// Keep in sync with Action.trimpath.
// The trimmed paths are a little different, but we need to trim in the
// same situations.
var from, toPath string
if m := p.Module; m != nil {
from = m.Dir
toPath = m.Path + "@" + m.Version
} else {
from = p.Dir
toPath = p.ImportPath
}
// -fdebug-prefix-map requires an absolute "to" path (or it joins the path
// with the working directory). Pick something that makes sense for the
// target platform.
var to string
if cfg.BuildContext.GOOS == "windows" {
to = filepath.Join(`\\_\_`, toPath)
} else {
to = filepath.Join("/_", toPath)
}
flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+from+"="+to)
} else if p.Goroot && cfg.GOROOT_FINAL != cfg.GOROOT {
flags = append(flags[:len(flags):len(flags)], "-fdebug-prefix-map="+cfg.GOROOT+"="+cfg.GOROOT_FINAL)
}
}
output, err := b.runOut(a, filepath.Dir(file), b.cCompilerEnv(), compiler, flags, "-o", outfile, "-c", filepath.Base(file))
if len(output) > 0 {
// On FreeBSD 11, when we pass -g to clang 3.8 it

View File

@ -223,6 +223,10 @@ CheckFlags:
// trimpath returns the -trimpath argument to use
// when compiling the action.
func (a *Action) trimpath() string {
// Keep in sync with Builder.ccompile
// The trimmed paths are a little different, but we need to trim in the
// same situations.
// Strip the object directory entirely.
objdir := a.Objdir
if len(objdir) > 1 && objdir[len(objdir)-1] == filepath.Separator {

View File

@ -0,0 +1,156 @@
# This test builds a cgo binary and verifies the source directory path
# does not appear in the binary, either literally or in compressed DWARF.
# TODO(golang.org/issue/36072): ideally we should build a binary from identical
# sources in different directories and verify the binary and all intermediate
# files are identical.
[short] skip
[!cgo] skip
# Check that the source path appears when -trimpath is not used.
go build -o hello.exe .
grep -q gopath[/\\]src hello.exe
go run ./list-dwarf hello.exe
stdout gopath[/\\]src
# Check that the source path does not appear when -trimpath is used.
[aix] stop # can't inspect XCOFF binaries
go build -trimpath -o hello.exe .
! grep -q gopath[/\\]src hello.exe
go run ./list-dwarf hello.exe
! stdout gopath/src
-- go.mod --
module m
go 1.14
-- hello.c --
#include <stdio.h>
void say_hello() { puts("Hello, world!\n"); }
-- hello.go --
package main
// void say_hello();
import "C"
func main() {
C.say_hello()
}
-- list-dwarf/list-dwarf.go --
package main
import (
"debug/dwarf"
"fmt"
"io"
"log"
"os"
"sort"
)
func main() {
files, err := run(os.Args[1])
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file)
}
}
func run(exePath string) ([]string, error) {
dwarfData, err := readDWARF(exePath)
if err != nil {
return nil, err
}
dwarfReader := dwarfData.Reader()
files := make(map[string]bool)
for {
e, err := dwarfReader.Next()
if err != nil {
return nil, err
}
if e == nil {
break
}
lr, err := dwarfData.LineReader(e)
if err != nil {
return nil, err
}
if lr == nil {
continue
}
var le dwarf.LineEntry
for {
if err := lr.Next(&le); err != nil {
if err == io.EOF {
break
}
return nil, err
}
files[le.File.Name] = true
}
}
sortedFiles := make([]string, 0, len(files))
for file := range files {
sortedFiles = append(sortedFiles, file)
}
sort.Strings(sortedFiles)
return sortedFiles, nil
}
-- list-dwarf/read_darwin.go --
package main
import (
"debug/dwarf"
"debug/macho"
)
func readDWARF(exePath string) (*dwarf.Data, error) {
machoFile, err := macho.Open(exePath)
if err != nil {
return nil, err
}
defer machoFile.Close()
return machoFile.DWARF()
}
-- list-dwarf/read_elf.go --
// +build android dragonfly freebsd illumos linux netbsd openbsd solaris
package main
import (
"debug/dwarf"
"debug/elf"
)
func readDWARF(exePath string) (*dwarf.Data, error) {
elfFile, err := elf.Open(exePath)
if err != nil {
return nil, err
}
defer elfFile.Close()
return elfFile.DWARF()
}
-- list-dwarf/read_windows.go --
package main
import (
"debug/dwarf"
"debug/pe"
)
func readDWARF(exePath string) (*dwarf.Data, error) {
peFile, err := pe.Open(exePath)
if err != nil {
return nil, err
}
defer peFile.Close()
return peFile.DWARF()
}