This is the mail archive of the binutils-cvs@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] PowerPC64 dot-symbol compatibility bugfixes


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8c5b4e5228ec94923fbdfb0008926b0b2a3f51c2

commit 8c5b4e5228ec94923fbdfb0008926b0b2a3f51c2
Author: Alan Modra <amodra@gmail.com>
Date:   Sat Dec 3 21:00:01 2016 +1030

    PowerPC64 dot-symbol compatibility bugfixes
    
    Lots of fixes for the compatibility code that handles linking of
    -mcall-aixdesc code (or that generated by 12 year old gcc) with
    current ELFv1 ABI code.
    
    1) A reference to a dot-symbol in an object file wasn't satisfied by a
       function descriptor in later object files.
    2) The as-needed code had bit-rotted;  Shared libs now need a strong
       reference to be counted as needed.
    3) --gc-sections involving dot-symbols was broken, needing
       func_desc_adjust to be run early and lots of other fixes.
    
    bfd/
    	* elf64-ppc.c (struct ppc_link_hash_entry): Delete "was_undefined".
    	(struct ppc_link_hash_table): Delete "twiddled_syms".  Add
    	"need_func_desc_adj".
    	(lookup_fdh): Link direct fdh sym via oh field and set flags.
    	(make_fdh): Make strong and weak undefined function descriptor
    	symbols.
    	(ppc64_elf_merge_symbol): New function.
    	(elf_backend_merge_symbol): Define.
    	(ppc64_elf_archive_symbol_lookup): Don't test undefweak for fake
    	function descriptors.
    	(add_symbol_adjust): Don't twiddle symbols to undefweak.
    	Propagate more ref flags to function descriptor symbol.  Make
    	some function descriptor symbols dynamic.
    	(ppc64_elf_before_check_relocs): Only run add_symbol_adjust for
    	ELFv1.  Set need_func_desc_adj.  Don't fix undefs list.
    	(ppc64_elf_check_relocs): Set non_ir_ref for descriptors.
    	Don't call lookup_fdh here.
    	(ppc64_elf_gc_sections): New function.
    	(bfd_elf64_bfd_gc_sections): Define.
    	(ppc64_elf_gc_mark_hook): Mark descriptor.
    	(func_desc_adjust): Don't make fake function descriptor syms strong
    	here.  Exit earlier on non-dotsyms.  Take note of elf.dynamic
    	flag when deciding whether a dynamic function descriptor might
    	be needed.  Transfer elf.dynamic and set elf.needs_plt.  Move
    	plt regardless of visibility.  Make descriptor dynamic if
    	entry sym is dynamic, not for other cases.
    	(ppc64_elf_func_desc_adjust): Don't run func_desc_adjust if
    	already done.
    	(ppc64_elf_edit_opd): Use oh field rather than lookup_fdh.
    	(ppc64_elf_size_stubs): Likewise.
    	(ppc_build_one_stub): Don't clear was_undefined.  Only set sym
    	undefweak if stub symbol is defined.
    	(undo_symbol_twiddle, ppc64_elf_restore_symbols): Delete.
    	* elf64-ppc.h (ppc64_elf_restore_symbols): Don't declare.
    ld/
    	* emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't call
    	ppc64_elf_restore_symbols.
    	* testsuite/ld-powerpc/dotsym1.d: New.
    	* testsuite/ld-powerpc/dotsym2.d: New.
    	* testsuite/ld-powerpc/dotsym3.d: New.
    	* testsuite/ld-powerpc/dotsym4.d: New.
    	* testsuite/ld-powerpc/dotsymref.s: New.
    	* testsuite/ld-powerpc/nodotsym.s: New.
    	* testsuite/ld-powerpc/powerpc.exp: Run new tests.

Diff:
---
 bfd/ChangeLog                       |  37 ++++
 bfd/elf64-ppc.c                     | 328 ++++++++++++++++++------------------
 bfd/elf64-ppc.h                     |   2 -
 ld/ChangeLog                        |  12 ++
 ld/emultempl/ppc64elf.em            |   1 -
 ld/testsuite/ld-powerpc/dotsym1.d   |  15 ++
 ld/testsuite/ld-powerpc/dotsym2.d   |  16 ++
 ld/testsuite/ld-powerpc/dotsym3.d   |  16 ++
 ld/testsuite/ld-powerpc/dotsym4.d   |  17 ++
 ld/testsuite/ld-powerpc/dotsymref.s |   4 +
 ld/testsuite/ld-powerpc/nodotsym.s  |  11 ++
 ld/testsuite/ld-powerpc/powerpc.exp |   4 +
 12 files changed, 299 insertions(+), 164 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7721b17..b0dafb2 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,42 @@
 2016-12-03  Alan Modra  <amodra@gmail.com>
 
+	* elf64-ppc.c (struct ppc_link_hash_entry): Delete "was_undefined".
+	(struct ppc_link_hash_table): Delete "twiddled_syms".  Add
+	"need_func_desc_adj".
+	(lookup_fdh): Link direct fdh sym via oh field and set flags.
+	(make_fdh): Make strong and weak undefined function descriptor
+	symbols.
+	(ppc64_elf_merge_symbol): New function.
+	(elf_backend_merge_symbol): Define.
+	(ppc64_elf_archive_symbol_lookup): Don't test undefweak for fake
+	function descriptors.
+	(add_symbol_adjust): Don't twiddle symbols to undefweak.
+	Propagate more ref flags to function descriptor symbol.  Make
+	some function descriptor symbols dynamic.
+	(ppc64_elf_before_check_relocs): Only run add_symbol_adjust for
+	ELFv1.  Set need_func_desc_adj.  Don't fix undefs list.
+	(ppc64_elf_check_relocs): Set non_ir_ref for descriptors.
+	Don't call lookup_fdh here.
+	(ppc64_elf_gc_sections): New function.
+	(bfd_elf64_bfd_gc_sections): Define.
+	(ppc64_elf_gc_mark_hook): Mark descriptor.
+	(func_desc_adjust): Don't make fake function descriptor syms strong
+	here.  Exit earlier on non-dotsyms.  Take note of elf.dynamic
+	flag when deciding whether a dynamic function descriptor might
+	be needed.  Transfer elf.dynamic and set elf.needs_plt.  Move
+	plt regardless of visibility.  Make descriptor dynamic if
+	entry sym is dynamic, not for other cases.
+	(ppc64_elf_func_desc_adjust): Don't run func_desc_adjust if
+	already done.
+	(ppc64_elf_edit_opd): Use oh field rather than lookup_fdh.
+	(ppc64_elf_size_stubs): Likewise.
+	(ppc_build_one_stub): Don't clear was_undefined.  Only set sym
+	undefweak if stub symbol is defined.
+	(undo_symbol_twiddle, ppc64_elf_restore_symbols): Delete.
+	* elf64-ppc.h (ppc64_elf_restore_symbols): Don't declare.
+
+2016-12-03  Alan Modra  <amodra@gmail.com>
+
 	* elf64-ppc.c (ppc64_elf_hide_symbol): Access hash table as
 	elf_link_hash_table rather than ppc_link_hash_table.
 
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index 27328ec..f624874 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -87,6 +87,7 @@ static bfd_vma opd_entry_value
 #define bfd_elf64_bfd_link_hash_table_create  ppc64_elf_link_hash_table_create
 #define bfd_elf64_get_synthetic_symtab	      ppc64_elf_get_synthetic_symtab
 #define bfd_elf64_bfd_link_just_syms	      ppc64_elf_link_just_syms
+#define bfd_elf64_bfd_gc_sections	      ppc64_elf_gc_sections
 
 #define elf_backend_object_p		      ppc64_elf_object_p
 #define elf_backend_grok_prstatus	      ppc64_elf_grok_prstatus
@@ -118,6 +119,7 @@ static bfd_vma opd_entry_value
 #define elf_backend_link_output_symbol_hook   ppc64_elf_output_symbol_hook
 #define elf_backend_special_sections	      ppc64_elf_special_sections
 #define elf_backend_merge_symbol_attribute    ppc64_elf_merge_symbol_attribute
+#define elf_backend_merge_symbol	      ppc64_elf_merge_symbol
 
 /* The name of the dynamic interpreter.  This is put in the .interp
    section.  */
@@ -3978,9 +3980,6 @@ struct ppc_link_hash_entry
      should be set for all globals defined in any opd/toc section.  */
   unsigned int adjust_done:1;
 
-  /* Set if we twiddled this symbol to weak at some stage.  */
-  unsigned int was_undefined:1;
-
   /* Set if this is an out-of-line register save/restore function,
      with non-standard calling convention.  */
   unsigned int save_res:1;
@@ -4087,8 +4086,8 @@ struct ppc_link_hash_table
   /* Set on error.  */
   unsigned int stub_error:1;
 
-  /* Temp used by ppc64_elf_before_check_relocs.  */
-  unsigned int twiddled_syms:1;
+  /* Whether func_desc_adjust needs to be run over symbols.  */
+  unsigned int need_func_desc_adj:1;
 
   /* Incremented every time we size stubs.  */
   unsigned int stub_iteration;
@@ -4898,32 +4897,29 @@ lookup_fdh (struct ppc_link_hash_entry *fh, struct ppc_link_hash_table *htab)
       fh->oh = fdh;
     }
 
-  return ppc_follow_link (fdh);
+  fdh = ppc_follow_link (fdh);
+  fdh->is_func_descriptor = 1;
+  fdh->oh = fh;
+  return fdh;
 }
 
-/* Make a fake function descriptor sym for the code sym FH.  */
+/* Make a fake function descriptor sym for the undefined code sym FH.  */
 
 static struct ppc_link_hash_entry *
 make_fdh (struct bfd_link_info *info,
 	  struct ppc_link_hash_entry *fh)
 {
-  bfd *abfd;
-  asymbol *newsym;
-  struct bfd_link_hash_entry *bh;
+  bfd *abfd = fh->elf.root.u.undef.abfd;
+  struct bfd_link_hash_entry *bh = NULL;
   struct ppc_link_hash_entry *fdh;
-
-  abfd = fh->elf.root.u.undef.abfd;
-  newsym = bfd_make_empty_symbol (abfd);
-  newsym->name = fh->elf.root.root.string + 1;
-  newsym->section = bfd_und_section_ptr;
-  newsym->value = 0;
-  newsym->flags = BSF_WEAK;
-
-  bh = NULL;
-  if (!_bfd_generic_link_add_one_symbol (info, abfd, newsym->name,
-					 newsym->flags, newsym->section,
-					 newsym->value, NULL, FALSE, FALSE,
-					 &bh))
+  flagword flags = (fh->elf.root.type == bfd_link_hash_undefweak
+		    ? BSF_WEAK
+		    : BSF_GLOBAL);
+
+  if (!_bfd_generic_link_add_one_symbol (info, abfd,
+					 fh->elf.root.root.string + 1,
+					 flags, bfd_und_section_ptr, 0,
+					 NULL, FALSE, FALSE, &bh))
     return NULL;
 
   fdh = (struct ppc_link_hash_entry *) bh;
@@ -5012,6 +5008,22 @@ ppc64_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
 		| ELF_ST_VISIBILITY (h->other));
 }
 
+/* Hook called on merging a symbol.  We use this to clear "fake" since
+   we now have a real symbol.  */
+
+static bfd_boolean
+ppc64_elf_merge_symbol (struct elf_link_hash_entry *h,
+			const Elf_Internal_Sym *isym ATTRIBUTE_UNUSED,
+			asection **psec ATTRIBUTE_UNUSED,
+			bfd_boolean newdef ATTRIBUTE_UNUSED,
+			bfd_boolean olddef ATTRIBUTE_UNUSED,
+			bfd *oldbfd ATTRIBUTE_UNUSED,
+			const asection *oldsec ATTRIBUTE_UNUSED)
+{
+  ((struct ppc_link_hash_entry *) h)->fake = 0;
+  return TRUE;
+}
+
 /* This function makes an old ABI object reference to ".bar" cause the
    inclusion of a new ABI object archive that defines "bar".
    NAME is a symbol defined in an archive.  Return a symbol in the hash
@@ -5030,8 +5042,7 @@ ppc64_elf_archive_symbol_lookup (bfd *abfd,
   if (h != NULL
       /* Don't return this sym if it is a fake function descriptor
 	 created by add_symbol_adjust.  */
-      && !(h->root.type == bfd_link_hash_undefweak
-	   && ((struct ppc_link_hash_entry *) h)->fake))
+      && !((struct ppc_link_hash_entry *) h)->fake)
     return h;
 
   if (name[0] == '.')
@@ -5077,38 +5088,49 @@ add_symbol_adjust (struct ppc_link_hash_entry *eh, struct bfd_link_info *info)
     return FALSE;
 
   fdh = lookup_fdh (eh, htab);
-  if (fdh == NULL)
-    {
-      if (!bfd_link_relocatable (info)
-	  && (eh->elf.root.type == bfd_link_hash_undefined
-	      || eh->elf.root.type == bfd_link_hash_undefweak)
-	  && eh->elf.ref_regular)
-	{
-	  /* Make an undefweak function descriptor sym, which is enough to
-	     pull in an --as-needed shared lib, but won't cause link
-	     errors.  Archives are handled elsewhere.  */
-	  fdh = make_fdh (info, eh);
-	  if (fdh == NULL)
-	    return FALSE;
-	  fdh->elf.ref_regular = 1;
-	}
+  if (fdh == NULL
+      && !bfd_link_relocatable (info)
+      && (eh->elf.root.type == bfd_link_hash_undefined
+	  || eh->elf.root.type == bfd_link_hash_undefweak)
+      && eh->elf.ref_regular)
+    {
+      /* Make an undefined function descriptor sym, in order to
+	 pull in an --as-needed shared lib.  Archives are handled
+	 elsewhere.  */
+      fdh = make_fdh (info, eh);
+      if (fdh == NULL)
+	return FALSE;
     }
-  else
+
+  if (fdh != NULL)
     {
       unsigned entry_vis = ELF_ST_VISIBILITY (eh->elf.other) - 1;
       unsigned descr_vis = ELF_ST_VISIBILITY (fdh->elf.other) - 1;
+
+      /* Make both descriptor and entry symbol have the most
+	 constraining visibility of either symbol.  */
       if (entry_vis < descr_vis)
 	fdh->elf.other += entry_vis - descr_vis;
       else if (entry_vis > descr_vis)
 	eh->elf.other += descr_vis - entry_vis;
 
-      if ((fdh->elf.root.type == bfd_link_hash_defined
-	   || fdh->elf.root.type == bfd_link_hash_defweak)
-	  && eh->elf.root.type == bfd_link_hash_undefined)
-	{
-	  eh->elf.root.type = bfd_link_hash_undefweak;
-	  eh->was_undefined = 1;
-	  htab->twiddled_syms = 1;
+      /* Propagate reference flags from entry symbol to function
+	 descriptor symbol.  */
+      fdh->elf.root.non_ir_ref |= eh->elf.root.non_ir_ref;
+      fdh->elf.ref_regular |= eh->elf.ref_regular;
+      fdh->elf.ref_regular_nonweak |= eh->elf.ref_regular_nonweak;
+
+      if (!fdh->elf.forced_local
+	  && fdh->elf.dynindx == -1
+	  && fdh->elf.versioned != versioned_hidden
+	  && (bfd_link_dll (info)
+	      || fdh->elf.def_dynamic
+	      || fdh->elf.ref_dynamic)
+	  && (eh->elf.ref_regular
+	      || eh->elf.def_regular))
+	{
+	  if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf))
+	    return FALSE;
 	}
     }
 
@@ -5190,18 +5212,14 @@ ppc64_elf_before_check_relocs (bfd *ibfd, struct bfd_link_info *info)
       else if (htab->elf.hgot == NULL
 	       && strcmp (eh->elf.root.root.string, ".TOC.") == 0)
 	htab->elf.hgot = &eh->elf;
-      else if (!add_symbol_adjust (eh, info))
-	return FALSE;
+      else if (abiversion (ibfd) <= 1)
+	{
+	  htab->need_func_desc_adj = 1;
+	  if (!add_symbol_adjust (eh, info))
+	    return FALSE;
+	}
       p = &eh->u.next_dot_sym;
     }
-
-  /* We need to fix the undefs list for any syms we have twiddled to
-     undefweak.  */
-  if (htab->twiddled_syms)
-    {
-      bfd_link_repair_undef_list (&htab->elf.root);
-      htab->twiddled_syms = 0;
-    }
   return TRUE;
 }
 
@@ -5394,12 +5412,17 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	h = NULL;
       else
 	{
+	  struct ppc_link_hash_entry *eh;
+
 	  h = sym_hashes[r_symndx - symtab_hdr->sh_info];
 	  h = elf_follow_link (h);
+	  eh = (struct ppc_link_hash_entry *) h;
 
 	  /* PR15323, ref flags aren't set for references in the same
 	     object.  */
 	  h->root.non_ir_ref = 1;
+	  if (eh->is_func && eh->oh != NULL)
+	    eh->oh->elf.root.non_ir_ref = 1;
 
 	  if (h == htab->elf.hgot)
 	    sec->has_toc_reloc = 1;
@@ -5809,14 +5832,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	      && ELF64_R_TYPE ((rel + 1)->r_info) == R_PPC64_TOC)
 	    {
 	      if (h != NULL)
-		{
-		  if (h->root.root.string[0] == '.'
-		      && h->root.root.string[1] != 0
-		      && lookup_fdh ((struct ppc_link_hash_entry *) h, htab))
-		    ;
-		  else
-		    ((struct ppc_link_hash_entry *) h)->is_func = 1;
-		}
+		((struct ppc_link_hash_entry *) h)->is_func = 1;
 	      else
 		{
 		  asection *s;
@@ -6343,6 +6359,23 @@ defined_func_desc (struct ppc_link_hash_entry *fh)
   return NULL;
 }
 
+static bfd_boolean func_desc_adjust (struct elf_link_hash_entry *, void *);
+
+/* Garbage collect sections, after first dealing with dot-symbols.  */
+
+static bfd_boolean
+ppc64_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
+{
+  struct ppc_link_hash_table *htab = ppc_hash_table (info);
+
+  if (htab != NULL && htab->need_func_desc_adj)
+    {
+      elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
+      htab->need_func_desc_adj = 0;
+    }
+  return bfd_elf_gc_sections (abfd, info);
+}
+
 /* Mark all our entry sym sections, both opd and code section.  */
 
 static void
@@ -6477,7 +6510,15 @@ ppc64_elf_gc_mark_hook (asection *sec,
 	      eh = (struct ppc_link_hash_entry *) h;
 	      fdh = defined_func_desc (eh);
 	      if (fdh != NULL)
-		eh = fdh;
+		{
+		  /* -mcall-aixdesc code references the dot-symbol on
+		     a call reloc.  Mark the function descriptor too
+		     against garbage collection.  */
+		  fdh->elf.mark = 1;
+		  if (fdh->elf.u.weakdef != NULL)
+		    fdh->elf.u.weakdef->mark = 1;
+		  eh = fdh;
+		}
 
 	      /* Function descriptor syms cause the associated
 		 function code sym section to be marked.  */
@@ -6956,7 +6997,6 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
 {
   struct bfd_link_info *info;
   struct ppc_link_hash_table *htab;
-  struct plt_entry *ent;
   struct ppc_link_hash_entry *fh;
   struct ppc_link_hash_entry *fdh;
   bfd_boolean force_local;
@@ -6965,18 +7005,29 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
   if (fh->elf.root.type == bfd_link_hash_indirect)
     return TRUE;
 
+  if (!fh->is_func)
+    return TRUE;
+
+  if (fh->elf.root.root.string[0] != '.'
+      || fh->elf.root.root.string[1] == '\0')
+    return TRUE;
+
   info = inf;
   htab = ppc_hash_table (info);
   if (htab == NULL)
     return FALSE;
 
+  /* Find the corresponding function descriptor symbol.  */
+  fdh = lookup_fdh (fh, htab);
+
   /* Resolve undefined references to dot-symbols as the value
      in the function descriptor, if we have one in a regular object.
      This is to satisfy cases like ".quad .foo".  Calls to functions
      in dynamic objects are handled elsewhere.  */
-  if (fh->elf.root.type == bfd_link_hash_undefweak
-      && fh->was_undefined
-      && (fdh = defined_func_desc (fh)) != NULL
+  if ((fh->elf.root.type == bfd_link_hash_undefined
+       || fh->elf.root.type == bfd_link_hash_undefweak)
+      && (fdh->elf.root.type == bfd_link_hash_defined
+	  || fdh->elf.root.type == bfd_link_hash_defweak)
       && get_opd_info (fdh->elf.root.u.def.section) != NULL
       && opd_entry_value (fdh->elf.root.u.def.section,
 			  fdh->elf.root.u.def.value,
@@ -6989,23 +7040,18 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
       fh->elf.def_dynamic = fdh->elf.def_dynamic;
     }
 
-  /* If this is a function code symbol, transfer dynamic linking
-     information to the function descriptor symbol.  */
-  if (!fh->is_func)
-    return TRUE;
-
-  for (ent = fh->elf.plt.plist; ent != NULL; ent = ent->next)
-    if (ent->plt.refcount > 0)
-      break;
-  if (ent == NULL
-      || fh->elf.root.root.string[0] != '.'
-      || fh->elf.root.root.string[1] == '\0')
-    return TRUE;
+  if (!fh->elf.dynamic)
+    {
+      struct plt_entry *ent;
 
-  /* Find the corresponding function descriptor symbol.  Create it
-     as undefined if necessary.  */
+      for (ent = fh->elf.plt.plist; ent != NULL; ent = ent->next)
+	if (ent->plt.refcount > 0)
+	  break;
+      if (ent == NULL)
+	return TRUE;
+    }
 
-  fdh = lookup_fdh (fh, htab);
+  /* Create a descriptor as undefined if necessary.  */
   if (fdh == NULL
       && !bfd_link_executable (info)
       && (fh->elf.root.type == bfd_link_hash_undefined
@@ -7016,51 +7062,30 @@ func_desc_adjust (struct elf_link_hash_entry *h, void *inf)
 	return FALSE;
     }
 
-  /* Fake function descriptors are made undefweak.  If the function
-     code symbol is strong undefined, make the fake sym the same.
-     If the function code symbol is defined, then force the fake
-     descriptor local;  We can't support overriding of symbols in a
-     shared library on a fake descriptor.  */
-
+  /* We can't support overriding of symbols on a fake descriptor.  */
   if (fdh != NULL
       && fdh->fake
-      && fdh->elf.root.type == bfd_link_hash_undefweak)
-    {
-      if (fh->elf.root.type == bfd_link_hash_undefined)
-	{
-	  fdh->elf.root.type = bfd_link_hash_undefined;
-	  bfd_link_add_undef (&htab->elf.root, &fdh->elf.root);
-	}
-      else if (fh->elf.root.type == bfd_link_hash_defined
-	       || fh->elf.root.type == bfd_link_hash_defweak)
-	{
-	  _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, TRUE);
-	}
-    }
+      && (fh->elf.root.type == bfd_link_hash_defined
+	  || fh->elf.root.type == bfd_link_hash_defweak))
+    _bfd_elf_link_hash_hide_symbol (info, &fdh->elf, TRUE);
 
-  if (fdh != NULL
-      && !fdh->elf.forced_local
-      && (!bfd_link_executable (info)
-	  || fdh->elf.def_dynamic
-	  || fdh->elf.ref_dynamic
-	  || (fdh->elf.root.type == bfd_link_hash_undefweak
-	      && ELF_ST_VISIBILITY (fdh->elf.other) == STV_DEFAULT)))
-    {
-      if (fdh->elf.dynindx == -1)
-	if (! bfd_elf_link_record_dynamic_symbol (info, &fdh->elf))
-	  return FALSE;
+  /* Transfer dynamic linking information to the function descriptor.  */
+  if (fdh != NULL)
+    {
       fdh->elf.ref_regular |= fh->elf.ref_regular;
       fdh->elf.ref_dynamic |= fh->elf.ref_dynamic;
       fdh->elf.ref_regular_nonweak |= fh->elf.ref_regular_nonweak;
       fdh->elf.non_got_ref |= fh->elf.non_got_ref;
-      if (ELF_ST_VISIBILITY (fh->elf.other) == STV_DEFAULT)
-	{
-	  move_plt_plist (fh, fdh);
-	  fdh->elf.needs_plt = 1;
-	}
-      fdh->is_func_descriptor = 1;
-      fdh->oh = fh;
-      fh->oh = fdh;
+      fdh->elf.dynamic |= fh->elf.dynamic;
+      fdh->elf.needs_plt |= (fh->elf.needs_plt
+			     || fh->elf.type == STT_FUNC
+			     || fh->elf.type == STT_GNU_IFUNC);
+      move_plt_plist (fh, fdh);
+
+      if (!fdh->elf.forced_local
+	  && fh->elf.dynindx != -1)
+	if (!bfd_elf_link_record_dynamic_symbol (info, &fdh->elf))
+	  return FALSE;
     }
 
   /* Now that the info is on the function descriptor, clear the
@@ -7145,7 +7170,11 @@ ppc64_elf_func_desc_adjust (bfd *obfd ATTRIBUTE_UNUSED,
 			       | STV_HIDDEN);
     }
 
-  elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
+  if (htab->need_func_desc_adj)
+    {
+      elf_link_hash_traverse (&htab->elf, func_desc_adjust, info);
+      htab->need_func_desc_adj = 0;
+    }
 
   return TRUE;
 }
@@ -8092,11 +8121,14 @@ ppc64_elf_edit_opd (struct bfd_link_info *info)
 	      if (h != NULL
 		  && h->root.root.string[0] == '.')
 		{
-		  fdh = lookup_fdh ((struct ppc_link_hash_entry *) h, htab);
-		  if (fdh != NULL
-		      && fdh->elf.root.type != bfd_link_hash_defined
-		      && fdh->elf.root.type != bfd_link_hash_defweak)
-		    fdh = NULL;
+		  fdh = ((struct ppc_link_hash_entry *) h)->oh;
+		  if (fdh != NULL)
+		    {
+		      fdh = ppc_follow_link (fdh);
+		      if (fdh->elf.root.type != bfd_link_hash_defined
+			  && fdh->elf.root.type != bfd_link_hash_defweak)
+			fdh = NULL;
+		    }
 		}
 
 	      skip = (sym_sec->owner != ibfd
@@ -11080,10 +11112,10 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 
 	  /* If the old-ABI "dot-symbol" is undefined make it weak so
 	     we don't get a link error from RELOC_FOR_GLOBAL_SYMBOL.  */
-	  if (fh->elf.root.type == bfd_link_hash_undefined)
+	  if (fh->elf.root.type == bfd_link_hash_undefined
+	      && (stub_entry->h->elf.root.type == bfd_link_hash_defined
+		  || stub_entry->h->elf.root.type == bfd_link_hash_defweak))
 	    fh->elf.root.type = bfd_link_hash_undefweak;
-	  /* Stop undo_symbol_twiddle changing it back to undefined.  */
-	  fh->was_undefined = 0;
 	}
 
       /* Now build the stub.  */
@@ -12412,8 +12444,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
 			 use the func descriptor sym instead if it is
 			 defined.  */
 		      if (hash->elf.root.root.string[0] == '.'
-			  && (fdh = lookup_fdh (hash, htab)) != NULL)
+			  && hash->oh != NULL)
 			{
+			  fdh = ppc_follow_link (hash->oh);
 			  if (fdh->elf.root.type == bfd_link_hash_defined
 			      || fdh->elf.root.type == bfd_link_hash_defweak)
 			    {
@@ -13242,33 +13275,6 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
   return TRUE;
 }
 
-/* This function undoes the changes made by add_symbol_adjust.  */
-
-static bfd_boolean
-undo_symbol_twiddle (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED)
-{
-  struct ppc_link_hash_entry *eh;
-
-  if (h->root.type == bfd_link_hash_indirect)
-    return TRUE;
-
-  eh = (struct ppc_link_hash_entry *) h;
-  if (eh->elf.root.type != bfd_link_hash_undefweak || !eh->was_undefined)
-    return TRUE;
-
-  eh->elf.root.type = bfd_link_hash_undefined;
-  return TRUE;
-}
-
-void
-ppc64_elf_restore_symbols (struct bfd_link_info *info)
-{
-  struct ppc_link_hash_table *htab = ppc_hash_table (info);
-
-  if (htab != NULL)
-    elf_link_hash_traverse (&htab->elf, undo_symbol_twiddle, info);
-}
-
 /* What to do when ld finds relocations against symbols defined in
    discarded sections.  */
 
diff --git a/bfd/elf64-ppc.h b/bfd/elf64-ppc.h
index 971ba09..b1ea550 100644
--- a/bfd/elf64-ppc.h
+++ b/bfd/elf64-ppc.h
@@ -94,5 +94,3 @@ bfd_boolean ppc64_elf_size_stubs
 (struct bfd_link_info *);
 bfd_boolean ppc64_elf_build_stubs
   (struct bfd_link_info *, char **);
-void ppc64_elf_restore_symbols
-  (struct bfd_link_info *info);
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b1c6b8c..90283e3 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,5 +1,17 @@
 2016-12-03  Alan Modra  <amodra@gmail.com>
 
+	* emultempl/ppc64elf.em (gld${EMULATION_NAME}_finish): Don't call
+	ppc64_elf_restore_symbols.
+	* testsuite/ld-powerpc/dotsym1.d: New.
+	* testsuite/ld-powerpc/dotsym2.d: New.
+	* testsuite/ld-powerpc/dotsym3.d: New.
+	* testsuite/ld-powerpc/dotsym4.d: New.
+	* testsuite/ld-powerpc/dotsymref.s: New.
+	* testsuite/ld-powerpc/nodotsym.s: New.
+	* testsuite/ld-powerpc/powerpc.exp: Run new tests.
+
+2016-12-03  Alan Modra  <amodra@gmail.com>
+
 	* testsuite/ld-elf/indirect1b.c: Give dot-symbol a version too.
 	* testsuite/ld-elf/indirect2.c: Likewise.
 	* testsuite/ld-elf/indirect3b.c: Likewise.
diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em
index eaa692d..b614e07 100644
--- a/ld/emultempl/ppc64elf.em
+++ b/ld/emultempl/ppc64elf.em
@@ -592,7 +592,6 @@ gld${EMULATION_NAME}_finish (void)
   if (msg != NULL)
     free (msg);
 
-  ppc64_elf_restore_symbols (&link_info);
   finish_default ();
 }
 
diff --git a/ld/testsuite/ld-powerpc/dotsym1.d b/ld/testsuite/ld-powerpc/dotsym1.d
new file mode 100644
index 0000000..1cb9338
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/dotsym1.d
@@ -0,0 +1,15 @@
+#source: nodotsym.s
+#source: dotsymref.s
+#as: -a64
+#ld: -melf64ppc -Ttext=0x10000000 -e foo
+#objdump: -d
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0+10000000 <\.foo>:
+.*:	(4e 80 00 20|20 00 80 4e) 	blr
+.*:	(60 00 00 00|00 00 00 60) 	nop
+.*:	(00 00 00 00|00 00 00 10) 	.*
+.*:	(10 00 00 00|00 00 00 00) 	.*
diff --git a/ld/testsuite/ld-powerpc/dotsym2.d b/ld/testsuite/ld-powerpc/dotsym2.d
new file mode 100644
index 0000000..7704db7
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/dotsym2.d
@@ -0,0 +1,16 @@
+#source: dotsymref.s
+#source: nodotsym.s
+#as: -a64
+#ld: -melf64ppc -Ttext=0x10000000 -e foo
+#objdump: -d
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0+10000000 <\.foo-0x8>:
+.*:	(00 00 00 00|08 00 00 10) 	.*
+.*:	(10 00 00 08|00 00 00 00) 	.*
+
+0+10000008 <\.foo>:
+.*:	(4e 80 00 20|20 00 80 4e) 	blr
diff --git a/ld/testsuite/ld-powerpc/dotsym3.d b/ld/testsuite/ld-powerpc/dotsym3.d
new file mode 100644
index 0000000..fac2f8e
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/dotsym3.d
@@ -0,0 +1,16 @@
+#source: nodotsym.s
+#source: dotsymref.s
+#as: -a64
+#ld: -melf64ppc -Ttext=0x1000 -shared
+#objdump: -dR
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0+1000 <\.foo>:
+.*:	(4e 80 00 20|20 00 80 4e) 	blr
+.*:	(60 00 00 00|00 00 00 60) 	nop
+.*:	(00 00 00 00|00 10 00 00) 	.*
+.*: R_PPC64_RELATIVE	\*ABS\*\+0x1000
+.*:	(00 00 10 00|00 00 00 00) 	.*
diff --git a/ld/testsuite/ld-powerpc/dotsym4.d b/ld/testsuite/ld-powerpc/dotsym4.d
new file mode 100644
index 0000000..fdd92f3
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/dotsym4.d
@@ -0,0 +1,17 @@
+#source: dotsymref.s
+#source: nodotsym.s
+#as: -a64
+#ld: -melf64ppc -Ttext=0x1000 -shared
+#objdump: -dR
+
+.*:     file format .*
+
+Disassembly of section \.text:
+
+0+1000 <\.foo-0x8>:
+.*:	(00 00 00 00|08 10 00 00) 	.*
+.*: R_PPC64_RELATIVE	\*ABS\*\+0x1008
+.*:	(00 00 10 08|00 00 00 00) 	.*
+
+0+1008 <\.foo>:
+.*:	(4e 80 00 20|20 00 80 4e) 	blr
diff --git a/ld/testsuite/ld-powerpc/dotsymref.s b/ld/testsuite/ld-powerpc/dotsymref.s
new file mode 100644
index 0000000..54c6f5c
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/dotsymref.s
@@ -0,0 +1,4 @@
+ .abiversion 1
+ .text
+ .p2align 3
+ .quad .foo
diff --git a/ld/testsuite/ld-powerpc/nodotsym.s b/ld/testsuite/ld-powerpc/nodotsym.s
new file mode 100644
index 0000000..dbc44ec
--- /dev/null
+++ b/ld/testsuite/ld-powerpc/nodotsym.s
@@ -0,0 +1,11 @@
+ .section .opd,"aw"
+ .p2align 3
+ .global foo
+ .type foo,@function
+foo:
+ .quad .L.foo,.TOC.@tocbase,0
+
+ .text
+.L.foo:
+ blr
+ .size foo,.-.L.foo
diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp
index 07226c6..18a8e62 100644
--- a/ld/testsuite/ld-powerpc/powerpc.exp
+++ b/ld/testsuite/ld-powerpc/powerpc.exp
@@ -299,6 +299,10 @@ if [ supports_ppc64 ] then {
     run_dump_test "tlsld"
     run_dump_test "relocsort"
     run_dump_test "addpcis"
+    run_dump_test "dotsym1"
+    run_dump_test "dotsym2"
+    run_dump_test "dotsym3"
+    run_dump_test "dotsym4"
 }
 
 run_dump_test "tlsld32"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]