Nick Clifton 3edb85
diff -rup binutils.orig/bfd/elf64-ppc.c binutils-2.29/bfd/elf64-ppc.c
Nick Clifton 3edb85
--- binutils.orig/bfd/elf64-ppc.c	2017-07-31 10:48:13.642980052 +0100
Nick Clifton 3edb85
+++ binutils-2.29/bfd/elf64-ppc.c	2017-07-31 10:48:37.386711582 +0100
Nick Clifton 3edb85
@@ -4010,6 +4010,10 @@ struct ppc_link_hash_entry
Nick Clifton 3edb85
      with non-standard calling convention.  */
Nick Clifton 3edb85
   unsigned int save_res:1;
Nick Clifton 3edb85
 
Nick Clifton 3edb85
+  /* Set if a duplicate symbol with non-zero localentry is detected,
Nick Clifton 3edb85
+     even when the duplicate symbol does not provide a definition.  */
Nick Clifton 3edb85
+  unsigned int non_zero_localentry:1;
Nick Clifton 3edb85
+
Nick Clifton 3edb85
   /* Contexts in which symbol is used in the GOT (or TOC).
Nick Clifton 3edb85
      TLS_GD .. TLS_EXPLICIT bits are or'd into the mask as the
Nick Clifton 3edb85
      corresponding relocs are encountered during check_relocs.
Nick Clifton 3edb85
@@ -5018,7 +5022,7 @@ ppc64_elf_merge_symbol_attribute (struct
Nick Clifton 3edb85
 
Nick Clifton 3edb85
 static bfd_boolean
Nick Clifton 3edb85
 ppc64_elf_merge_symbol (struct elf_link_hash_entry *h,
Nick Clifton 3edb85
-			const Elf_Internal_Sym *isym ATTRIBUTE_UNUSED,
Nick Clifton 3edb85
+			const Elf_Internal_Sym *isym,
Nick Clifton 3edb85
 			asection **psec ATTRIBUTE_UNUSED,
Nick Clifton 3edb85
 			bfd_boolean newdef ATTRIBUTE_UNUSED,
Nick Clifton 3edb85
 			bfd_boolean olddef ATTRIBUTE_UNUSED,
Nick Clifton 3edb85
@@ -5026,6 +5030,8 @@ ppc64_elf_merge_symbol (struct elf_link_
Nick Clifton 3edb85
 			const asection *oldsec ATTRIBUTE_UNUSED)
Nick Clifton 3edb85
 {
Nick Clifton 3edb85
   ((struct ppc_link_hash_entry *) h)->fake = 0;
Nick Clifton 3edb85
+  if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0)
Nick Clifton 3edb85
+    ((struct ppc_link_hash_entry *) h)->non_zero_localentry = 1;
Nick Clifton 3edb85
   return TRUE;
Nick Clifton 3edb85
 }
Nick Clifton 3edb85
 
Nick Clifton 3edb85
@@ -6332,6 +6338,7 @@ is_elfv2_localentry0 (struct elf_link_ha
Nick Clifton 3edb85
 	  && h->type == STT_FUNC
Nick Clifton 3edb85
 	  && h->root.type == bfd_link_hash_defined
Nick Clifton 3edb85
 	  && (STO_PPC64_LOCAL_MASK & h->other) == 0
Nick Clifton 3edb85
+	  && !((struct ppc_link_hash_entry *) h)->non_zero_localentry
Nick Clifton 3edb85
 	  && is_ppc64_elf (h->root.u.def.section->owner)
Nick Clifton 3edb85
 	  && abiversion (h->root.u.def.section->owner) >= 2);
Nick Clifton 3edb85
 }
Nick Clifton 3edb85
@@ -8346,10 +8353,28 @@ ppc64_elf_tls_setup (struct bfd_link_inf
Nick Clifton 3edb85
   else if (!htab->do_multi_toc)
Nick Clifton f93f25
     htab->params->no_multi_toc = 1;
Nick Clifton f93f25
 
Nick Clifton 3edb85
+  /* Default to --no-plt-localentry, as this option can cause problems
Nick Clifton 3edb85
+     with symbol interposition.  For example, glibc libpthread.so and
Nick Clifton 3edb85
+     libc.so duplicate many pthread symbols, with a fallback
Nick Clifton 3edb85
+     implementation in libc.so.  In some cases the fallback does more
Nick Clifton 3edb85
+     work than the pthread implementation.  __pthread_condattr_destroy
Nick Clifton 3edb85
+     is one such symbol: the libpthread.so implementation is
Nick Clifton 3edb85
+     localentry:0 while the libc.so implementation is localentry:8.
Nick Clifton 3edb85
+     An app that "cleverly" uses dlopen to only load necessary
Nick Clifton 3edb85
+     libraries at runtime may omit loading libpthread.so when not
Nick Clifton 3edb85
+     running multi-threaded, which then results in the libc.so
Nick Clifton 3edb85
+     fallback symbols being used and ld.so complaining.  Now there
Nick Clifton 3edb85
+     are workarounds in ld (see non_zero_localentry) to detect the
Nick Clifton 3edb85
+     pthread situation, but that may not be the only case where
Nick Clifton 3edb85
+     --plt-localentry can cause trouble.  */
Nick Clifton f93f25
   if (htab->params->plt_localentry0 < 0)
Nick Clifton f93f25
-    htab->params->plt_localentry0
Nick Clifton f93f25
-      = elf_link_hash_lookup (&htab->elf, "GLIBC_2.26",
Nick Clifton f93f25
-			      FALSE, FALSE, FALSE) != NULL;
Nick Clifton f93f25
+    htab->params->plt_localentry0 = 0;
Nick Clifton 3edb85
+  if (htab->params->plt_localentry0
Nick Clifton 3edb85
+      && elf_link_hash_lookup (&htab->elf, "GLIBC_2.26",
Nick Clifton 3edb85
+			       FALSE, FALSE, FALSE) == NULL)
Nick Clifton 3edb85
+    info->callbacks->einfo
Nick Clifton 3edb85
+      (_("%P: warning: --plt-localentry is especially dangerous without "
Nick Clifton 3edb85
+	 "ld.so support to detect ABI violations.\n"));
Nick Clifton f93f25
 
Nick Clifton f93f25
   htab->tls_get_addr = ((struct ppc_link_hash_entry *)
Nick Clifton f93f25
 			elf_link_hash_lookup (&htab->elf, ".__tls_get_addr",
Nick Clifton 3edb85
diff -rup binutils.orig/gold/powerpc.cc binutils-2.29/gold/powerpc.cc
Nick Clifton 3edb85
--- binutils.orig/gold/powerpc.cc	2017-07-31 10:48:13.621980289 +0100
Nick Clifton 3edb85
+++ binutils-2.29/gold/powerpc.cc	2017-07-31 10:48:37.387711571 +0100
Nick Clifton 3edb85
@@ -7660,8 +7660,10 @@ Target_powerpc<size, big_endian>::scan_r
Nick Clifton 3edb85
 	{
Nick Clifton 3edb85
 	  if (parameters->options().user_set_plt_localentry())
Nick Clifton 3edb85
 	    plt_localentry0 = parameters->options().plt_localentry();
Nick Clifton 3edb85
-	  else
Nick Clifton 3edb85
-	    plt_localentry0 = symtab->lookup("GLIBC_2.26", NULL) != NULL;
Nick Clifton 3edb85
+	  if (plt_localentry0
Nick Clifton 3edb85
+	      && symtab->lookup("GLIBC_2.26", NULL) == NULL)
Nick Clifton 3edb85
+	    gold_warning(_("--plt-localentry is especially dangerous without "
Nick Clifton 3edb85
+			   "ld.so support to detect ABI violations"));
Nick Clifton 3edb85
 	}
Nick Clifton 3edb85
       this->plt_localentry0_ = plt_localentry0;
Nick Clifton 3edb85
       this->plt_localentry0_init_ = true;
Nick Clifton 3edb85
diff -rup binutils.orig/ld/ld.texinfo binutils-2.29/ld/ld.texinfo
Nick Clifton 3edb85
--- binutils.orig/ld/ld.texinfo	2017-07-31 10:48:13.601980515 +0100
Nick Clifton 3edb85
+++ binutils-2.29/ld/ld.texinfo	2017-07-31 10:48:37.388711559 +0100
Nick Clifton 3edb85
@@ -7600,6 +7600,24 @@ barrier in the call stub, or use LD_BIND
Nick Clifton 3edb85
 looks for calls to commonly used functions that create threads, and if
Nick Clifton 3edb85
 seen, adds the necessary barriers.  Use these options to change the
Nick Clifton 3edb85
 default behaviour.
Nick Clifton 3edb85
+
Nick Clifton 3edb85
+@cindex PowerPC64 ELFv2 PLT localentry optimization
Nick Clifton 3edb85
+@kindex --plt-localentry
Nick Clifton 3edb85
+@kindex --no-plt-localentry
Nick Clifton 3edb85
+@item --plt-localentry
Nick Clifton 3edb85
+@itemx --no-localentry
Nick Clifton 3edb85
+ELFv2 functions with localentry:0 are those with a single entry point,
Nick Clifton 3edb85
+ie. global entry == local entry, and that have no requirement on r2
Nick Clifton 3edb85
+(the TOC/GOT pointer) or r12, and guarantee r2 is unchanged on return.
Nick Clifton 3edb85
+Such an external function can be called via the PLT without saving r2
Nick Clifton 3edb85
+or restoring it on return, avoiding a common load-hit-store for small
Nick Clifton 3edb85
+functions.   The optimization is attractive, with up to 40% reduction
Nick Clifton 3edb85
+in execution time for a small function, but can result in symbol
Nick Clifton 3edb85
+interposition failures.  Also, minor changes in a shared library,
Nick Clifton 3edb85
+including system libraries, can cause a function that was localentry:0
Nick Clifton 3edb85
+to become localentry:8.  This will result in a dynamic loader
Nick Clifton 3edb85
+complaint and failure to run.  The option is experimental, use with
Nick Clifton 3edb85
+care.  @option{--no-plt-localentry} is the default.
Nick Clifton 3edb85
 @end table
Nick Clifton 3edb85
 
Nick Clifton 3edb85
 @ifclear GENERIC