aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2019-07-11 22:08:39 +0930
committerAlan Modra <amodra@gmail.com>2019-07-13 09:57:50 +0930
commitf26a32876ba49b2d5537beccea2a38bc544e9732 (patch)
treed336701d832c5984d9027a6b371e9acc7c6eb772 /bfd
parent7b2438015ca87297b2796c662182f796bb5358c2 (diff)
downloadgdb-f26a32876ba49b2d5537beccea2a38bc544e9732.zip
gdb-f26a32876ba49b2d5537beccea2a38bc544e9732.tar.gz
gdb-f26a32876ba49b2d5537beccea2a38bc544e9732.tar.bz2
Dynamic TLS section symbols
It is possible to create shared libraries on PowerPC using -ftls-model=inital-exec or -ftls-model=local-exec. The first is half reasonable, getting you a shared library that can't be dlopen'd but otherwise is reasonable. The second is quite bad. Not only do you lose being able to dlopen, the library also has dynamic text relocations. Worse, the TPREL16_LO, TPREL16_HA and other TPREL16 dynamic relocs emitted were wrong, resulting in wrong values being applied by ld.so. Using the first TLS section symbol in dynamic relocations for local TLS symbols doesn't work. It's wrong because TLS symbols used by TLS relocs have values relative to the TLS segment, whereas the TLS section symbols are addresses. This patch instead uses a symbol index of zero which is used elsewhere by PowerPC on dynamic TLS relocs. It's not strictly ABI compliant to use a non-TLS symbol with TLS relocs but symbol index zero can be interpreted as "no symbol". Not using the first TLS section symbol means it doesn't need to be dynamic. The patch also fixes a further problem with PowerPC32 dynamic TPREL16* relocs, which shouldn't have the symbol value in the addend as we do for non-TLS symbols. bfd/ * elflink.c (_bfd_elf_omit_section_dynsym_default): Don't keep tls_sec. (_bfd_elf_init_1_index_section): Prefer not using TLS sections. (_bfd_elf_init_2_index_sections): Likewise. * elf64-ppc.c (ppc64_elf_relocate_section): When emitting dynamic relocations for local TLS symbols, use STN_UNDEF as the relocation symbol. * elf32-ppc.c (ppc_elf_relocate_section): Likewise, and don't leave TLS symbol value in the addend. ld/ * testsuite/ld-powerpc/tlsso.r: Update. * testsuite/ld-powerpc/tlsso32.g: Update. * testsuite/ld-powerpc/tlsso32.r: Update. * testsuite/ld-powerpc/tlstocso.r: Update. * testsuite/ld-cris/tls-dso-dtpoffd2.d: Update. * testsuite/ld-cris/tls-dso-dtpoffd4.d: Update. * testsuite/ld-cris/tls-dso-tpoffgotcomm1.d: Update. * testsuite/ld-cris/tls-gd-1.d: Update. * testsuite/ld-cris/tls-gd-1h.d: Update. * testsuite/ld-cris/tls-gd-2.d: Update. * testsuite/ld-cris/tls-gd-2h.d: Update. * testsuite/ld-cris/tls-ie-10.d: Update. * testsuite/ld-cris/tls-ie-11.d: Update. * testsuite/ld-cris/tls-ie-8.d: Update. * testsuite/ld-cris/tls-ie-9.d: Update. * testsuite/ld-cris/tls-js1.d: Update. * testsuite/ld-cris/tls-ld-4.d: Update. * testsuite/ld-cris/tls-ld-5.d: Update. * testsuite/ld-cris/tls-ld-6.d: Update. * testsuite/ld-cris/tls-ld-7.d: Update. * testsuite/ld-cris/tls-ldgd-14.d: Update. * testsuite/ld-cris/tls-ldgd-15.d: Update. * testsuite/ld-cris/tls-ldgdx-14.d: Update. * testsuite/ld-cris/tls-ldgdx-15.d: Update. * testsuite/ld-cris/tls-local-54.d: Update. * testsuite/ld-cris/tls-local-60.d: Update. * testsuite/ld-cris/tls-local-61.d: Update. * testsuite/ld-cris/tls-local-63.d: Update. * testsuite/ld-cris/tls-local-64.d: Update. * testsuite/ld-cris/tls-ok-30.d: Update. * testsuite/ld-cris/tls-ok-32.d: Update. * testsuite/ld-cris/tls-ok-34.d: Update. * testsuite/ld-mips-elf/tls-multi-got-1.got: Update. * testsuite/ld-mips-elf/tls-multi-got-1.r: Update. * testsuite/ld-mips-elf/tlsdyn-pie-o32.d: Update. * testsuite/ld-mips-elf/tlsdyn-pie-o32.got: Update. * testsuite/ld-mips-elf/tlslib-o32-hidden.got: Update. * testsuite/ld-mips-elf/tlslib-o32-ver.got: Update. * testsuite/ld-mips-elf/tlslib-o32.got: Update. * testsuite/ld-s390/tlspic.rd: Update. * testsuite/ld-s390/tlspic_64.rd: Update. * testsuite/ld-sparc/tlssunnopic32.rd: Update. * testsuite/ld-sparc/tlssunnopic64.rd: Update. * testsuite/ld-sparc/tlssunpic32.rd: Update. * testsuite/ld-sparc/tlssunpic64.rd: Update.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog12
-rw-r--r--bfd/elf32-ppc.c28
-rw-r--r--bfd/elf64-ppc.c39
-rw-r--r--bfd/elflink.c31
4 files changed, 74 insertions, 36 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7daec6b..b41c059 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,15 @@
+2019-07-13 Alan Modra <amodra@gmail.com>
+
+ * elflink.c (_bfd_elf_omit_section_dynsym_default): Don't keep
+ tls_sec.
+ (_bfd_elf_init_1_index_section): Prefer not using TLS sections.
+ (_bfd_elf_init_2_index_sections): Likewise.
+ * elf64-ppc.c (ppc64_elf_relocate_section): When emitting dynamic
+ relocations for local TLS symbols, use STN_UNDEF as the relocation
+ symbol.
+ * elf32-ppc.c (ppc_elf_relocate_section): Likewise, and don't
+ leave TLS symbol value in the addend.
+
2019-07-08 Alan Modra <amodra@gmail.com>
PR 24785
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index ae03d72..33ab4e0 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -8209,19 +8209,27 @@ ppc_elf_relocate_section (bfd *output_bfd,
but ld.so expects buggy relocs.
FIXME: Why not always use a zero index? */
osec = sec->output_section;
- indx = elf_section_data (osec)->dynindx;
- if (indx == 0)
+ if ((osec->flags & SEC_THREAD_LOCAL) != 0)
+ {
+ osec = htab->elf.tls_sec;
+ indx = 0;
+ }
+ else
{
- osec = htab->elf.text_index_section;
indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ {
+ osec = htab->elf.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
}
- BFD_ASSERT (indx != 0);
-#ifdef DEBUG
- if (indx == 0)
- printf ("indx=%ld section=%s flags=%08x name=%s\n",
- indx, osec->name, osec->flags,
- h->root.root.string);
-#endif
+
+ /* ld.so doesn't expect buggy TLS relocs.
+ Don't leave the symbol value in the
+ addend for them. */
+ if (IS_PPC_TLS_RELOC (r_type))
+ outrel.r_addend -= osec->vma;
}
outrel.r_info = ELF32_R_INFO (indx, r_type);
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index c5c18d0..d77cfdf 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -15891,21 +15891,38 @@ ppc64_elf_relocate_section (bfd *output_bfd,
}
else
{
- asection *osec;
+ asection *osec = sec->output_section;
- osec = sec->output_section;
- indx = elf_section_data (osec)->dynindx;
-
- if (indx == 0)
+ if ((osec->flags & SEC_THREAD_LOCAL) != 0)
+ {
+ /* TLS symbol values are relative to the
+ TLS segment. Dynamic relocations for
+ local TLS symbols therefore can't be
+ reduced to a relocation against their
+ section symbol because it holds the
+ address of the section, not a value
+ relative to the TLS segment. We could
+ change the .tdata dynamic section symbol
+ to be zero value but STN_UNDEF works
+ and is used elsewhere, eg. for TPREL64
+ GOT relocs against local TLS symbols. */
+ osec = htab->elf.tls_sec;
+ indx = 0;
+ }
+ else
{
- if ((osec->flags & SEC_READONLY) == 0
- && htab->elf.data_index_section != NULL)
- osec = htab->elf.data_index_section;
- else
- osec = htab->elf.text_index_section;
indx = elf_section_data (osec)->dynindx;
+ if (indx == 0)
+ {
+ if ((osec->flags & SEC_READONLY) == 0
+ && htab->elf.data_index_section != NULL)
+ osec = htab->elf.data_index_section;
+ else
+ osec = htab->elf.text_index_section;
+ indx = elf_section_data (osec)->dynindx;
+ }
+ BFD_ASSERT (indx != 0);
}
- BFD_ASSERT (indx != 0);
/* We are turning this relocation into one
against a section symbol, so subtract out
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 02ea2dc..d146a4b 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -900,9 +900,6 @@ _bfd_elf_omit_section_dynsym_default (bfd *output_bfd ATTRIBUTE_UNUSED,
SHT_PROGBITS/SHT_NOBITS. */
case SHT_NULL:
htab = elf_hash_table (info);
- if (p == htab->tls_sec)
- return FALSE;
-
if (htab->text_index_section != NULL)
return p != htab->text_index_section && p != htab->data_index_section;
@@ -7052,14 +7049,17 @@ void
_bfd_elf_init_1_index_section (bfd *output_bfd, struct bfd_link_info *info)
{
asection *s;
+ asection *found = NULL;
for (s = output_bfd->sections; s != NULL; s = s->next)
if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
&& !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
{
- elf_hash_table (info)->text_index_section = s;
- break;
+ found = s;
+ if ((s->flags & SEC_THREAD_LOCAL) == 0)
+ break;
}
+ elf_hash_table (info)->text_index_section = found;
}
/* Find two non-excluded output sections, one for code, one for data.
@@ -7068,29 +7068,30 @@ void
_bfd_elf_init_2_index_sections (bfd *output_bfd, struct bfd_link_info *info)
{
asection *s;
+ asection *found = NULL;
/* Data first, since setting text_index_section changes
_bfd_elf_omit_section_dynsym_default. */
for (s = output_bfd->sections; s != NULL; s = s->next)
- if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY)) == SEC_ALLOC)
+ if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
+ && !(s->flags & SEC_READONLY)
&& !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
{
- elf_hash_table (info)->data_index_section = s;
- break;
+ found = s;
+ if ((s->flags & SEC_THREAD_LOCAL) == 0)
+ break;
}
+ elf_hash_table (info)->data_index_section = found;
for (s = output_bfd->sections; s != NULL; s = s->next)
- if (((s->flags & (SEC_EXCLUDE | SEC_ALLOC | SEC_READONLY))
- == (SEC_ALLOC | SEC_READONLY))
+ if ((s->flags & (SEC_EXCLUDE | SEC_ALLOC)) == SEC_ALLOC
+ && (s->flags & SEC_READONLY)
&& !_bfd_elf_omit_section_dynsym_default (output_bfd, info, s))
{
- elf_hash_table (info)->text_index_section = s;
+ found = s;
break;
}
-
- if (elf_hash_table (info)->text_index_section == NULL)
- elf_hash_table (info)->text_index_section
- = elf_hash_table (info)->data_index_section;
+ elf_hash_table (info)->text_index_section = found;
}
bfd_boolean