daily update
[deliverable/binutils-gdb.git] / bfd / elflink.c
index ee80bcc7e2ee76f1b0263869a3ed57e96267bbee..69a87a6b44b5e4209b9009568e38a49c3d657835 100644 (file)
@@ -851,47 +851,26 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
 
 static void
 elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
-                   Elf_Internal_Sym *isym, bfd_boolean definition,
-                   bfd_boolean dynamic)
+                   const Elf_Internal_Sym *isym,
+                   bfd_boolean definition, bfd_boolean dynamic)
 {
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
   /* If st_other has a processor-specific meaning, specific
-     code might be needed here. We never merge the visibility
-     attribute with the one from a dynamic object.  */
+     code might be needed here.  */
   if (bed->elf_backend_merge_symbol_attribute)
     (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
                                                dynamic);
 
-  /* If this symbol has default visibility and the user has requested
-     we not re-export it, then mark it as hidden.  */
-  if (definition
-      && !dynamic
-      && (abfd->no_export
-         || (abfd->my_archive && abfd->my_archive->no_export))
-      && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
-    isym->st_other = (STV_HIDDEN
-                     | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
-
-  if (!dynamic && ELF_ST_VISIBILITY (isym->st_other) != 0)
-    {
-      unsigned char hvis, symvis, other, nvis;
-
-      /* Only merge the visibility. Leave the remainder of the
-        st_other field to elf_backend_merge_symbol_attribute.  */
-      other = h->other & ~ELF_ST_VISIBILITY (-1);
-
-      /* Combine visibilities, using the most constraining one.  */
-      hvis = ELF_ST_VISIBILITY (h->other);
-      symvis = ELF_ST_VISIBILITY (isym->st_other);
-      if (! hvis)
-       nvis = symvis;
-      else if (! symvis)
-       nvis = hvis;
-      else
-       nvis = hvis < symvis ? hvis : symvis;
+  if (!dynamic)
+    {
+      unsigned symvis = ELF_ST_VISIBILITY (isym->st_other);
+      unsigned hvis = ELF_ST_VISIBILITY (h->other);
 
-      h->other = other | nvis;
+      /* Keep the most constraining visibility.  Leave the remainder
+        of the st_other field to elf_backend_merge_symbol_attribute.  */
+      if (symvis - 1 < hvis - 1)
+       h->other = symvis | (h->other & ~ELF_ST_VISIBILITY (-1));
     }
 }
 
@@ -2952,13 +2931,6 @@ elf_link_is_defined_archive_symbol (bfd * abfd, carsym * symdef)
   if (! bfd_check_format (abfd, bfd_object))
     return FALSE;
 
-  /* If we have already included the element containing this symbol in the
-     link then we do not need to include it again.  Just claim that any symbol
-     it contains is not a definition, so that our caller will not decide to
-     (re)include this element.  */
-  if (abfd->archive_pass)
-    return FALSE;
-
   /* Select the appropriate symbol table.  */
   if ((abfd->flags & DYNAMIC) == 0 || elf_dynsymtab (abfd) == 0)
     hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -4095,6 +4067,16 @@ error_free_dyn:
              name = newname;
            }
 
+         /* If this symbol has default visibility and the user has
+            requested we not re-export it, then mark it as hidden.  */
+         if (definition
+             && !dynamic
+             && (abfd->no_export
+                 || (abfd->my_archive && abfd->my_archive->no_export))
+             && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
+           isym->st_other = (STV_HIDDEN
+                             | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
+
          if (!_bfd_elf_merge_symbol (abfd, info, name, isym, &sec, &value,
                                      sym_hash, &old_bfd, &old_weak,
                                      &old_alignment, &skip, &override,
@@ -4939,20 +4921,8 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd,
 }
 
 /* Add symbols from an ELF archive file to the linker hash table.  We
-   don't use _bfd_generic_link_add_archive_symbols because of a
-   problem which arises on UnixWare.  The UnixWare libc.so is an
-   archive which includes an entry libc.so.1 which defines a bunch of
-   symbols.  The libc.so archive also includes a number of other
-   object files, which also define symbols, some of which are the same
-   as those defined in libc.so.1.  Correct linking requires that we
-   consider each object file in turn, and include it if it defines any
-   symbols we need.  _bfd_generic_link_add_archive_symbols does not do
-   this; it looks through the list of undefined symbols, and includes
-   any object file which defines them.  When this algorithm is used on
-   UnixWare, it winds up pulling in libc.so.1 early and defining a
-   bunch of symbols.  This means that some of the other objects in the
-   archive are not included in the link, which is incorrect since they
-   precede libc.so.1 in the archive.
+   don't use _bfd_generic_link_add_archive_symbols because we need to
+   handle versioned symbols.
 
    Fortunately, ELF archive handling is simpler than that done by
    _bfd_generic_link_add_archive_symbols, which has to allow for a.out
@@ -4967,8 +4937,7 @@ static bfd_boolean
 elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
 {
   symindex c;
-  bfd_boolean *defined = NULL;
-  bfd_boolean *included = NULL;
+  unsigned char *included = NULL;
   carsym *symdefs;
   bfd_boolean loop;
   bfd_size_type amt;
@@ -4992,11 +4961,10 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
   if (c == 0)
     return TRUE;
   amt = c;
-  amt *= sizeof (bfd_boolean);
-  defined = (bfd_boolean *) bfd_zmalloc (amt);
-  included = (bfd_boolean *) bfd_zmalloc (amt);
-  if (defined == NULL || included == NULL)
-    goto error_return;
+  amt *= sizeof (*included);
+  included = (unsigned char *) bfd_zmalloc (amt);
+  if (included == NULL)
+    return FALSE;
 
   symdefs = bfd_ardata (abfd)->symdefs;
   bed = get_elf_backend_data (abfd);
@@ -5021,7 +4989,7 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
          struct bfd_link_hash_entry *undefs_tail;
          symindex mark;
 
-         if (defined[i] || included[i])
+         if (included[i])
            continue;
          if (symdef->file_offset == last)
            {
@@ -5056,7 +5024,8 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
          else if (h->root.type != bfd_link_hash_undefined)
            {
              if (h->root.type != bfd_link_hash_undefweak)
-               defined[i] = TRUE;
+               /* Symbol must be defined.  Don't check it again.  */
+               included[i] = TRUE;
              continue;
            }
 
@@ -5068,16 +5037,6 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
          if (! bfd_check_format (element, bfd_object))
            goto error_return;
 
-         /* Doublecheck that we have not included this object
-            already--it should be impossible, but there may be
-            something wrong with the archive.  */
-         if (element->archive_pass != 0)
-           {
-             bfd_set_error (bfd_error_bad_value);
-             goto error_return;
-           }
-         element->archive_pass = 1;
-
          undefs_tail = info->hash->undefs_tail;
 
          if (!(*info->callbacks
@@ -5115,14 +5074,11 @@ elf_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
     }
   while (loop);
 
-  free (defined);
   free (included);
 
   return TRUE;
 
  error_return:
-  if (defined != NULL)
-    free (defined);
   if (included != NULL)
     free (included);
   return FALSE;
@@ -13044,17 +13000,24 @@ _bfd_elf_make_dynamic_reloc_section (asection *         sec,
   return reloc_sec;
 }
 
-/* Copy the ELF symbol type associated with a linker hash entry.  */
+/* Copy the ELF symbol type and other attributes for a linker script
+   assignment from HSRC to HDEST.  Generally this should be treated as
+   if we found a strong non-dynamic definition for HDEST (except that
+   ld ignores multiple definition errors).  */
 void
-_bfd_elf_copy_link_hash_symbol_type (bfd *abfd ATTRIBUTE_UNUSED,
-    struct bfd_link_hash_entry * hdest,
-    struct bfd_link_hash_entry * hsrc)
+_bfd_elf_copy_link_hash_symbol_type (bfd *abfd,
+                                    struct bfd_link_hash_entry *hdest,
+                                    struct bfd_link_hash_entry *hsrc)
 {
-  struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *)hdest;
-  struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc;
+  struct elf_link_hash_entry *ehdest = (struct elf_link_hash_entry *) hdest;
+  struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *) hsrc;
+  Elf_Internal_Sym isym;
 
   ehdest->type = ehsrc->type;
   ehdest->target_internal = ehsrc->target_internal;
+
+  isym.st_other = ehsrc->other;
+  elf_merge_st_other (abfd, ehdest, &isym, TRUE, FALSE);
 }
 
 /* Append a RELA relocation REL to section S in BFD.  */
This page took 0.030568 seconds and 4 git commands to generate.