Bug 17057

Summary: Production of DSOs using TLSDESC is utterly broken on i386
Product: binutils Reporter: Rich Felker <bugdal>
Component: ldAssignee: H.J. Lu <hjl.tools>
Status: RESOLVED FIXED    
Severity: normal CC: amonakov
Priority: P2    
Version: 2.25   
Target Milestone: 2.25   
See Also: https://sourceware.org/bugzilla/show_bug.cgi?id=17117
Host: Target:
Build: Last reconfirmed:

Description Rich Felker 2014-06-15 03:30:12 UTC
Attempting to compile/link the following program:

__thread int my_tls = 1;
int *my_tls_addr() { return &my_tls; }

with the following gcc command line:

gcc -shared -mtls-dialect=gnu2 -fPIC -o foo.so foo.c

results in the following error message (details vary by version; I also tried two different builds of 2.24, my own and Debian's):

/usr/bin/ld: BFD (GNU Binutils) 2.23.2 assertion fail elf32-i386.c:3922

The problem seems to be a miscomputation of the size of .got.plt needed for the TLSDESC entries. Incidentally, if there are no PLT entries at all (this can be achieved with the above program by -nostartfiles), the error goes away, but the resulting DSO is unusable; it contains no DT_JMPREL in the DYNAMIC, so TLSDESC relocations don't happen and naturally this results in a crash when the program attempts to access the TLS.

Is this code completely untested? I can't seem to figure out how to produce any usable/testable TLSDESC-using DSO.
Comment 1 H.J. Lu 2014-07-15 17:26:58 UTC
*** Bug 17117 has been marked as a duplicate of this bug. ***
Comment 2 H.J. Lu 2014-07-15 17:33:12 UTC
A self-contained testcase:

[hjl@gnu-6 pr17057]$ cat x.c 
__thread int my_tls = 1;
int *my_tls_addr() { return &my_tls; }
[hjl@gnu-6 pr17057]$ cat y.c 
extern void foo (void);

void
bar (void)
{
  foo ();
}
[hjl@gnu-6 pr17057]$ gcc -fPIC -m32 y.c -c -O2 x.c -mtls-dialect=gnu2
[hjl@gnu-6 pr17057]$ ld  -m elf_i386 -shared -o x.so y.o  x.o
ld: BFD (Linux/GNU Binutils) 2.24.51.0.4.20140708 assertion fail /net/gnu-6/export/linux/src/binutils/binutils/bfd/elf32-i386.c:4035
[hjl@gnu-6 pr17057]$
Comment 3 Sourceware Commits 2014-07-15 20:16:02 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gdb and binutils".

The branch, master has been updated
       via  998d811a23ca3f2c463dfaf40259486ff9958244 (commit)
      from  41e995687391695e16550eb9c18da8e5d0dcffa9 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=998d811a23ca3f2c463dfaf40259486ff9958244

commit 998d811a23ca3f2c463dfaf40259486ff9958244
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Jul 15 13:09:55 2014 -0700

    Update elf_i386_compute_jump_table_size
    
    Commit e1f987424b7b3f5ac63a2a6ae044a202a44b8ff8 changed how
    next_tls_desc_index was set up.  This patch updates
    elf_i386_compute_jump_table_size to use elf.srelplt->reloc_count
    instead of next_tls_desc_index.
    
    bfd/
    
    	PR ld/17057
    	* elf32-i386.c (elf_i386_compute_jump_table_size): Replace
    	next_tls_desc_index with elf.srelplt->reloc_count.
    
    ld/testsuite/
    
    	PR ld/17057
    	* ld-i386/i386.exp: Run pr17057.
    	* ld-i386/pr17057.d: New file.
    	* ld-i386/pr17057.s: Likewise.

-----------------------------------------------------------------------

Summary of changes:
 bfd/ChangeLog                  |    6 ++++++
 bfd/elf32-i386.c               |    2 +-
 ld/testsuite/ChangeLog         |    7 +++++++
 ld/testsuite/ld-i386/i386.exp  |    1 +
 ld/testsuite/ld-i386/pr17057.d |    9 +++++++++
 ld/testsuite/ld-i386/pr17057.s |    3 +++
 6 files changed, 27 insertions(+), 1 deletions(-)
 create mode 100644 ld/testsuite/ld-i386/pr17057.d
 create mode 100644 ld/testsuite/ld-i386/pr17057.s
Comment 4 H.J. Lu 2014-07-15 20:16:45 UTC
Fixed.