aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-ppc.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2017-07-29 12:33:35 +0930
committerAlan Modra <amodra@gmail.com>2017-07-29 13:02:27 +0930
commit8b5f1ed8777df405f3c7b87472b1506f5125aebe (patch)
treefe5af9f4c9fd47c2ee17365ddc456e86661f0f47 /bfd/elf64-ppc.c
parentef080e7ed4a373037231e709bfa1a909f4eae0f9 (diff)
downloadgdb-8b5f1ed8777df405f3c7b87472b1506f5125aebe.zip
gdb-8b5f1ed8777df405f3c7b87472b1506f5125aebe.tar.gz
gdb-8b5f1ed8777df405f3c7b87472b1506f5125aebe.tar.bz2
PR 21847, Don't default PowerPC64 to --plt-localentry
The big comment in ppc64_elf_tls_setup says why. I've also added some code to the bfd linker that catches the -lpthread -lc symbol differences and disable generation of optimized call stubs even when --plt-localentry is activated. Gold doesn't yet have that. PR 21847 bfd/ * elf64-ppc.c (struct ppc_link_hash_entry): Add non_zero_localentry. (ppc64_elf_merge_symbol): Set non_zero_localentry. (is_elfv2_localentry0): Test non_zero_localentry. (ppc64_elf_tls_setup): Default to --no-plt-localentry. gold/ * powerpc.cc (Target_powerpc::scan_relocs): Default to --no-plt-localentry. ld/ * ld.texinfo (plt-localentry): Document.
Diffstat (limited to 'bfd/elf64-ppc.c')
-rw-r--r--bfd/elf64-ppc.c27
1 files changed, 23 insertions, 4 deletions
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index cc0e8ee..5f3c79f 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -4013,6 +4013,10 @@ struct ppc_link_hash_entry
with non-standard calling convention. */
unsigned int save_res:1;
+ /* Set if a duplicate symbol with non-zero localentry is detected,
+ even when the duplicate symbol does not provide a definition. */
+ unsigned int non_zero_localentry:1;
+
/* Contexts in which symbol is used in the GOT (or TOC).
TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the
corresponding relocs are encountered during check_relocs.
@@ -5021,7 +5025,7 @@ ppc64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
static bfd_boolean
ppc64_elf_merge_symbol (struct elf_link_hash_entry *h,
- const Elf_Internal_Sym *isym ATTRIBUTE_UNUSED,
+ const Elf_Internal_Sym *isym,
asection **psec ATTRIBUTE_UNUSED,
bfd_boolean newdef ATTRIBUTE_UNUSED,
bfd_boolean olddef ATTRIBUTE_UNUSED,
@@ -5029,6 +5033,8 @@ ppc64_elf_merge_symbol (struct elf_link_hash_entry *h,
const asection *oldsec ATTRIBUTE_UNUSED)
{
((struct ppc_link_hash_entry *) h)->fake = 0;
+ if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0)
+ ((struct ppc_link_hash_entry *) h)->non_zero_localentry = 1;
return TRUE;
}
@@ -6335,6 +6341,7 @@ is_elfv2_localentry0 (struct elf_link_hash_entry *h)
&& h->type == STT_FUNC
&& h->root.type == bfd_link_hash_defined
&& (STO_PPC64_LOCAL_MASK & h->other) == 0
+ && !((struct ppc_link_hash_entry *) h)->non_zero_localentry
&& is_ppc64_elf (h->root.u.def.section->owner)
&& abiversion (h->root.u.def.section->owner) >= 2);
}
@@ -8349,10 +8356,22 @@ ppc64_elf_tls_setup (struct bfd_link_info *info)
else if (!htab->do_multi_toc)
htab->params->no_multi_toc = 1;
+ /* Default to --no-plt-localentry, as this option can cause problems
+ with symbol interposition. For example, glibc libpthread.so and
+ libc.so duplicate many pthread symbols, with a fallback
+ implementation in libc.so. In some cases the fallback does more
+ work than the pthread implementation. __pthread_condattr_destroy
+ is one such symbol: the libpthread.so implementation is
+ localentry:0 while the libc.so implementation is localentry:8.
+ An app that "cleverly" uses dlopen to only load necessary
+ libraries at runtime may omit loading libpthread.so when not
+ running multi-threaded, which then results in the libc.so
+ fallback symbols being used and ld.so complaining. Now there
+ are workarounds in ld (see non_zero_localentry) to detect the
+ pthread situation, but that may not be the only case where
+ --plt-localentry can cause trouble. */
if (htab->params->plt_localentry0 < 0)
- htab->params->plt_localentry0
- = elf_link_hash_lookup (&htab->elf, "GLIBC_2.26",
- FALSE, FALSE, FALSE) != NULL;
+ htab->params->plt_localentry0 = 0;
htab->tls_get_addr = ((struct ppc_link_hash_entry *)
elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",