I'm trying to update our LLVM version to current master. Ran into this linker error:
/usr/bin/ld: /home/nikic/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-5c2422e2d705ee7d.rlib(std-5c2422e2d705ee7d.std.e5hw7qqp-cgu.2.rcgu.o): TLS transition from R_X86_64_TLSLD to R_X86_64_TPOFF32 against `_ZN3std10sys_common11thread_info11THREAD_INFO7__getit5__KEY17hc720e1025694e38eE' at 0x15 in section `.text._ZN3std10sys_common11thread_info3set17hbe84d5bac17e4e00E' failed
I'm a bit stumped on how I would go about debugging something like this.
I suspect this is due to https://reviews.llvm.org/D62106. It looks like __tls_get_addr now uses a GOTPCREL rather than PLT32 relocation and that somehow breaks things.
Try another linker, possibly a linker bug with your particular version of binutil.
At least if I understand the error correctly, then "ELF handling for Thread-Local storage document” specifies a mechanism to transition from TLSLD to TPOFF32
As far as debugging goes, I would also attempt to 1) minimize and 2) look at the assembly to understand what relocations llvm generates
Yeah, I've minimized this (just a thread local linked in from a different crate is enough) and looked at the objdump differences, which turned out to just be GOT vs PLT for the __tls_get_addr symbol.
Tried a different linker -- works with gold.
Wait no, it seems to work with both binutils ld and gold when explicitly specified via
-C linker. But fails without. What is our default linker?
Looks like the default linker is
Okay, it doesn't work with -Clinker after all. Turns out I just get an empty executable in that case because crt0 is not linked in. After dropping libc it also happens with an explicit
linker-flavour option which specifies what kind of a linker you’re using.
My go-to alternative is usually