Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: cannot read build ID from ELF binaries written by gold #21564

Closed
rsc opened this issue Aug 22, 2017 · 3 comments
Closed

cmd/go: cannot read build ID from ELF binaries written by gold #21564

rsc opened this issue Aug 22, 2017 · 3 comments
Milestone

Comments

@rsc
Copy link
Contributor

rsc commented Aug 22, 2017

cmd/go is apparently unable to read the Go build ID from ELF binaries created by /usr/bin/gold on Ubuntu 17.04, which is:

$ gold -v
GNU gold (GNU Binutils for Ubuntu 2.28) 1.14
$

If I build with external linking with and without gold, I get different binaries, both of which seem to have a valid .note.go.buildid section:

$ go build -ldflags=-linkmode=external -o /tmp/hello.default ~/go/test/helloworld.go
$ go build "-ldflags=-linkmode=external -extldflags=-fuse-ld=gold" -o /tmp/hello.gold ~/go/test/helloworld.go
$ objdump -s -j .note.go.buildid /tmp/hello.default

/tmp/hello.default:     file format elf64-x86-64

Contents of section .note.go.buildid:
 400320 04000000 28000000 04000000 476f0000  ....(.......Go..
 400330 61633839 33303162 66323264 39643237  ac89301bf22d9d27
 400340 64626331 35393532 32306538 31333466  dbc1595220e8134f
 400350 34643230 31656132                    4d201ea2        
$ objdump -s -j .note.go.buildid /tmp/hello.gold

/tmp/hello.gold:     file format elf64-x86-64

Contents of section .note.go.buildid:
 4002c0 04000000 28000000 04000000 476f0000  ....(.......Go..
 4002d0 61633839 33303162 66323264 39643237  ac89301bf22d9d27
 4002e0 64626331 35393532 32306538 31333466  dbc1595220e8134f
 4002f0 34643230 31656132                    4d201ea2        
$ readelf -S /tmp/hello.default | grep -C 3 note.go.buildid
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             00000000004002fc  000002fc
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.go.buildid  NOTE             0000000000400320  00000320
       0000000000000038  0000000000000000   A       0     0     32
  [ 4] .note.gnu.build-i NOTE             0000000000400358  00000358
       0000000000000024  0000000000000000   A       0     0     4
$ readelf -S /tmp/hello.gold | grep -C 3 note.go.buildid
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             000000000040028c  0000028c
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.go.buildid  NOTE             00000000004002c0  000002c0
       0000000000000038  0000000000000000   A       0     0     32
  [ 4] .note.gnu.build-i NOTE             00000000004002f8  000002f8
       0000000000000024  0000000000000000   A       0     0     4
$ 

The sections are in a different order using gold but things look OK. In particular the sections themselves seem to have exactly the same bytes in either build.

But while normally go test -run NoteReading cmd/go passes, if I change it to use gold, it fails:

$ git diff
diff --git a/src/cmd/go/note_test.go b/src/cmd/go/note_test.go
index 2ee013faf3..87c31cea88 100644
--- a/src/cmd/go/note_test.go
+++ b/src/cmd/go/note_test.go
@@ -53,7 +53,7 @@ func testNoteReading(t *testing.T) {
 		t.Skipf("skipping - external linking not supported")
 	}
 
-	tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external", "-o", tg.path("hello.exe"), tg.path("hello.go"))
+	tg.run("build", "-ldflags", "-buildid="+buildID+" -linkmode=external -extldflags=-fuse-ld=gold", "-o", tg.path("hello.exe"), tg.path("hello.go"))
 	id, err = main.ReadBuildIDFromBinary(tg.path("hello.exe"))
 	if err != nil {
 		t.Fatalf("reading build ID from hello binary (linkmode=external): %v", err)
$ go test -run=NoteReading cmd/go
--- FAIL: TestNoteReading (0.27s)
	go_test.go:260: running testgo [build -ldflags -buildid=TestNoteReading-Build-ID -o /tmp/gotest563847269/hello.exe /tmp/gotest563847269/hello.go]
	go_test.go:260: running testgo [build -ldflags -buildid=TestNoteReading-Build-ID -linkmode=external -extldflags=-fuse-ld=gold -o /tmp/gotest563847269/hello.exe /tmp/gotest563847269/hello.go]
	note_test.go:62: buildID in hello binary = "", want "TestNoteReading-Build-ID" (linkmode=external)
--- FAIL: TestNoteReading2K (0.27s)
	go_test.go:260: running testgo [build -ldflags -buildid=TestNoteReading-Build-ID -o /tmp/gotest844349056/hello.exe /tmp/gotest844349056/hello.go]
	go_test.go:260: running testgo [build -ldflags -buildid=TestNoteReading-Build-ID -linkmode=external -extldflags=-fuse-ld=gold -o /tmp/gotest844349056/hello.exe /tmp/gotest844349056/hello.go]
	note_test.go:62: buildID in hello binary = "", want "TestNoteReading-Build-ID" (linkmode=external)
FAIL
FAIL	cmd/go	2.469s
$ 

This makes Go using gold do spurious rebuilds of binaries, because they appear out of date but are not.

I discovered this by compiling gccgo from source, which installed a new gcc into /usr/local/bin, and I'd (apparently mistakenly) configured with --with-ld=/usr/bin/gold. I will rebuild without that, but we should probably understand what is going on here.

I remember that in the past we've had problems with Ubuntu shipping ancient buggy versions of gold. I wondered if that might be the case here, but objdump and readelf are happy with the binary, so the go command probably should be made to be happy too.

@rsc
Copy link
Contributor Author

rsc commented Aug 22, 2017

/cc @ianlancetaylor

@rsc rsc added this to the Go1.10 milestone Aug 22, 2017
@ianlancetaylor
Copy link
Contributor

The bug is that the Go linker is using the wrong alignment for the SHT_NOTE section. The difference is that gold accumulates the SHT_NOTE sections into a single PT_NOTE segment, where the alignment makes the note impossible to find reliably. The GNU linker generates multiple PT_NOTE segments.

@gopherbot
Copy link

Change https://golang.org/cl/58290 mentions this issue: cmd/link: set correct alignment of ELF note section

@golang golang locked and limited conversation to collaborators Aug 24, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants