Created attachment 8840 [details] testcase.tar.xz, Part 1 When building webkitgtk-2.10.4: $ LD=gold/ld-new ./link gold/ld-new: internal error in relocate_tls, at ../../binutils/gold/aarch64.cc:7418
Created attachment 8841 [details] testcase.tar.xz, Part 2
Created attachment 8842 [details] testcase.tar.xz, Part 3
I hit the same assert when building LLVM's unit test on AArch64 with gold. It seems the issue is triggered when linking to a thread-local variable in dynamically linked library. Reproducer 1: $ cat reproduce_gold_crash.sh cat > gold_crash_a1.c << INPUT __thread void* tv; INPUT cat > gold_crash_b1.c << INPUT extern __thread void* tv; int main(int argc, char **argv) { tv = argv; } INPUT gcc -O2 -fPIC -rdynamic -shared -Wl,-soname,gold_crash_a1.so.1 -o libgold_crash_a1.so gold_crash_a1.c gcc -O2 -fPIC -rdynamic -o gold_crash1.exe gold_crash_b1.c -L. -lgold_crash_a1 $ PATH=$HOME/bin:$PATH ./reproduce_gold_crash.sh /home/llvm-test/bin/ld: internal error in relocate_tls, at ../../binutils-gdb/gold/aarch64.cc:7418 collect2: error: ld returned 1 exit status Reproducer 2: $ cat call_once.cpp #include <mutex> #include <stdio.h> std::once_flag flag1; int main() { std::call_once(flag1, [](){puts("Hello!\n");}); } $ PATH=$HOME/bin:$PATH g++ -O2 -fPIC -std=c++11 call_once.cpp /home/llvm-test/bin/ld: internal error in relocate_tls, at ../../binutils-gdb/gold/aarch64.cc:7418 collect2: error: ld returned 1 exit status $ PATH=$HOME/bin:$PATH ld -v GNU gold (GNU Binutils 2.26.51.20160104) 1.11 I could also reproduce this with the following Debian versions of gold: * GNU gold (GNU Binutils for Debian 2.25.1) 1.11 * GNU gold (GNU Binutils for Debian 2.25) 1.11
Hi, Kristof, I was able to reproduce case 2 (but not 1). In gold, tls_segment is never created in layout.cc, so comes the assertion. In call_once.o, there is the tls symbol _ZSt15__once_callable, however there is no sections that has bit elfcpp::SHF_TLS turned on, and tls_segment is only created if there is at least one sectoin with SHF_TLS bit. So, Cary, shall we create the tls_segment whenever the Scanner encounters a tls symbol?
(In reply to Han Shen from comment #4) > Hi, Kristof, I was able to reproduce case 2 (but not 1). > > In gold, tls_segment is never created in layout.cc, so comes the assertion. > In call_once.o, there is the tls symbol _ZSt15__once_callable, however there > is no sections that has bit elfcpp::SHF_TLS turned on, and tls_segment is > only created if there is at least one sectoin with SHF_TLS bit. > > So, Cary, shall we create the tls_segment whenever the Scanner encounters a > tls symbol? It looks like this is in relocate_tls(), in this block: case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21: case elfcpp::R_AARCH64_TLSDESC_LD64_LO12: case elfcpp::R_AARCH64_TLSDESC_ADD_LO12: case elfcpp::R_AARCH64_TLSDESC_CALL: ... if (tlsopt == tls::TLSOPT_TO_IE) { if (tls_segment == NULL) { gold_assert(parameters->errors()->error_count() > 0 || issue_undefined_symbol_error(gsym)); return aarch64_reloc_funcs::STATUS_BAD_RELOC; } return tls_desc_gd_to_ie(relinfo, target, rela, r_type, view, psymval, got_entry_address, address); } at the gold_assert() there. Is that where the assert is happening for you? Looking at tls_desc_gd_to_ie(), and comparing this with the similar case in the x86 backend, it looks to me like the insistence on having a non-NULL tls_segment here is too zealous -- the optimization from GD to IE never needs tls_segment, and it's perfectly reasonable to have a relocation to an external TLS symbol without having a TLS segment in the main executable. I think if you simply remove the "if (tls_segment == NULL) { ... }" block here, it will fix the problem.
In fact, if I compile the example for x86-64 with -mtls-dialect=gnu2, I see the same failure. In x86_64.cc, we don't check for tls_segment when optimizing R_X86_64_TLSGD to IE, but we do have a bogus check when optimizing R_X86_64_GOTPC32_TLSDESC or R_X86_64_TLSDESC_CALL. We have a similar problem in i386.cc. It looks like the aarch64.cc target simply inherited the bug from x86_64.cc.
The master branch has been updated by Cary Coutant <ccoutant@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d21f123b0ead1806416cf0dafae12bec4cca8920 commit d21f123b0ead1806416cf0dafae12bec4cca8920 Author: Cary Coutant <ccoutant@gmail.com> Date: Mon Jan 11 23:57:44 2016 -0800 Fix internal error when applying TLSDESC relocations with no TLS segment. gold/ PR gold/19353 * aarch64.cc (Target_aarch64::relocate_tls): Don't insist that we have a TLS segment for GD-to-IE optimization. * i386.cc (Target_i386::tls_gd_to_ie): Remove tls_segment parameter. Adjust all calls. (Target_i386::tls_desc_gd_to_ie): Likewise. (Target_i386::relocate_tls): Don't insist that we have a TLS segment for TLSDESC GD-to-IE optimizations. * x86_64.cc (Target_x86_64::tls_gd_to_ie): Remove tls_segment parameter. Adjust all calls. (Target_x86_64::tls_desc_gd_to_ie): Likewise. (Target_x86_64::relocate_tls): Don't insist that we have a TLS segment for TLSDESC GD-to-IE optimizations.
Fixed on trunk.