When cross-building the Rust compiler for sparc64-unknown-linux-gnu, the build fails with an internal binutils error: error: linking with `sparc64-linux-gnu-gcc` failed: exit code: 1 | = note: "sparc64-linux-gnu-gcc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-L" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/sparc64-unknown-linux-gnu/lib" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std0-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std1-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std10-7456b92f185380f18a6 46928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std11-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std12-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std13-7456 b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std14-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std15-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std2-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std3-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std4-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std5-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std6-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std7-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std8-7456b92f185380f18a646928cc900174.rs.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.std9-7456b92f185380f18a646928cc900174.rs.rcgu.o" "-o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/libstd-50a30754efc77185.so" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.crate.metadata.rcgu.o" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps/std-50a30754efc77185.crate.allocator.rcgu.o" "-Wl,-z,relro,-z,now" "-Wl,-O1" "-nodefaultlibs" "-L" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/deps" "-L" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/release/deps" "-L" "/srv/glaubitz/rust/rust/build/sparc64-unknown-linux-gnu/native/libbacktrace/.libs" "-L" "/srv/glaubitz/rust/rust/build/sparc64-unknown-linux-gnu/native/jemalloc/lib" "-L" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1-std/sparc64-unknown-linux-gnu/release/build/compiler_builtins-990f7637d0503f4e/out" "-L" "/srv/glaubitz/rust/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/sparc64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,--whole-archive" "-l" "backtrace" "-Wl,--no-whole-archive" "-Wl,-Bdynamic" "-l" "dl" "-l" "rt" "-l" "pthread" "-Wl,-Bstatic" "-Wl,--whole-archive" "/tmp/rustc.SObmSkbjz1fo/libpanic_unwind-4f85ba5d0e870e29.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.SObmSkbjz1fo/libunwind-c86c9565da689e14.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.SObmSkbjz1fo/liballoc_system-655151fba596847e.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.SObmSkbjz1fo/liblibc-b8f9bb8294d9a014.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.SObmSkbjz1fo/liballoc-513d34708cb20443.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.SObmSkbjz1fo/libstd_unicode-5211f032242a5357.rlib" "-Wl,--no-whole-archive" "-Wl,--whole-archive" "/tmp/rustc.SObmSkbjz1fo/libcore-e2f49b08d2bc06b5.rlib" "-Wl,--no-whole-archive" "/tmp/rustc.SObmSkbjz1fo/libcompiler_builtins-136e26942e0df602.rlib" "-Wl,-Bdynamic" "-l" "gcc_s" "-l" "c" "-l" "m" "-l" "rt" "-l" "pthread" "-l" "util" "-l" "util" "-shared" "-Wl,-rpath,$ORIGIN/../lib" = note: /usr/lib/gcc-cross/sparc64-linux-gnu/7/../../../../sparc64-linux-gnu/bin/ld: BFD (GNU Binutils for Debian) 2.30 internal error, aborting at ../../bfd/elflink.c:9710 in elf_link_output_extsym /usr/lib/gcc-cross/sparc64-linux-gnu/7/../../../../sparc64-linux-gnu/bin/ld: Please report this bug. collect2: error: ld returned 1 exit status The issue is resolved immediately by downgrading to binutils 2.28.
Please try master branch. This may have been fixed by commit a8735c82b8519d8b18915765ca983fc07154a17d Author: Eric Botcazou <ebotcazou@gcc.gnu.org> Date: Sat Feb 10 02:30:25 2018 +0100 Fix GOT relocation overflow on SPARC. commit c20c30f615756ddfccc4bb75c65ccfc1a399466e Author: Eric Botcazou <ebotcazou@gcc.gnu.org> Date: Tue Feb 6 18:15:56 2018 +0100 Fix PR ld/22263 on SPARC. This is -fpie -pie generating dynamic relocations in the text section, simply because no TLS transitions are applied in PIE mode. The meat of the patch is to turn calls to bfd_link_pic (info) in TLS-related code into !bfd_link_executable (info) and there are quite a lot of them.
The GOT relocation issue I just fixed (on master, 2.30 and 2.29 branch) can have pretty much unpredictable results since it may cause memory corruption. Please retry with updated sources containing the fix.
While the patch from a8735c82b8519d8b18915765ca983fc07154a17d was actually still missing and using a binutils with the patch actually fixed another build issue with rustc for me, this particular error is still present - even with binutils built and installed from git: = note: /usr/local/bin/ld: BFD (GNU Binutils) 2.30.51.20180211 internal error, aborting at elflink.c:9710 in elf_link_output_extsym /usr/local/bin/ld: Please report this bug. collect2: error: ld returned 1 exit status error: aborting due to previous error error: Could not compile `std`.
So, after debugging this, the problem is as follows: Rust is using LLVM with -integrated-as (at least effectively; it may well be using it as a library and setting the flag itself, but the point is that the lowered IR is fed straight into the object code backend rather than being serialised via assembly and then assembled separately). LLVM's SparcMCCodeEmitter::getCallTargetOpValue handles __tls_get_addr specially to not emit an R_SPARC_WDISP30/WPLT30, and somewhere else the R_SPARC_TLS_LDM_CALL gets emitted, but the important point is that __tls_get_addr is never added to the output object file's symbol table despite being the symbolic operand to the call instruction. Thus, when linking one of these object files, that object file's hash table never pulls in the definition of __tls_get_addr, and so when _bfd_sparc_elf_check_relocs is called for an R_SPARC_TLS_LDM_CALL, it looks up __tls_get_addr, doesn't find it, and so an entry is created, since TRUE is passed to bfd_link_hash_lookup for create, but this entry has type bfd_link_hash_new, and this never changes. So it seems to me there are two issues here: 1. LLVM should be emitting an entry for __tls_get_addr in its symbol table so it is made visible to the object file. 2. ld should gracefully handle this case. If this case is an error, it should instead be passing FALSE for create to bfd_link_hash_lookup, and if the result is NULL, printing an error; otherwise, if this case should work, something needs to implicitly pull in the symbol (and in theory LLVM doesn't need to change, though in practice it's best to do so anyway for compatibility). I've talked specifically about local-dynamic here for simplicity, but global-dynamic has the same issue too. Note that gold also falls foul of this, giving "gold: internal error in tls_get_addr_sym, at ../../gold/sparc.cc:391", though line 391 is "gold_assert(this->tls_get_addr_sym_);" which is much easier to debug! Reproduction: jrtc27@deb4g:~/tmp/22832$ cat 22832.c __thread int x; int f(void) { return x; } jrtc27@deb4g:~/tmp/22832$ clang -integrated-as -o 22832.o -fPIC -c 22832.c jrtc27@deb4g:~/tmp/22832$ readelf -Wrs 22832.o Relocation section '.rela.text' at offset 0x138 contains 6 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000008 0000000300000011 R_SPARC_PC22 0000000000000000 _GLOBAL_OFFSET_TABLE_ + 4 000000000000000c 0000000300000010 R_SPARC_PC10 0000000000000000 _GLOBAL_OFFSET_TABLE_ + 8 0000000000000014 0000000500000038 R_SPARC_TLS_GD_HI22 0000000000000000 x + 0 0000000000000018 0000000500000039 R_SPARC_TLS_GD_LO10 0000000000000000 x + 0 000000000000001c 000000050000003a R_SPARC_TLS_GD_ADD 0000000000000000 x + 0 0000000000000020 000000050000003b R_SPARC_TLS_GD_CALL 0000000000000000 x + 0 Symbol table '.symtab' contains 6 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FILE LOCAL DEFAULT ABS 22832.c 2: 0000000000000000 0 TLS LOCAL DEFAULT 4 .tbss 3: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND _GLOBAL_OFFSET_TABLE_ 4: 0000000000000000 52 FUNC GLOBAL DEFAULT 2 f 5: 0000000000000000 4 TLS GLOBAL DEFAULT 4 x jrtc27@deb4g:~/tmp/22832$ ld -o lib22832.so -shared 22832.o ld: BFD (GNU Binutils) 2.30.51.20180211 internal error, aborting at elflink.c:9710 in elf_link_output_extsym ld: Please report this bug. jrtc27@deb4g:~/tmp/22832$ gold -o lib22832.so -shared 22832.o gold: internal error in tls_get_addr_sym, at ../../gold/sparc.cc:391
> Thus, when linking one of these object files, that object file's hash table > never pulls in the definition of __tls_get_addr, and so when > _bfd_sparc_elf_check_relocs is called for an R_SPARC_TLS_LDM_CALL, it looks > up __tls_get_addr, doesn't find it, and so an entry is created, since TRUE > is passed to bfd_link_hash_lookup for create, but this entry has type > bfd_link_hash_new, and this never changes. > > So it seems to me there are two issues here: > > 1. LLVM should be emitting an entry for __tls_get_addr in its symbol table > so it is made visible to the object file. > > 2. ld should gracefully handle this case. If this case is an error, it > should instead be passing FALSE for create to bfd_link_hash_lookup, and if > the result is NULL, printing an error; otherwise, if this case should work, > something needs to implicitly pull in the symbol (and in theory LLVM doesn't > need to change, though in practice it's best to do so anyway for > compatibility). Thanks for debugging this. The irony is that I put TRUE precisely because I thought it would deal with such a case... Given that Gold and ld agree, I think that the error is indeed on the LLVM side but you're right that ld should handle this more gracefully (it's not too bad either). Do you want me to prepare a patch or do you intend to do it?
(In reply to James Clarke from comment #4) > Note that gold also falls foul of this, giving "gold: internal error in > tls_get_addr_sym, at ../../gold/sparc.cc:391", though line 391 is > "gold_assert(this->tls_get_addr_sym_);" which is much easier to debug! I'm actually getting the following internal error when trying to build firefox on sparc64 during some rust code compilation: 1:32.84 = note: /srv/glaubitz/firefox/mozilla-central/obj-sparc64-unknown-linux-gnu/build/unix/gold/ld: internal error in sized_finalize_symbol, at ../../gold/symtab.cc:2937 1:32.84 collect2: error: ld returned 1 exit status Is this related?
(In reply to John Paul Adrian Glaubitz from comment #6) > (In reply to James Clarke from comment #4) > > Note that gold also falls foul of this, giving "gold: internal error in > > tls_get_addr_sym, at ../../gold/sparc.cc:391", though line 391 is > > "gold_assert(this->tls_get_addr_sym_);" which is much easier to debug! > > I'm actually getting the following internal error when trying to build > firefox on sparc64 during some rust code compilation: > > 1:32.84 = note: > /srv/glaubitz/firefox/mozilla-central/obj-sparc64-unknown-linux-gnu/build/ > unix/gold/ld: internal error in sized_finalize_symbol, at > ../../gold/symtab.cc:2937 > 1:32.84 collect2: error: ld returned 1 exit status > > Is this related? Possibly, but I'd expect it to trigger an assertion failure in tls_get_addr_sym before that as with my test case. I suggest you open a new bug for this (and if you have debug symbols in that build, run it under gdb and `p *sym` to see what symbol it's having issues with).
The master branch has been updated by Eric Botcazou <ebotcazou@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=e513bd38a6b91401947d90ba5f301f01d3991b8e commit e513bd38a6b91401947d90ba5f301f01d3991b8e Author: Eric Botcazou <ebotcazou@gcc.gnu.org> Date: Thu Feb 15 15:55:11 2018 +0100 PR ld/22832 on SPARC. The fix for PR ld/22727 on SPARC passed TRUE as the 'create' argument in the call to bfd_link_hash_lookup. It turns out this was a bad idea because, if the symbol is created at this point, the link will abort later in elf_link_output_extsym. This changes the TRUE into a FALSE and puts an assertion on the result of the call, making it easier to debug the issue; that's exactly in keeping with what Gold does. bfd/ * elfxx-sparc.c (_bfd_sparc_elf_check_relocs) <R_SPARC_TLS_GD_CALL>: Pass FALSE instead of TRUE as 'create' argument to bfd_link_hash_lookup and assert that the result of the call is not NULL.
The binutils-2_30-branch branch has been updated by Eric Botcazou <ebotcazou@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d31b3bc9174ca62d7527a63e6428718311faff9c commit d31b3bc9174ca62d7527a63e6428718311faff9c Author: Eric Botcazou <ebotcazou@gcc.gnu.org> Date: Thu Feb 15 15:55:11 2018 +0100 PR ld/22832 on SPARC. The fix for PR ld/22727 on SPARC passed TRUE as the 'create' argument in the call to bfd_link_hash_lookup. It turns out this was a bad idea because, if the symbol is created at this point, the link will abort later in elf_link_output_extsym. This changes the TRUE into a FALSE and puts an assertion on the result of the call, making it easier to debug the issue; that's exactly in keeping with what Gold does. bfd/ * elfxx-sparc.c (_bfd_sparc_elf_check_relocs) <R_SPARC_TLS_GD_CALL>: Pass FALSE instead of TRUE as 'create' argument to bfd_link_hash_lookup and assert that the result of the call is not NULL.
BFD adjusted, the assertion failure is now similar to that of Gold.