-
Notifications
You must be signed in to change notification settings - Fork 18k
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/link: does not support multiple TOCs in internal linking mode #21961
Comments
/cc @laboger |
@mundaym I'm using latest one
|
I rolled back to
@mundaym @ianlancetaylor not really sure what is wrong with the latest version! |
Yikes I haven't been watching the build board lately and I see we have been randomly failing in runtime since e7e4a4f and this latest failure of SEGV was introduced with @ianlancetaylor 's change 8e5ac83. segv happens here: 0x112c0 <runtime/cgo(.text).sigfillset>: std r2,24(r1) In golang prior to the change to omit the ld -r where it works, this code looks like this: => 0x112c0 <runtime/cgo(.text).sigfillset>: std r2,24(r1) So my theory is that the TOCs from the individual .o files should be getting merged into a single TOC at some point, but if the external linker isn't involved in the final link, how's it going to happen except by the ld -r? My understanding is that the go tool is linked with the internal linker and not the external linker, so in that case the ld -r is still useful for ppc64le. This brings up a different concern however, why this wasn't caught in the buildbots? |
You mean the trybots? They don't run on ppc64x, they only check that the compilation works. |
FYI... this doesn't affect ppc64 because 'go' is built statically there. |
@mundaym This breaks the 'go' tool so I was somewhat thinking that it should fail during the build. But I see now that go_bootstrap is built as static but the final go tool is built as a dynamic binary containing cgo using the internal linker which is the case that is broken by the removal of ld -r. |
Any updates? builds are still failing with the latest code. @ianlancetaylor any comments? |
@ianlancetaylor I don't know what your thoughts are on this. This regression makes the go tool unusable on the golang build so we would like to get this fixed. I can create a fix to back out your change for ppc64le, i.e., continue to use the ld -r on ppc64le but not on other platforms. I believe the other option is to fix the internal linker to correctly handle merging of the TOCs, but that might take me a while because I don't know the internal linker well enough. |
What happens if we simply add
That seems to me like the right temporary fix unless and until somebody fixes the internal linker. The downside is that we won't generate fully statically linked binaries for pure Go programs on ppc64le. Is that acceptable? |
Isn't this going to force external linking only when iscgo is true? So pure Go programs on ppc64le should still be truly statically linked with this change. I just tried it, and that's what happened with a simple hello.go without cgo, which is pure Go AFAIK? I think this is the correct temporary fix, but this means the 'go' tool is linked with the external linker and not the internal linker. In both cases it is a dynamic binary. I'm not sure what the downside might be for using a different linker. |
Sorry, what I wrote was a little confusing. I think this will change the behavior of any pure Go program that imports the net or os/user packages. I think that currently they will use internal linking, and with my suggestion they will use external linking. You're right that they will be dynamically linked either way. I think the only significant difference is that with this change a pure Go program (that imports the net or os/user package) will only be buildable if the C linker is installed on the system where the Go program is being built. Without this change such a program would be buildable even if the C linker was not installed at all. On GNU/Linux I doubt that is worth worrying about (on Windows, on the other hand, it would be a problem). Does the change actually fix the problem? |
Yes this fixes the problem, sorry I wasn't explicit on that. I don't have a good feel for how many programs might be affected or who would care. Obviously the building of the 'go' tool requires the 'ld -r' so it must have the C linker on the system. I think we fix it and see who complains. |
You're right that clearly invoking |
Change https://golang.org/cl/66270 mentions this issue: |
The internal linker doesn't know how to handle multiple TOC sections in internal linking mode. This used to work because before CL 64793 we invoked ld -r on multiple objects, and that merged the TOC sections for us. Updates #21961 Change-Id: I48260a7195be660016f2f358ebc8cb79652210ab Reviewed-on: https://go-review.googlesource.com/66270 Run-TryBot: Ian Lance Taylor <iant@golang.org> Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This is related to #15409 is it not? From my POV I'd be fine with deleting all the code related to internal linking support for cgo but that might not be terribly friendly. |
Yes, it seems likely that fixing this would fix #15409. Internal linking is quite important on Windows but I agree that it is less interesting on GNU/Linux systems. Still, in general, it is a goal that people can install a Go distribution and, as long as they don't use cgo, use it with no C compiler or linker installed. With the current standard library that means that the internal linker must support at least the code generated for the net and os/user packages. |
The recent breakage in the ppc64x builds and the discussion about cross builds made me curious, so I did a cross build of golang for ppc64le and found that the go binary created is statically (and therefore internally) linked. I moved the cross built golang over to a ppc64le machine and the tests all passed. So I think that means an installation of a Go distribution for ppc64le from a cross build on an x86 could be installed with no C compiler or linker. At this point I don't understand why the go binary is built differently when doing a cross. It seems that it should be built the same way whether cross or natively built. It should still have multiple TOCs in both cases? |
By default when cross-compiling we assume that we don't have a C cross-compiler available, so we build without cgo support. You should be able to get the same result cross and native, assuming you have a C cross-compiler, if you set |
@cherrymui @jeremyfaller Do you have a guess on how much work it would be to get internal linking to work with cgo on ppc64le? Maybe some relocation types are missing and then this TOC merging would have to be done. |
I'm not familiar with the ABI to tell. I would guess as long as we actually understand the ABI, it won't take much work. Maybe keep track the multiple TOCs, and group them together (?) according to the ABI? |
Actually I'm not sure if the title truly explains the problem here. It's been a while so I'm looking back through to try and understand what's really wrong. I know the problem happened because there were two relocatable files to be linked together and they both had references which needed plt generation. They previously worked because 'ld -r' was done for all those files prior to the final link. When the 'ld-r' was removed this quit working and the fix was to disable internal linking with cgo on ppc64le. Is this the ABI you mean? https://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html |
I tried to enable internal linking with cgo on master in cmd/link/internal/ld/config.go and got this error during the build:
I added print statements before the panic and the empty container was the .got. |
@cherrymui I think I found out why the "initialize bounds" error message is happening in .plt. In cmd/link/internal/ppc64/asm.go function addpltsym, when an entry is added to the plt using plt.Grow, that doesn't update the size. If I add a call to plt.SetSize to increase the plt size then I can get past this error. By the way, is there a tool like readelf to see what relocations are in the runtime/cgo(.text) and runtime/cgo(.toc) sections? It looks like the problem is that each input file has a runtime/cgo with (.text) and (.toc) but then at the final link, the relocations assume a single TOC. So some of the r2 addresses and relocated offsets are wrong because of this. |
That makes sense.
Sorry I'm not sure I understand what you mean. Why |
I was able to get readelf to work, I was trying it on the wrong type of file. I'm trying to understand how the SELFGOT data should be processed because that's the problem I'm trying to resolve next.
And then in cmd/link/internal/ld/data.go function allocateDataSections it tries to process the SELFGOT entries and there are a few problems with that code:
I don't know if the code in allocateDataSections for processing the SELFGOT for PPC64 is currently used for AIX or if it ever executed at all. |
Change https://golang.org/cl/261837 mentions this issue: |
When attempting to enable internal linking with cgo on ppc64 it was discovered that the plt size was not being updated after adding entries to it, which resulted in this error: .plt: initialize bounds (16 < 24) This changes fixes that problem. Updates #21961 Change-Id: Ie17539c329f5a4802e5defd93852dcdde19ded8c Reviewed-on: https://go-review.googlesource.com/c/go/+/261837 Trust: Lynn Boger <laboger@linux.vnet.ibm.com> Run-TryBot: Lynn Boger <laboger@linux.vnet.ibm.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Change https://golang.org/cl/304458 mentions this issue: |
Change https://golang.org/cl/304459 mentions this issue: |
Setup .TOC. to point to the same place for all objects. Today, the linker assumes all call relocations can use the local function entry point of imported object files. This requires a consistent pointer across all objects. This intentionally computes the .TOC. pointer in all linking configurations. In some cases the .TOC. is not used today (e.g linking position-dependent go only code). It is harmless and simple to compute in all cases, so just do it for easier maintenance. Notably, .TOC. is used in some cases when static linking is requested on ppc64le/linux: * Position-independent C code using a PC-rel relocation against .TOC.. cgo generated C object files are usually compiled PIC even if the go binary itself is not. * Anything which causes PLT stub generation. The stubs always generate a .TOC. relative relocation. * The race detector. Today, this links in an externally compiled archive which contains position-independent object files. Similarly, position-independent linking is always punted to the external linker on ppc64 today. Updates #21961 Fixes #15409 Change-Id: Ifd8294b9249e16ba8b92eaf876d15d162f9c61fd Reviewed-on: https://go-review.googlesource.com/c/go/+/304458 Reviewed-by: Cherry Mui <cherryyz@google.com> Trust: Lynn Boger <laboger@linux.vnet.ibm.com>
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?master
Does this issue reproduce with the latest release?
yes
What operating system and processor architecture are you using (
go env
)?ppc64le
What did you do?
export PATH=/usr/local/go/bin/:$PATH
export GOROOT_BOOTSTRAP=
go env GOROOT
root@localhost:~/go/bin# go version
go version go1.8.3 linux/ppc64le
cloned the latest code here:
root@localhost:~/go/src# pwd
/root/go/src
run make.bash
root@localhost:~/go/src# ./make.bash
Use the build go binary:
If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.
What did you expect to see?
Instead, I should see a golang version
What did you see instead?
I see a SIGSEGV
The text was updated successfully, but these errors were encountered: