PR ld/14170
authorAlan Modra <amodra@gmail.com>
Sun, 27 May 2012 13:55:45 +0000 (13:55 +0000)
committerAlan Modra <amodra@gmail.com>
Sun, 27 May 2012 13:55:45 +0000 (13:55 +0000)
* elflink.c (_bfd_elf_merge_symbol): When a symbol defined in
a dynamic library finds a new instance with non-default
visibility in a regular object, correctly handle symbols
already on the undefs list and undo dynamic symbol state when
the new symbol is hidden or internal.

bfd/ChangeLog
bfd/elflink.c

index 9834aab..4abe5f2 100644 (file)
@@ -1,3 +1,12 @@
+2012-05-27  Alan Modra  <amodra@gmail.com>
+
+       PR ld/14170
+       * elflink.c (_bfd_elf_merge_symbol): When a symbol defined in
+       a dynamic library finds a new instance with non-default
+       visibility in a regular object, correctly handle symbols
+       already on the undefs list and undo dynamic symbol state when
+       the new symbol is hidden or internal.
+
 2012-05-25  H.J. Lu  <hongjiu.lu@intel.com>
 
        * elf32-i386.c (elf_i386_create_dynamic_sections): Don't use
index 7f35e7f..e715942 100644 (file)
@@ -1216,15 +1216,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
            h = *sym_hash;
        }
 
-      if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root)
-         && bfd_is_und_section (sec))
-       {
-         /* If the new symbol is undefined and the old symbol was
-            also undefined before, we need to make sure
-            _bfd_generic_link_add_one_symbol doesn't mess
-            up the linker hash table undefs list.  Since the old
-            definition came from a dynamic object, it is still on the
-            undefs list.  */
+      /* If the old symbol was undefined before, then it will still be
+        on the undefs list.  If the new symbol is undefined or
+        common, we can't make it bfd_link_hash_new here, because new
+        undefined or common symbols will be added to the undefs list
+        by _bfd_generic_link_add_one_symbol.  Symbols may not be
+        added twice to the undefs list.  Also, if the new symbol is
+        undefweak then we don't want to lose the strong undef.  */
+      if (h->root.u.undef.next || info->hash->undefs_tail == &h->root)
+       {
          h->root.type = bfd_link_hash_undefined;
          h->root.u.undef.abfd = abfd;
        }
@@ -1234,11 +1234,18 @@ _bfd_elf_merge_symbol (bfd *abfd,
          h->root.u.undef.abfd = NULL;
        }
 
-      if (h->def_dynamic)
+      if (ELF_ST_VISIBILITY (sym->st_other) != STV_PROTECTED)
        {
-         h->def_dynamic = 0;
-         h->ref_dynamic = 1;
+         /* If the new symbol is hidden or internal, completely undo
+            any dynamic link state.  */
+         (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+         h->forced_local = 0;
+         h->ref_dynamic = 0;
        }
+      else
+       h->ref_dynamic = 1;
+      h->def_dynamic = 0;
+      h->dynamic_def = 0;
       /* FIXME: Should we check type and size for protected symbol?  */
       h->size = 0;
       h->type = 0;