The run_ld.c test from gcc is incorrectly linked using binutils 2.30 and later with -pie. /* { dg-do run } */ /* { dg-require-effective-target tls_runtime } */ /* { dg-add-options tls } */ extern void abort (void); __thread int tls_ld __attribute__((tls_model("local-dynamic"))) = 1; __thread int tls_ld2 __attribute__((tls_model("local-dynamic"))) = 2; int get_ld (void) { return tls_ld + tls_ld2; } int *get_ldp (void) { return &tls_ld; } int main (void) { int val; val = get_ld (); if (val != 1 + 2) abort (); val = *get_ldp (); if (val != 1) abort (); return 0; } Executing on host: /home/dave/gnu/gcc/objdir/gcc/xgcc -B/home/dave/gnu/gcc/objdi r/gcc/ /home/dave/gnu/gcc/gcc/gcc/testsuite/gcc.dg/torture/tls/run-ld.c -fno -diagnostics-show-caret -fdiagnostics-color=never -O0 -pie -fPIE -ansi -pe dantic-errors -lm -o ./run-ld.exe (timeout = 300) spawn -ignore SIGHUP /home/dave/gnu/gcc/objdir/gcc/xgcc -B/home/dave/gnu/gcc/obj dir/gcc/ /home/dave/gnu/gcc/gcc/gcc/testsuite/gcc.dg/torture/tls/run-ld.c -fno-d iagnostics-show-caret -fdiagnostics-color=never -O0 -pie -fPIE -ansi -pedantic-e rrors -lm -o ./run-ld.exe PASS: gcc.dg/torture/tls/run-ld.c -O0 -pie -fPIE (test for excess errors) Setting LD_LIBRARY_PATH to :/home/dave/gnu/gcc/objdir/gcc:/home/dave/gnu/gcc/obj dir/hppa-linux-gnu/./libatomic/.libs::/home/dave/gnu/gcc/objdir/gcc:/home/dave/g nu/gcc/objdir/hppa-linux-gnu/./libatomic/.libs:/home/dave/gnu/gcc/objdir/hppa-li nux-gnu/libstdc++-v3/src/.libs:/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libssp/. libs:/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libgomp/.libs:/home/dave/gnu/gcc/o bjdir/hppa-linux-gnu/libatomic/.libs:/home/dave/gnu/gcc/objdir/./gcc:/home/dave/ gnu/gcc/objdir/./prev-gcc:/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libstdc++-v3/ src/.libs:/home/dave/gnu/gcc/objdir/hppa-linux-gnu/libssp/.libs:/home/dave/gnu/g cc/objdir/hppa-linux-gnu/libgomp/.libs:/home/dave/gnu/gcc/objdir/hppa-linux-gnu/ libatomic/.libs:/home/dave/gnu/gcc/objdir/./gcc:/home/dave/gnu/gcc/objdir/./prev -gcc Execution timeout is: 300 spawn [open ...] FAIL: gcc.dg/torture/tls/run-ld.c -O0 -pie -fPIE execution test Typical link command is: /home/dave/gnu/binutils/objdir/ld/ld-new -plugin /home/dave/gnu/gcc/objdir/gcc/liblto_plugin.so -plugin-opt=/home/dave/gnu/gcc/objdir/gcc/lto-wrapper -plugin-opt=-fresolution=run-ld.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -dynamic-linker /lib/ld.so.1 -o ./run-ld.exe /usr/lib/hppa-linux-gnu/Scrt1.o /usr/lib/hppa-linux-gnu/crti.o /home/dave/gnu/gcc/objdir/gcc/crtbeginS.o -L/home/dave/gnu/gcc/objdir/gcc -L/lib/hppa-linux-gnu -L/usr/lib/hppa-linux-gnu run-ld.o -lm -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /home/dave/gnu/gcc/objdir/gcc/crtendS.o /usr/lib/hppa-linux-gnu/crtn.o -pie As far as I can tell, the tls_ld and tls_ld2 variables are not linked correctly. When it is linked correctly, I see the following: Breakpoint 1, __GI___tls_get_addr (ti=0x41001214) at dl-tls.c:825 825 dl-tls.c: No such file or directory. (gdb) x/2x $r26 0x41001214: 0x00000001 0x00000000 (gdb) c Continuing. Breakpoint 1, __GI___tls_get_addr (ti=0x41001200) at dl-tls.c:825 825 in dl-tls.c (gdb) x/2x $r26 0x41001200: 0x00000001 0x00000004 With Debian 2.30, I see: Starting program: /home/dave/gnu/gcc/objdir/gcc/testsuite/gcc/run-ld.exe Breakpoint 1, __GI___tls_get_addr (ti=0x4100121c) at dl-tls.c:825 825 dl-tls.c: No such file or directory. (gdb) x/2x $r26 0x4100121c: 0x00000001 0x00000000 (gdb) c Continuing. Breakpoint 1, __GI___tls_get_addr (ti=0x41001208) at dl-tls.c:825 825 in dl-tls.c (gdb) x/2x $r26 0x41001208: 0x00000001 0x00000000
Created attachment 10959 [details] fix I believe this should cure the problem
Well it should have fixed the bug, but we then hit a glibc bug. R_PARISC_TLS_DTPOFF32 addend is ignored. :-( When generating an executable it is possible to omit both of R_PARISC_TLS_DTPMOD32 and R_PARISC_TLS_DTPOFF32 dynamic relocs for local tls symbols, and it's also possible to omit R_PARISC_TLS_DTPOFF32 in shared libraries for local tls symbols. So I'm going to have to implement that little optimisation for hppa..
The master branch has been updated by Alan Modra <amodra@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4352556b36ab4f1c6f81a0ac3daf4619a419558d commit 4352556b36ab4f1c6f81a0ac3daf4619a419558d Author: Alan Modra <amodra@gmail.com> Date: Thu Apr 19 11:19:35 2018 +0930 PR22978, TLS local-dynamic incorrectly linked on hppa-linux We were emitting dynamic relocs on the second word of a TLS GD GOT entry pair (the dtprel offset), without the addend necessary when no symbol is present on the dynamic reloc. Unfortunately the simple solution of providing the proper addend doesn't work due to an hppa glibc ld.so bug that ignores such addends. So instead optimize the relocs. The dtprel offset is known at link time for locally defined symbols (the only case where we'll end up with no symbol on a dynamic reloc) so we can omit the dynamic reloc in that case. Furthermore, we can omit a dynamic reloc on the first word of a TLS GD GOT entry pair (the module id) if the symbol is local and we are producing an executable. Similarly, a tprel reloc on a TLS IE GOT entry is not needed for local symbols in an executable. So the condition for TLS GOT relocs can become bfd_link_dll(info) rather than bfd_link_pic(info) as needed for normal GOT relocs. This all presumes hppa ld.so doesn't need to differentiate TLS GD GOT pairs from TLS LD GOT pairs, which is currently true. PR 22978 * elf32-hppa.c (got_relocs_needed): Add extra param to special case both dtprel and tprel relocs. (allocate_dynrelocs): Adjust conditions for got relocs. (elf32_hppa_relocate_section): Likewise for local sym got relocs. Emit dynamic relocs on TLS GOT entries for shared libraries, not when pic. Omit dynamic reloc on dtprel entry when local, and on tprel entry when local and executable.
Patch applied.