-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/link: Cross-compiled binaries using cgo selects incorrect ld-linux #12443
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
Comments
This is usually gnu multi arch which decided to move the location of the loader .so. I don't know where you got that tool chain from, but you may need a different one. In any case, you found the workaround which is to create a symlink to the expected location of the linker. If you grep for that location in the go source, I think there is a comment explaining it.
|
If you are using cgo, then the Go linker should be invoking the system linker, and that is where the interpreter is being set. Try your build with -ldflags=-v. That should show how the system linker is being run. |
The toolchain is created by the Yocto Project (as part of a their Creating a toolchain section ) I would argue that that's not quite expected behavior on Go's part rather than the toolchain which has been fairly battletested by the Yocto crowd but I'm happy to be wrong 😄 From standard compilation you can see that ld-linux-armhf.so.3 is present...
But the same snippet from the go compilation has:
How can it be controlled to pick a specific/default one? |
What is the output of |
I think it might be because it's using internal linking?
Internal linking does have the ELF interpreter hardcoded.
Have you tried to add -ldflags "-linkmode external" to your
go build command line?
|
|
Not a blind bit of difference sadly, as mentioned - there's some hardcoding for EABI vs OABI in cmd/link/internal/arm/obj.go which seems to be the issue. |
When external linking, the elf interpreter should be selected by your cross
compiler.
To verify, go build -ldflags "-linkmode external -v " and look at the gcc
invocation command line.
|
Combining with the -v you get:
@minux It's essentially the same information, I was reading the arm linking code in the go src and I don't think it ever consults GCC for that information? |
In your case the Go linker is simply running arm-poky-linux-gnueabi-gcc and trusting that it will do the right thing. The Go linker doesn't need to consult GCC, it is actually running GCC. |
The output of GCC -dumpspecs shows that your compiler will only use ld-linux-armhf.so.3 when the -mfloat-abi=hard option is used. You need to arrange for your Go code to pass that option to the external linker. The easiest way to do that is to add Closing this because I don't think Go can do any better. Please feel free to reopen if you think there is something we can do. |
@ianlancetaylor Yeah I think that makes sense, I wasn't aware of that requirement but that's great. This ticket should stand as a useful resource for others at least! Can confirm that adding
|
I think the root of this issue is that go doesn't honour the whole $CC environment variable. OpenEmbedded (poky) sets the CC variable to the whole command needed to compile for a given target. Its compiler and linker binaries are generic, and need to be told about their target platforms. On my system CC is: CC="arm-poky-linux-gnueabi-gcc -march=armv7-a -marm -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a9 --sysroot=/oe/build/tmp-glibc/sysroots/wandboard" but when go runs it only runs arm-poky-linux-gnueabi-gcc for linking. Is that the intended behaviour, or is this this a bug? |
That is a bug. But it's not this bug. Please open a new issue with a test case. Thanks. |
I am trying to use a Yocto toolchain to build cross-platform binaries for a Gumstix targte using the cgo bindings with the following code:
I built it using the following:
When trying to run the executable on target you groan and see:
The issue seems to be that the runtime loader used is incorrect
If you run readelf you can see it's embedding ld-linux.so.3 as the linux loader but the toolchain is configured for ld-linux-armhf.so.3
I'm not sure why this has happened as those CC and CFLAGS are exactly that used to produce other binaries which don't have this issue i.e.:
After a bit of faffing and checking out the binaries a suggested workaround is simply to create a softlink between the two but this should ideally be fixed when building:
Any suggestions?
The text was updated successfully, but these errors were encountered: