Summary: | -pie issues with TLS relocations | ||
---|---|---|---|
Product: | binutils | Reporter: | Jakub Jelinek <jakub> |
Component: | ld | Assignee: | unassigned |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | bug-binutils, drepper.fsp, hjl.tools |
Priority: | P2 | ||
Version: | unspecified | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Last reconfirmed: | ||
Bug Depends on: | |||
Bug Blocks: | 14940 | ||
Attachments: | bz6443.patch |
Description
Jakub Jelinek
2008-04-22 09:17:52 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.
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. Why does it limit to PIE? If a symbol in shared library is resolved locally, will we run into the same problem? 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. (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? 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? 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. 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. 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 Fixed. |