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: go version <binary> fails with -buildmode=pie Linux ELF binaries #31861

Closed
rsc opened this issue May 6, 2019 · 17 comments
Closed

cmd/go: go version <binary> fails with -buildmode=pie Linux ELF binaries #31861

rsc opened this issue May 6, 2019 · 17 comments
Labels
FrozenDueToAge GoCommand cmd/go modules NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Milestone

Comments

@rsc
Copy link
Contributor

rsc commented May 6, 2019

$ go build -o /tmp/go.exe
$ go version /tmp/go.exe
/tmp/go.exe: go version not found
$

It's possible I am using too old a tree but I think this is still broken at head.

@rsc rsc added this to the Go1.13 milestone May 6, 2019
@ianlancetaylor
Copy link
Contributor

In a -buildmode=pie executable the .go.buildinfo section is deep into the data segment, much farther than the 64K that go version reads. This doesn't actually have anything to do with -buildmode=pie as such; go version fails on ELF systems when using -ldflags=-linkmode=external, and -buildmode=pie currently implies an external link.

@ianlancetaylor
Copy link
Contributor

It's not clear to me why the .go.buildinfo section is writable.

@dotaheor
Copy link

dotaheor commented May 7, 2019

A little off topic, is there an option to disable packaging module versions in building?

@andybons andybons added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label May 8, 2019
@rsc
Copy link
Contributor Author

rsc commented Jun 6, 2019

We can certainly fall back to reading the ELF binaries to find the right place in non-stripped binaries. We just can't assume that in general.

@rsc
Copy link
Contributor Author

rsc commented Jun 6, 2019

@dotaheor, no there's no such option.

@ianlancetaylor
Copy link
Contributor

But why is the section writable? If it weren't writable, it would be in the text segment, and more likely to be found with the current algorithm.

@bcmills
Copy link
Contributor

bcmills commented Jun 26, 2019

@ianlancetaylor, just to try to understand the problem I changed cmd/link/sym to mark SBUILDINFO as read-only.

That caused the internal linking of -buildmode=pie tests to crash with a segmentation fault in _dl_relocate_object, so I added a corresponding SBUILDINFORELRO section and tried again.

That made all.bash once again pass, but empirically did not fix go version.

@bcmills
Copy link
Contributor

bcmills commented Jun 28, 2019

I looked in to this some more, but I'm in way over my head.

I know that the choice to make SBUILDINFO writable was intentional, because the DataStart methods in cmd/go/internal/version/exe.go look for the first writable section specifically. I do not understand why the section must be writable, and I can't figure out what is supposed to ensure the ordering of the writable sections in the final binary.

@ianlancetaylor
Copy link
Contributor

It sounds like making the section readonly didn't help anyhow.

On ELF I think we can look for the section by opening the file using elf.Open and finding the section using elf.(*File).Section.

@rsc
Copy link
Contributor Author

rsc commented Jul 2, 2019

I think the problem with non-writable was that it contains pointers to writable variables so the relocations were simpler if they were in the same section.

@Infinoid
Copy link
Contributor

For ELF binaries, the "go version" command finds the .go.buildinfo data by searching for the first program-header that's read-write, and hoping the version info is near that.

Is there any reason why you don't look for a section header named ".go.buildinfo", instead?

@Infinoid
Copy link
Contributor

Infinoid commented Jul 18, 2019

The above fix gets "go version exefile" working for me on amd64 ubuntu 18.04, with or without external linking, with or without pie, with or without stripping the binary. I think it should work on all ELF platforms; I don't know about other file formats.

@gopherbot
Copy link

Change https://golang.org/cl/186737 mentions this issue: cmd/go: fix "go version" bug #31861

@odeke-em
Copy link
Member

odeke-em commented Aug 5, 2019

Hello @Infinoid, thank you for mailing a fix!
Ian left some feedback on your CL some days ago but since we are just about to release Go1.13, I kindly wanted to nudge you to take a look or please let him know if you won't have time to make the update and he can make the update -- apologies for rushing you.

@gopherbot
Copy link

Change https://golang.org/cl/188957 mentions this issue: cmd/go: look for .go.buildinfo section when looking for ELF version

@jayconrod
Copy link
Contributor

The updated test fails on darwin. It looks like the only TryBot that runs without -short is on Linux, so we didn't catch this.

I'll prepare a fix for Mach-O.

I don't think we need to fix this for PE binaries, since -buildmode=pie is not supported on Windows. I don't know whether we need to fix XCOFF.

@jayconrod jayconrod reopened this Aug 6, 2019
@gopherbot
Copy link

Change https://golang.org/cl/189159 mentions this issue: cmd/go: look for __go_buildinfo section when looking for Mach-O version

@golang golang locked and limited conversation to collaborators Aug 5, 2020
@rsc rsc removed their assignment Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge GoCommand cmd/go modules NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants