From a9eedc0789085f55193bdbf0d777b8eaeccb1890 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 26 Jan 2022 09:24:25 -0500 Subject: [PATCH] cmd/go: refactor TestScript/build_issue48319 to check a more general property MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The test previously checked that the DWARF DW_AT_comp_dir attribute matched GOROOT_FINAL. However, on further consideration, we believe that DW_AT_comp_dir should not actually match GOROOT_FINAL: the DWARF spec says that DW_AT_comp_dir records “the current working directory of the compilation command that produced this compilation unit”, but the actual working directory of the compilation command proper is a throwaway directory in the build cache — it is neither stable nor meaningful. However, the test was getting at a real issue that we do care about: namely, that the binary produced by a 'go build' command with cgo enabled should not reuse a dependency that embeds a stale GOROOT_FINAL. This change refactors the test to verify the latter property instead of checking DW_AT_comp_dir specifically. For #50183 Updates #48319 Change-Id: I0b1151d9ba3d0ff903f72e27850306406e5cb518 Reviewed-on: https://go-review.googlesource.com/c/go/+/380914 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Russ Cox TryBot-Result: Gopher Robot --- .../go/testdata/script/build_issue48319.txt | 160 +++--------------- 1 file changed, 27 insertions(+), 133 deletions(-) diff --git a/src/cmd/go/testdata/script/build_issue48319.txt b/src/cmd/go/testdata/script/build_issue48319.txt index f58a5faa3f..3979247f2f 100644 --- a/src/cmd/go/testdata/script/build_issue48319.txt +++ b/src/cmd/go/testdata/script/build_issue48319.txt @@ -1,50 +1,33 @@ +# Regression test for https://go.dev/issue/48319: +# cgo builds should not include debug information from a stale GOROOT_FINAL. + [short] skip [!cgo] skip +[windows] skip # The Go Windows builders have an extremely out-of-date gcc that does not support reproducible builds; see https://go.dev/issue/50824. -# Set up fresh GOCACHE +# This test is sensitive to cache invalidation, +# so use a separate build cache that we can control. env GOCACHE=$WORK/gocache mkdir $GOCACHE -# 1. unset GOROOT_FINAL, Build a simple binary with cgo by origin go. -# The DW_AT_comp_dir of runtime/cgo should have a prefix with origin goroot. -env GOROOT_FINAL= -# If using "go run", it is no debuginfo in binary. So use "go build". -# And we can check the stderr to judge if the cache of "runtime/cgo" -# was used or not. -go build -o binary.exe -exec ./binary.exe $TESTGO_GOROOT -stdout 'cgo DW_AT_comp_dir is right in binary' - - -# 2. GOROOT_FINAL will be changed, the runtime/cgo will be rebuild. -env GOROOT_FINAL=$WORK/gorootfinal -go build -x -o binary.exe -stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' -exec ./binary.exe $GOROOT_FINAL -stdout 'cgo DW_AT_comp_dir is right in binary' - - -[!symlink] skip - -# Symlink the compiler to another path -env GOROOT=$WORK/goroot -symlink $GOROOT -> $TESTGO_GOROOT - -# 3. GOROOT_FINAL is same with 2, build with the other go -# the runtime/cgo will not be rebuild. -go build -x -o binary.exe -! stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' -exec ./binary.exe $GOROOT_FINAL -stdout 'cgo DW_AT_comp_dir is right in binary' - - -# 4. unset GOROOT_FINAL, build with the other go -# the runtime/cgo will be rebuild. -env GOROOT_FINAL= -go build -x -o binary.exe -stderr '(clang|gcc)( |\.exe).*gcc_.*\.c' -exec ./binary.exe $GOROOT -stdout 'cgo DW_AT_comp_dir is right in binary' +# Build a binary using a specific value of GOROOT_FINAL. +env GOROOT_FINAL=$WORK${/}goroot1 +go build -o main.exe +mv main.exe main1.exe + +# Now clean the cache and build using a different GOROOT_FINAL. +# The resulting binaries should differ in their debug metadata. +go clean -cache +env GOROOT_FINAL=$WORK${/}goroot2 +go build -o main.exe +mv main.exe main2.exe +! cmp main2.exe main1.exe + +# Set GOROOT_FINAL back to the first value. +# If the build is properly reproducible, the two binaries should match. +env GOROOT_FINAL=$WORK${/}goroot1 +go build -o main.exe +cmp -q main.exe main1.exe -- go.mod -- module main @@ -54,100 +37,11 @@ go 1.18 package main import "C" -import ( - "debug/dwarf" - "fmt" - "log" - "os" - "path/filepath" - "strings" -) + +import "runtime" var _ C.int func main() { - dwarfData, err := readDWARF(os.Args[0]) - if err != nil { - log.Fatal(err) - } - goroot := filepath.Join(os.Args[1], "src") - dwarfReader := dwarfData.Reader() - cgopackage := filepath.Join("runtime", "cgo") - var hascgo bool - for { - e, err := dwarfReader.Next() - if err != nil { - log.Fatal(err) - } - if e == nil { - break - } - field := e.AttrField(dwarf.AttrCompDir) - if field == nil { - continue - } - compdir := field.Val.(string) - if strings.HasSuffix(compdir, cgopackage) { - hascgo = true - if !strings.HasPrefix(compdir, goroot) { - fmt.Printf("cgo DW_AT_comp_dir %s contains incorrect path in binary.\n", compdir) - return - } - } - } - if hascgo { - fmt.Println("cgo DW_AT_comp_dir is right in binary") - } else { - fmt.Println("binary does not contain cgo") - } -} --- 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() -} --- 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() -} --- 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() + println(runtime.GOROOT()) } -- 2.48.1