PATCH: PR ld/2884: Crash in elf64_ia64_relocate_section

H. J. Lu hjl@lucon.org
Thu Jul 6 23:28:00 GMT 2006


The problem is when linker sees a reference and then a versioned dynamic
definition, it calls elf_backend_copy_indirect_symbol to copy the
symbol info to the versioned dynamic definition. When linker sees a
normal definition with non-default visibility, it removes the old
dynamic definition without saving the symbol info copied over
previously. This patch copies the symbol info from the old versioned
dynamic definition to the new one with non-default visibility.


H.J.
---
2006-07-06  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/2884
	* elflink.c (_bfd_elf_merge_symbol): Set ref_dynamic to 0 for
	hidden and internal visibility.  Copy the symbol info from the
	old versioned dynamic definition to the new one with
	non-default visibility.

--- bfd/elflink.c.foo	2006-07-05 11:50:35.000000000 -0700
+++ bfd/elflink.c	2006-07-06 16:23:17.000000000 -0700
@@ -988,16 +988,20 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && !bfd_is_und_section (sec))
     {
       *skip = TRUE;
-      /* Make sure this symbol is dynamic.  */
-      h->ref_dynamic = 1;
       /* A protected symbol has external availability. Make sure it is
 	 recorded as dynamic.
 
 	 FIXME: Should we check type and size for protected symbol?  */
       if (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
-	return bfd_elf_link_record_dynamic_symbol (info, h);
+	{
+	  h->ref_dynamic = 1;
+	  return bfd_elf_link_record_dynamic_symbol (info, h);
+	}
       else
-	return TRUE;
+	{
+	  h->ref_dynamic = 0;
+	  return TRUE;
+	}
     }
   else if (!newdyn
 	   && ELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
@@ -1007,7 +1011,25 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	 relocatable file and the old definition comes from a dynamic
 	 object, we remove the old definition.  */
       if ((*sym_hash)->root.type == bfd_link_hash_indirect)
-	h = *sym_hash;
+	{
+	  /* Handle the case where the old dynamic definition is
+	     versioned.  We need to copy the symbol info from the
+	     versioned symbol to the normal one if it is referenced
+	     before.  */
+	  if (h->ref_regular)
+	    {
+	      const struct elf_backend_data *bed
+		= get_elf_backend_data (abfd);
+	      struct elf_link_hash_entry *vh = *sym_hash;
+	      vh->root.type = h->root.type;
+	      h->root.type = bfd_link_hash_indirect;
+	      (*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
+	      h->root.type = vh->root.type;
+	      h = vh;
+	    }
+	  else
+	    h = *sym_hash;
+	}
 
       if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root)
 	  && bfd_is_und_section (sec))
@@ -1030,9 +1052,14 @@ _bfd_elf_merge_symbol (bfd *abfd,
       if (h->def_dynamic)
 	{
 	  h->def_dynamic = 0;
-	  h->ref_dynamic = 1;
+	  /* Hidden and internal symbols aren't available outside.  */
+	  if (ELF_ST_VISIBILITY (sym->st_other) == STV_PROTECTED)
+	    h->ref_dynamic = 1;
+	  else
+	    h->ref_dynamic = 0;
 	  h->dynamic_def = 1;
 	}
+
       /* FIXME: Should we check type and size for protected symbol?  */
       h->size = 0;
       h->type = 0;



More information about the Binutils mailing list