--- Comment #4 from James Clarke <jrtc27 at jrtc27 dot com> ---
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/", though line 391 is
"gold_assert(this->tls_get_addr_sym_);" which is much easier to debug!


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
000000000000000c  0000000300000010 R_SPARC_PC10           0000000000000000
0000000000000014  0000000500000038 R_SPARC_TLS_GD_HI22    0000000000000000 x +
0000000000000018  0000000500000039 R_SPARC_TLS_GD_LO10    0000000000000000 x +
000000000000001c  000000050000003a R_SPARC_TLS_GD_ADD     0000000000000000 x +
0000000000000020  000000050000003b R_SPARC_TLS_GD_CALL    0000000000000000 x +

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
     4: 0000000000000000    52 FUNC    GLOBAL DEFAULT    2 f
     5: 0000000000000000     4 TLS     GLOBAL DEFAULT    4 x
jrtc27@deb4g:~/tmp/22832$ ld -o -shared 22832.o
ld: BFD (GNU Binutils) internal error, aborting at
elflink.c:9710 in elf_link_output_extsym

ld: Please report this bug.

jrtc27@deb4g:~/tmp/22832$ gold -o -shared 22832.o
gold: internal error in tls_get_addr_sym, at ../../gold/

You are receiving this mail because:
You are on the CC list for the bug.
bug-binutils mailing list

Reply via email to