[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug ld/23825] Linker creates COPY relocs for reference to TLS symbols
From: |
wilson at gcc dot gnu.org |
Subject: |
[Bug ld/23825] Linker creates COPY relocs for reference to TLS symbols |
Date: |
Sun, 01 Sep 2019 03:50:27 +0000 |
https://sourceware.org/bugzilla/show_bug.cgi?id=23825
--- Comment #3 from Jim Wilson <wilson at gcc dot gnu.org> ---
I got an internal bug report with a simplified testcase related to this, took
another look, and found the problem.
hifiveu017:1097$ cat tmp.c
#include <stdio.h>
extern __thread int a;
int main (void) {printf ("a = %d\n", a); return 0; }
hifiveu017:1097$ cat tmp2.c
__thread int a = 10;
hifiveu017:1098$ gcc --shared -fpic -o libtmp.so tmp2.c
hifiveu017:1099$ gcc tmp.c libtmp.so -Wl,--rpath=`pwd`
hifiveu017:1100$ ./a.out
Segmentation fault (core dumped)
hifiveu017:1101$
Running objdump on a.out, we see
15 .tdata 00000004 0000000000011df8 0000000000011df8 00000df8 2**2
ALLOC, THREAD_LOCAL
16 .preinit_array 00000008 0000000000011df8 0000000000011df8 00000df8 2**0
CONTENTS, ALLOC, LOAD, DATA
So the problem here is that tdata has a size, and is alloc, but the next
section preinit_array starts at the same address as tdata which is wrong.
I tracked this down a bit of code in ld/ldlang.c which does
/* .tbss sections effectively have zero size. */
if (!IS_TBSS (os->bfd_section)
|| bfd_link_relocatable (&link_info))
dotdelta = TO_ADDR (os->bfd_section->size);
else
dotdelta = 0;
dot += dotdelta;
This may be right for .tbss, but is not right for the RISC-V .tdata section.
The RISC-V .tdata section ended up this way because we have code in
bfd/elfnn-riscv.c that does
htab->sdyntdata =
bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
(SEC_ALLOC | SEC_THREAD_LOCAL
| SEC_LINKER_CREATED));
So if there is a .tdata.dyn section and no .tdata section, .tdata.dyn gets
merged into .tdata and .tdata ends up looking like a .tbss section and gets
handled wrong by the linker.
There is also a second problem here, which is that a bss-like section can only
work at the end of a segment, but there is no code in the linker script to
ensure that .tdata.dyn ends up at the end of a segment. It is is just mixed in
with the other .tdata.* sections, with no guarantee that it is the last one.
I think the solution to this is to just claim that .tdata.dyn has contents, to
ensure that space is allocated for it. Normally, it is only used as a target
for copy relocs, and hence has no contents, but this causes multiple problems.
This section will normally be small, so I don't think there is much performance
loss from just pretending that it has contents. I have a patch that does this,
and it fixes my testcase, and elf/tst-tls12 from glibc.
--
You are receiving this mail because:
You are on the CC list for the bug.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Bug ld/23825] Linker creates COPY relocs for reference to TLS symbols,
wilson at gcc dot gnu.org <=