Skip to content

runtime, liblink, cmd/ld: externally linked binaries without cgo crash immediately on amd64 #9913

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

Closed
mwhudson opened this issue Feb 18, 2015 · 3 comments
Milestone

Comments

@mwhudson
Copy link
Contributor

If you externally link a binary and runtime/cgo.a cannot be found (maybe by saying CGO_ENABLED=0 ./make.bash) you get a warning, and a binary that crashes during startup:

mwhudson@narsil:src$ ../bin/go run -ldflags -linkmode=external /opt/opensource/go-test-cases/trivial.go
# command-line-arguments
warning: unable to find runtime/cgo.a
signal: segmentation fault (core dumped)

The reason turns out to be a disagreement over the TLS offset for g. Presumably because both g and m used to be stored in TLS, the runtime and internal linking assumes it to be 16 but as g is now the only pointer stored in TLS, binutils ld sets it to 8, causing the tls consistency check on startup to fail.

I see two ways to fix this: one would be to just change the runtime and internal linker to assume the offset is 8 bytes and the other would be use a special relocation to get the linker (either internal or external) to tell us what the symbol is. In the latter case I don't think there would really be any need to do the magic import of runtime/cgo in an externally linked program (the comment justifying it is already a bit wrong, unless I am very confused).

mwhudson added a commit to mwhudson/go that referenced this issue Feb 18, 2015
The runtime assumes that it knows the offset from the TLS base to g,
but in the external linking case it is actually the host linker that
decides.  This changes the runtime (on linux/amd64 only) to use a
global variable with a magic name that the linker recognizes and
generates the appropriate relocation to overwrite it with the offset.

Fixes golang#9913

Change-Id: I75050866dbb7f0f5a952ffaa9c4caca6e5212ee7
@minux
Copy link
Member

minux commented Feb 18, 2015 via email

@mwhudson
Copy link
Contributor Author

Ah, so my evil plan to delete that code completely can't work. Shame. Maybe we can update the comment though?

@minux
Copy link
Member

minux commented Feb 18, 2015 via email

@mikioh mikioh added this to the Go1.5 milestone Mar 5, 2015
mwhudson added a commit to mwhudson/go that referenced this issue Mar 16, 2015
For OSes that use elf on intel, 2*Ptrsize bytes are reserved for TLS.
But only one pointer (g) has been stored in the TLS for a while now.
So we can set it to just Ptrsize, which happily matches what happens
when externally linking.

Fixes golang#9913

Change-Id: Ic816369d3a55a8cdcc23be349b1a1791d53f5f81
mwhudson added a commit to mwhudson/go that referenced this issue Mar 16, 2015
The runtime assumes that it knows the offset from the TLS base to g,
but in the external linking case it is actually the host linker that
decides.  This changes the runtime (on linux/amd64 only) to use a
global variable with a magic name that the linker recognizes and
generates the appropriate relocation to overwrite it with the offset.

Fixes golang#9913

Change-Id: I75050866dbb7f0f5a952ffaa9c4caca6e5212ee7
@golang golang locked and limited conversation to collaborators Jun 25, 2016
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

4 participants