Skip to content

Module Info (runtime.modinfo) prevents binary comparison #49573

@markdascher

Description

@markdascher

What version of Go are you using (go version)?

$ go version
go version go1.17.2 darwin/amd64

Does this issue reproduce with the latest release?

Yes, it also happens when I build go version go1.17.3 darwin/amd64 from source.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="auto"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/…/Library/Caches/go-build"
GOENV="/Users/…/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/…/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/Users/…/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/Cellar/go/1.17.2/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/Cellar/go/1.17.2/libexec/pkg/tool/darwin_amd64"
GOVCS=""
GOVERSION="go1.17.2"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/qg/q9y62zhd5fsdgs48lbmy7mrr0000gq/T/go-build2909188506=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

$ mkdir test
$ cd test
$ go mod init test
$ cat > tools.go <<EOF
//go:build tools

package tools

import _ "github.com/mitchellh/gox"
EOF
$ go mod tidy

$ go clean -cache -testcache -modcache
$ go install -ldflags="-s -w" -trimpath github.com/mitchellh/gox
$ cksum ~/go/bin/gox
4117901733 2801072 ~/go/bin/gox

$ go mod vendor
$ go clean -cache -testcache -modcache
$ go install -ldflags="-s -w" -trimpath github.com/mitchellh/gox
$ cksum ~/go/bin/gox                                            
2432579230 2801072 ~/go/bin/gox

What did you expect to see?

Expected to see the vendored build produce the same binary, with checksum 4117901733. Or at the very least, expected there to be some combination of build flags where go mod vendor doesn't affect the build output.

What did you see instead?

The checksum changed to 2432579230. The most obvious difference comes from runtime.modinfo, where the versioned result doesn't include module hashes:

$ go version -m ~/go/bin/gox 
~/go/bin/gox: go1.17.2
	path	github.com/mitchellh/gox
	mod	github.com/mitchellh/gox	v1.0.1	h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=
	dep	github.com/hashicorp/go-version	v1.0.0	h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8=
	dep	github.com/mitchellh/iochan	v1.0.0	h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=

$ go version -m ~/go/bin/gox 
~/go/bin/gox: go1.17.2
	path	github.com/mitchellh/gox
	mod	github.com/mitchellh/gox	v1.0.1	
	dep	github.com/hashicorp/go-version	v1.0.0	
	dep	github.com/mitchellh/iochan	v1.0.0	

I can eliminate the discrepancy by modifying src/cmd/go/internal/load/pkg.go to skip the modload.PackageBuildInfo() call. And then confirmed -ldflags="-s -w" wasn't needed, since -trimpath is enough to make the two builds identical using the modified release.

I realize the compiler isn't obligated to produce identical outputs in this situation, and that the metadata is normally useful. However, these differences make it impossible to double-check for correctness when migrating to and from vendored mode. Unfortunately, compiler bugs are probably more common than we'd like to admit, and even if the compiler is perfect, my understanding of them definitely isn't. 🙂 So I've gotten in the habit of double-checking things.

Basically, it would be nice to have an off switch. See #41895 for a similar issue. In my case, passing in -linkshared was not permitted. (And even if it worked, it certainly wasn't designed for this.) There are new options -buildinfo and -buildvcs in master, but they only control new fields being added to runtime.modinfo in the next release. This could actually be a good opportunity to come up with a more flexible option for that, like -buildinfo=flags,vcs and -buildinfo=none, since those options haven't been released yet.

I ran into similar difficulty when migrating from GOPATH mode to module-aware mode, and suspect that runtime.modinfo was a culprit there too.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions