Bug 6443 - -pie issues with TLS relocations
Summary: -pie issues with TLS relocations
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks: 14940
  Show dependency treegraph
 
Reported: 2008-04-22 09:17 UTC by Jakub Jelinek
Modified: 2012-12-10 13:08 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
bz6443.patch (839 bytes, patch)
2008-04-22 09:23 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2008-04-22 09:17:52 UTC
__thread int a;
__thread int b __attribute((tls_model ("local-exec")));
__thread int c __attribute((tls_model ("initial-exec")));
__thread int d __attribute((tls_model ("local-dynamic")));
__thread int e __attribute((tls_model ("global-dynamic")));

int
main (void)
{
  return a + b + c + d + e;
}

compiled/linked with -O2 -pie -fpie on various arches either doesn't link at all,
or makes completely unnecessarily a DT_TEXTREL PIE.  Tried x86_64, i386, ppc,
ppc64.  For the TLS transitions and relocations, PIEs should be handled like
other executables, so many info->shared checks need to be replaced with
!info->executable.  For the TLS relocations, even when the executable is
position independent, the offsets within the PIE's TLS block are known at link
time and so relocations like R_X86_64_TPOFF32 can be relocated fully at link
time.
Comment 1 Jakub Jelinek 2008-04-22 09:23:43 UTC
Created attachment 2715 [details]
bz6443.patch

Attached is just very lightly tested x86_64 set of changes, but i386, ppc,
ppc64 and other arches need similar changes.  For now glibc will use a
workaround, but it would be good to have this fixed soon.
Comment 2 Alan Modra 2008-04-22 16:10:46 UTC
I'll take a look at ppc.  The obvious change doesn't help much as enabling
ppc_elf_tls_optimize for pie results in us hitting the bfd_error_bad_value at
elf32-ppc.c:6577 when we try to make a dynamic reloc for the edited LD->LE tls
reloc.  That is, if you use an old enough compiler.

gcc 4.2 and later reschedule the tls sequences and ppc_elf_tls_optimize gives
up.  We really need some way of tying together relocs on arg setup for
__tls_get_addr and the call to __tls_get_addr itself.  One way that occurred to
me is to emit a call to the tls variable involved instead of __tls_get_addr, and
of course restore the real call in the linker.  eg. instead of

  addi 3,30,foo@got@tlsld
  bl __tls_get_addr

emit

  addi 3,30,foo@got@tlsld
  bl foo

This would allow the linker to edit the sequence as the tls symbol foo on both
relocs ties things together.  A real call to a tls symbol can't happen, so all
bl some_tls_symbol means bl __tls_get_addr.  Unfortunately this is an ABI change.

Alternatively, disable scheduling of tls sequences involving __tls_get_addr in gcc.
Comment 3 H.J. Lu 2008-04-24 13:00:02 UTC
Why does it limit to PIE? If a symbol in shared library is resolved locally,
will we run into the same problem?
Comment 4 Jakub Jelinek 2008-04-24 13:11:40 UTC
The important thing is that executables and PIEs are always the first in the
symbol search scope, so the linker can compute the offsets within the TLS block
at runtime.  For shared libraries you can't do that, as you don't know how big
the executable or PIE's TLS block will be, what alignment will it need etc.,
so for those you need a runtime relocation.

If gcc on ppc/ppc64 reschedules insns and violates the TLS ABI, then it should
be fixed.  E.g. on i?86/x86_64 we use multiple asm insns in one define_insn
to make sure that something that must be kept consecutive isn't scattered around.
See e.g. tls_global_dynamic_64, tls_local_dynamic_base_64,
tls_global_dynamic_32_gnu etc. in i386.md.

But for fixing this particular bug you could perhaps leave out the local-dynamic
and global-dynamic in the testcase, that was added just for completeness.
Comment 5 H.J. Lu 2008-04-24 13:25:11 UTC
(In reply to comment #4)
> The important thing is that executables and PIEs are always the first in the
> symbol search scope, so the linker can compute the offsets within the TLS block
> at runtime.  For shared libraries you can't do that, as you don't know how big
> the executable or PIE's TLS block will be, what alignment will it need etc.,
> so for those you need a runtime relocation.
> 

Can you add those comments in your patch? Also please add a testcase
for each change. Your testcase only shows R_X86_64_TPOFF32 is affected. But
your proposed change affects many other TLS relocations. Are they really
necessary?
Comment 6 H.J. Lu 2008-04-24 13:31:54 UTC
Will this patch

--- elf64-x86-64.c.pie  2008-04-24 06:05:36.000000000 -0700
+++ elf64-x86-64.c      2008-04-24 06:29:08.000000000 -0700
@@ -1050,7 +1050,7 @@ elf64_x86_64_check_relocs (bfd *abfd, st
          goto create_got;
 
        case R_X86_64_TPOFF32:
-         if (info->shared)
+         if (!info->executable)
            {
              (*_bfd_error_handler)
                (_("%B: relocation %s against `%s' can not be used when making a
shared object; recompile with -fPIC"),
@@ -3211,7 +3211,7 @@ elf64_x86_64_relocate_section (bfd *outp
          break;
 
        case R_X86_64_TPOFF32:
-         BFD_ASSERT (! info->shared);
+         BFD_ASSERT (info->executable);
          relocation = tpoff (info, relocation);
          break;
 

be enough for x86-64?
Comment 7 Jakub Jelinek 2008-04-24 13:46:48 UTC
That's certainly not enough, see the testcase I've provided.  There are various
relocations:
0000000000000003  0000000b00000016 R_X86_64_GOTTPOFF      0000000000000008 c +
fffffffffffffffc
000000000000000c  0000000c00000017 R_X86_64_TPOFF32       0000000000000000 a + 0
0000000000000014  0000000d00000017 R_X86_64_TPOFF32       0000000000000004 b + 0
000000000000001e  0000000e00000014 R_X86_64_TLSLD         000000000000000c d +
fffffffffffffffc
0000000000000023  0000000f00000004 R_X86_64_PLT32         0000000000000000
__tls_get_addr + fffffffffffffffc
0000000000000029  0000000e00000015 R_X86_64_DTPOFF32      000000000000000c d + 0
0000000000000031  0000001000000013 R_X86_64_TLSGD         0000000000000010 e +
fffffffffffffffc
0000000000000039  0000000f00000004 R_X86_64_PLT32         0000000000000000
__tls_get_addr + fffffffffffffffc
and all of them can and should be in a PIE transitioned to the fastest,
local-exec, ones, as all resolve to a symbol within the PIE.
Comment 8 H.J. Lu 2008-04-24 13:56:26 UTC
Subject: Re:  -pie issues with TLS relocations

On Thu, Apr 24, 2008 at 6:46 AM, jakub at redhat dot com
<sourceware-bugzilla@sourceware.org> wrote:
>
>  ------- Additional Comments From jakub at redhat dot com  2008-04-24 13:46 -------
>  That's certainly not enough, see the testcase I've provided.  There are various
>  relocations:
>  0000000000000003  0000000b00000016 R_X86_64_GOTTPOFF      0000000000000008 c +
>  fffffffffffffffc
>  000000000000000c  0000000c00000017 R_X86_64_TPOFF32       0000000000000000 a + 0
>  0000000000000014  0000000d00000017 R_X86_64_TPOFF32       0000000000000004 b + 0
>  000000000000001e  0000000e00000014 R_X86_64_TLSLD         000000000000000c d +
>  fffffffffffffffc
>  0000000000000023  0000000f00000004 R_X86_64_PLT32         0000000000000000
>  __tls_get_addr + fffffffffffffffc
>  0000000000000029  0000000e00000015 R_X86_64_DTPOFF32      000000000000000c d + 0
>  0000000000000031  0000001000000013 R_X86_64_TLSGD         0000000000000010 e +
>  fffffffffffffffc
>  0000000000000039  0000000f00000004 R_X86_64_PLT32         0000000000000000
>  __tls_get_addr + fffffffffffffffc
>  and all of them can and should be in a PIE transitioned to the fastest,
>  local-exec, ones, as all resolve to a symbol within the PIE.
>

Please add testcases to your patch to make sure that only necessary changes
are included.
Comment 9 cvs-commit@gcc.gnu.org 2009-08-02 23:56:01 UTC
Subject: Bug 6443

CVSROOT:	/cvs/src
Module name:	src
Changes by:	hjl@sourceware.org	2009-08-02 23:55:50

Modified files:
	bfd            : ChangeLog elf32-i386.c elf64-x86-64.c 
	ld/testsuite   : ChangeLog 
	ld/testsuite/ld-i386: i386.exp 
	ld/testsuite/ld-x86-64: x86-64.exp 
Added files:
	ld/testsuite/ld-i386: tlspie1.d tlspie1.s 
	ld/testsuite/ld-x86-64: tlspie1.d tlspie1.s 

Log message:
	2009-08-02  H.J. Lu  <hongjiu.lu@intel.com>
	Jakub Jelinek  <jakub@redhat.com>
	
	PR ld/6443
	* elf32-i386.c (elf_i386_tls_transition): Check executable
	instead of shared for TLS when building PIE.
	(elf_i386_check_relocs): Likewise.
	(elf_i386_allocate_dynrelocs): Likewise.
	(elf_i386_relocate_section): Likewise.
	
	* elf64-x86-64.c (elf64_x86_64_tls_transition): Check executable
	instead of shared for TLS when building PIE.
	(elf64_x86_64_check_relocs): Likewise.
	(elf64_x86_64_allocate_dynrelocs): Likewise.
	(elf64_x86_64_relocate_section): Likewise.
	
	ld/testsuite/
	
	2009-08-02  H.J. Lu  <hongjiu.lu@intel.com>
	
	PR ld/6443
	* ld-i386/i386.exp: Run tlspie1.
	* ld-x86-64/x86-64.exp: tlspie1.
	
	* ld-i386/tlspie1.d: New.
	* ld-i386/tlspie1.s: Likewise.
	* ld-x86-64/tlspie1.d: Likewise.
	* ld-x86-64/tlspie1.s: Likewise.

Patches:
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/bfd/ChangeLog.diff?cvsroot=src&r1=1.4712&r2=1.4713
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/bfd/elf32-i386.c.diff?cvsroot=src&r1=1.220&r2=1.221
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/bfd/elf64-x86-64.c.diff?cvsroot=src&r1=1.180&r2=1.181
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/ld/testsuite/ChangeLog.diff?cvsroot=src&r1=1.1139&r2=1.1140
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-i386/tlspie1.d.diff?cvsroot=src&r1=NONE&r2=1.1
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-i386/tlspie1.s.diff?cvsroot=src&r1=NONE&r2=1.1
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-i386/i386.exp.diff?cvsroot=src&r1=1.26&r2=1.27
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-x86-64/tlspie1.d.diff?cvsroot=src&r1=NONE&r2=1.1
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-x86-64/tlspie1.s.diff?cvsroot=src&r1=NONE&r2=1.1
http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/ld/testsuite/ld-x86-64/x86-64.exp.diff?cvsroot=src&r1=1.13&r2=1.14

Comment 10 H.J. Lu 2010-03-17 13:22:16 UTC
Fixed.