Display the reference causing a shared library to be needed
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 363abed0a260845e65d967bdb06e2907960500b9..88967c835fa7dc7d164e70ade4093c6c079a7bb1 100644 (file)
@@ -85,7 +85,8 @@ _bfd_elf_define_linkage_sym (bfd *abfd,
   h->def_regular = 1;
   h->non_elf = 0;
   h->type = STT_OBJECT;
-  h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
+  if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
+    h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
 
   bed = get_elf_backend_data (abfd);
   (*bed->elf_backend_hide_symbol) (info, h, TRUE);
@@ -950,11 +951,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   bed = get_elf_backend_data (abfd);
 
-  /* This code is for coping with dynamic objects, and is only useful
-     if we are doing an ELF link.  */
-  if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
-    return TRUE;
-
   /* For merging, we only care about real symbols.  But we need to make
      sure that indirect symbol dynamic flags are updated.  */
   hi = h;
@@ -962,6 +958,49 @@ _bfd_elf_merge_symbol (bfd *abfd,
         || h->root.type == bfd_link_hash_warning)
     h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
+  /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
+     existing symbol.  */
+
+  oldbfd = NULL;
+  oldsec = NULL;
+  switch (h->root.type)
+    {
+    default:
+      break;
+
+    case bfd_link_hash_undefined:
+    case bfd_link_hash_undefweak:
+      oldbfd = h->root.u.undef.abfd;
+      break;
+
+    case bfd_link_hash_defined:
+    case bfd_link_hash_defweak:
+      oldbfd = h->root.u.def.section->owner;
+      oldsec = h->root.u.def.section;
+      break;
+
+    case bfd_link_hash_common:
+      oldbfd = h->root.u.c.p->section->owner;
+      oldsec = h->root.u.c.p->section;
+      if (pold_alignment)
+       *pold_alignment = h->root.u.c.p->alignment_power;
+      break;
+    }
+  if (poldbfd && *poldbfd == NULL)
+    *poldbfd = oldbfd;
+
+  /* Differentiate strong and weak symbols.  */
+  newweak = bind == STB_WEAK;
+  oldweak = (h->root.type == bfd_link_hash_defweak
+            || h->root.type == bfd_link_hash_undefweak);
+  if (pold_weak)
+    *pold_weak = oldweak;
+
+  /* This code is for coping with dynamic objects, and is only useful
+     if we are doing an ELF link.  */
+  if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
+    return TRUE;
+
   /* We have to check it for every instance since the first few may be
      references and not all compilers emit symbol type for undefined
      symbols.  */
@@ -1006,45 +1045,6 @@ _bfd_elf_merge_symbol (bfd *abfd,
       return TRUE;
     }
 
-  /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
-     existing symbol.  */
-
-  switch (h->root.type)
-    {
-    default:
-      oldbfd = NULL;
-      oldsec = NULL;
-      break;
-
-    case bfd_link_hash_undefined:
-    case bfd_link_hash_undefweak:
-      oldbfd = h->root.u.undef.abfd;
-      oldsec = NULL;
-      break;
-
-    case bfd_link_hash_defined:
-    case bfd_link_hash_defweak:
-      oldbfd = h->root.u.def.section->owner;
-      oldsec = h->root.u.def.section;
-      break;
-
-    case bfd_link_hash_common:
-      oldbfd = h->root.u.c.p->section->owner;
-      oldsec = h->root.u.c.p->section;
-      if (pold_alignment)
-       *pold_alignment = h->root.u.c.p->alignment_power;
-      break;
-    }
-  if (poldbfd && *poldbfd == NULL)
-    *poldbfd = oldbfd;
-
-  /* Differentiate strong and weak symbols.  */
-  newweak = bind == STB_WEAK;
-  oldweak = (h->root.type == bfd_link_hash_defweak
-            || h->root.type == bfd_link_hash_undefweak);
-  if (pold_weak)
-    *pold_weak = oldweak;
-
   /* In cases involving weak versioned symbols, we may wind up trying
      to merge a symbol with itself.  Catch that here, to avoid the
      confusion that results if we try to override a symbol with
@@ -1087,20 +1087,19 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   /* When we try to create a default indirect symbol from the dynamic
      definition with the default version, we skip it if its type and
-     the type of existing regular definition mismatch.  We only do it
-     if the existing regular definition won't be dynamic.  */
+     the type of existing regular definition mismatch.  */
   if (pold_alignment == NULL
-      && !info->shared
-      && !info->export_dynamic
-      && !h->ref_dynamic
       && newdyn
       && newdef
       && !olddyn
-      && (olddef || h->root.type == bfd_link_hash_common)
-      && ELF_ST_TYPE (sym->st_info) != h->type
-      && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
-      && h->type != STT_NOTYPE
-      && !(newfunc && oldfunc))
+      && (((olddef || h->root.type == bfd_link_hash_common)
+          && ELF_ST_TYPE (sym->st_info) != h->type
+          && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+          && h->type != STT_NOTYPE
+          && !(newfunc && oldfunc))
+         || (olddef
+             && ((h->type == STT_GNU_IFUNC)
+                 != (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))))
     {
       *skip = TRUE;
       return TRUE;
@@ -1437,7 +1436,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
       if (!(oldbfd != NULL
            && (oldbfd->flags & BFD_PLUGIN) != 0
            && (abfd->flags & BFD_PLUGIN) == 0))
-       *skip = TRUE;
+       {
+         newdef = FALSE;
+         *skip = TRUE;
+       }
 
       /* Merge st_other.  If the symbol already has a dynamic index,
         but visibility says it should not be visible, turn it into a
@@ -1702,6 +1704,12 @@ _bfd_elf_add_default_symbol (bfd *abfd,
       ht = (struct elf_link_hash_entry *) hi->root.u.i.link;
       (*bed->elf_backend_copy_indirect_symbol) (info, ht, hi);
 
+      /* A reference to the SHORTNAME symbol from a dynamic library
+        will be satisfied by the versioned symbol at runtime.  In
+        effect, we have a reference to the versioned symbol.  */
+      ht->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak;
+      hi->dynamic_def |= ht->dynamic_def;
+
       /* See if the new flags lead us to realize that the symbol must
         be dynamic.  */
       if (! *dynsym)
@@ -1771,6 +1779,8 @@ nondefault:
       if (hi->root.type == bfd_link_hash_indirect)
        {
          (*bed->elf_backend_copy_indirect_symbol) (info, h, hi);
+         h->ref_dynamic_nonweak |= hi->ref_dynamic_nonweak;
+         hi->dynamic_def |= h->dynamic_def;
 
          /* See if the new flags lead us to realize that the symbol
             must be dynamic.  */
@@ -3309,6 +3319,18 @@ _bfd_elf_relocs_compatible (const bfd_target *input,
   return ibed->relocs_compatible == obed->relocs_compatible;
 }
 
+/* Make a special call to the linker "notice" function to tell it that
+   we are about to handle an as-needed lib, or have finished
+   processing the lib.  */ 
+
+bfd_boolean
+_bfd_elf_notice_as_needed (bfd *ibfd,
+                          struct bfd_link_info *info,
+                          enum notice_asneeded_action act)
+{
+  return (*info->callbacks->notice) (info, NULL, ibfd, NULL, act, 0, NULL);
+}
+
 /* Add symbols from an ELF object file to the linker hash table.  */
 
 static bfd_boolean
@@ -3338,14 +3360,13 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   unsigned int old_size = 0;
   unsigned int old_count = 0;
   void *old_tab = NULL;
-  void *old_hash;
   void *old_ent;
   struct bfd_link_hash_entry *old_undefs = NULL;
   struct bfd_link_hash_entry *old_undefs_tail = NULL;
   long old_dynsymcount = 0;
   bfd_size_type old_dynstr_size = 0;
   size_t tabsize = 0;
-  size_t hashsize = 0;
+  asection *s;
 
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
@@ -3387,75 +3408,64 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
      symbol.  This differs from .gnu.warning sections, which generate
      warnings when they are included in an output file.  */
   /* PR 12761: Also generate this warning when building shared libraries.  */
-  if (info->executable || info->shared)
+  for (s = abfd->sections; s != NULL; s = s->next)
     {
-      asection *s;
+      const char *name;
 
-      for (s = abfd->sections; s != NULL; s = s->next)
+      name = bfd_get_section_name (abfd, s);
+      if (CONST_STRNEQ (name, ".gnu.warning."))
        {
-         const char *name;
+         char *msg;
+         bfd_size_type sz;
 
-         name = bfd_get_section_name (abfd, s);
-         if (CONST_STRNEQ (name, ".gnu.warning."))
+         name += sizeof ".gnu.warning." - 1;
+
+         /* If this is a shared object, then look up the symbol
+            in the hash table.  If it is there, and it is already
+            been defined, then we will not be using the entry
+            from this shared object, so we don't need to warn.
+            FIXME: If we see the definition in a regular object
+            later on, we will warn, but we shouldn't.  The only
+            fix is to keep track of what warnings we are supposed
+            to emit, and then handle them all at the end of the
+            link.  */
+         if (dynamic)
            {
-             char *msg;
-             bfd_size_type sz;
-
-             name += sizeof ".gnu.warning." - 1;
-
-             /* If this is a shared object, then look up the symbol
-                in the hash table.  If it is there, and it is already
-                been defined, then we will not be using the entry
-                from this shared object, so we don't need to warn.
-                FIXME: If we see the definition in a regular object
-                later on, we will warn, but we shouldn't.  The only
-                fix is to keep track of what warnings we are supposed
-                to emit, and then handle them all at the end of the
-                link.  */
-             if (dynamic)
-               {
-                 struct elf_link_hash_entry *h;
+             struct elf_link_hash_entry *h;
 
-                 h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
+             h = elf_link_hash_lookup (htab, name, FALSE, FALSE, TRUE);
 
-                 /* FIXME: What about bfd_link_hash_common?  */
-                 if (h != NULL
-                     && (h->root.type == bfd_link_hash_defined
-                         || h->root.type == bfd_link_hash_defweak))
-                   {
-                     /* We don't want to issue this warning.  Clobber
-                        the section size so that the warning does not
-                        get copied into the output file.  */
-                     s->size = 0;
-                     continue;
-                   }
-               }
+             /* FIXME: What about bfd_link_hash_common?  */
+             if (h != NULL
+                 && (h->root.type == bfd_link_hash_defined
+                     || h->root.type == bfd_link_hash_defweak))
+               continue;
+           }
 
-             sz = s->size;
-             msg = (char *) bfd_alloc (abfd, sz + 1);
-             if (msg == NULL)
-               goto error_return;
+         sz = s->size;
+         msg = (char *) bfd_alloc (abfd, sz + 1);
+         if (msg == NULL)
+           goto error_return;
 
-             if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
-               goto error_return;
+         if (! bfd_get_section_contents (abfd, s, msg, 0, sz))
+           goto error_return;
 
-             msg[sz] = '\0';
+         msg[sz] = '\0';
 
-             if (! (_bfd_generic_link_add_one_symbol
-                    (info, abfd, name, BSF_WARNING, s, 0, msg,
-                     FALSE, bed->collect, NULL)))
-               goto error_return;
+         if (! (_bfd_generic_link_add_one_symbol
+                (info, abfd, name, BSF_WARNING, s, 0, msg,
+                 FALSE, bed->collect, NULL)))
+           goto error_return;
 
-             if (! info->relocatable)
-               {
-                 /* Clobber the section size so that the warning does
-                    not get copied into the output file.  */
-                 s->size = 0;
+         if (!info->relocatable && info->executable)
+           {
+             /* Clobber the section size so that the warning does
+                not get copied into the output file.  */
+             s->size = 0;
 
-                 /* Also set SEC_EXCLUDE, so that symbols defined in
-                    the warning section don't get copied to the output.  */
-                 s->flags |= SEC_EXCLUDE;
-               }
+             /* Also set SEC_EXCLUDE, so that symbols defined in
+                the warning section don't get copied to the output.  */
+             s->flags |= SEC_EXCLUDE;
            }
        }
     }
@@ -3481,7 +3491,6 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
     goto error_return;
   else
     {
-      asection *s;
       const char *soname = NULL;
       char *audit = NULL;
       struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
@@ -3700,7 +3709,7 @@ error_free_dyn:
       extsymoff = hdr->sh_info;
     }
 
-  sym_hash = NULL;
+  sym_hash = elf_sym_hashes (abfd);
   if (extsymcount != 0)
     {
       isymbuf = bfd_elf_get_elf_syms (abfd, hdr, extsymcount, extsymoff,
@@ -3708,13 +3717,16 @@ error_free_dyn:
       if (isymbuf == NULL)
        goto error_return;
 
-      /* We store a pointer to the hash table entry for each external
-        symbol.  */
-      amt = extsymcount * sizeof (struct elf_link_hash_entry *);
-      sym_hash = (struct elf_link_hash_entry **) bfd_alloc (abfd, amt);
       if (sym_hash == NULL)
-       goto error_free_sym;
-      elf_sym_hashes (abfd) = sym_hash;
+       {
+         /* We store a pointer to the hash table entry for each
+            external symbol.  */
+         amt = extsymcount * sizeof (struct elf_link_hash_entry *);
+         sym_hash = (struct elf_link_hash_entry **) bfd_zalloc (abfd, amt);
+         if (sym_hash == NULL)
+           goto error_free_sym;
+         elf_sym_hashes (abfd) = sym_hash;
+       }
     }
 
   if (dynamic)
@@ -3764,8 +3776,7 @@ error_free_dyn:
        }
 
       tabsize = htab->root.table.size * sizeof (struct bfd_hash_entry *);
-      hashsize = extsymcount * sizeof (struct elf_link_hash_entry *);
-      old_tab = bfd_malloc (tabsize + entsize + hashsize);
+      old_tab = bfd_malloc (tabsize + entsize);
       if (old_tab == NULL)
        goto error_free_vers;
 
@@ -3777,16 +3788,13 @@ error_free_dyn:
 
       /* Make a special call to the linker "notice" function to
         tell it that we are about to handle an as-needed lib.  */
-      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
-                                      notice_as_needed, 0, NULL))
+      if (!(*bed->notice_as_needed) (abfd, info, notice_as_needed))
        goto error_free_vers;
 
-      /* Clone the symbol table and sym hashes.  Remember some
-        pointers into the symbol table, and dynamic symbol count.  */
-      old_hash = (char *) old_tab + tabsize;
-      old_ent = (char *) old_hash + hashsize;
+      /* Clone the symbol table.  Remember some pointers into the
+        symbol table, and dynamic symbol count.  */
+      old_ent = (char *) old_tab + tabsize;
       memcpy (old_tab, htab->root.table.table, tabsize);
-      memcpy (old_hash, sym_hash, hashsize);
       old_undefs = htab->root.undefs;
       old_undefs_tail = htab->root.undefs_tail;
       old_table = htab->root.table.table;
@@ -3843,7 +3851,6 @@ error_free_dyn:
       flags = BSF_NO_FLAGS;
       sec = NULL;
       value = isym->st_value;
-      *sym_hash = NULL;
       common = bed->common_definition (isym);
 
       bind = ELF_ST_BIND (isym->st_info);
@@ -4430,6 +4437,9 @@ error_free_dyn:
              int ret;
              const char *soname = elf_dt_name (abfd);
 
+             info->callbacks->minfo ("%!", soname, old_bfd,
+                                     h->root.root.string);
+
              /* A symbol from a library loaded via DT_NEEDED of some
                 other library is referenced by a regular object.
                 Add a DT_NEEDED entry for it.  Issue an error if
@@ -4475,16 +4485,13 @@ error_free_dyn:
       unsigned int i;
 
       /* Restore the symbol table.  */
-      if (bed->as_needed_cleanup)
-       (*bed->as_needed_cleanup) (abfd, info);
-      old_hash = (char *) old_tab + tabsize;
-      old_ent = (char *) old_hash + hashsize;
-      sym_hash = elf_sym_hashes (abfd);
+      old_ent = (char *) old_tab + tabsize;
+      memset (elf_sym_hashes (abfd), 0,
+             extsymcount * sizeof (struct elf_link_hash_entry *));
       htab->root.table.table = old_table;
       htab->root.table.size = old_size;
       htab->root.table.count = old_count;
       memcpy (htab->root.table.table, old_tab, tabsize);
-      memcpy (sym_hash, old_hash, hashsize);
       htab->root.undefs = old_undefs;
       htab->root.undefs_tail = old_undefs_tail;
       _bfd_elf_strtab_restore_size (htab->dynstr, old_dynstr_size);
@@ -4539,8 +4546,7 @@ error_free_dyn:
 
       /* Make a special call to the linker "notice" function to
         tell it that symbols added for crefs may need to be removed.  */
-      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
-                                      notice_not_needed, 0, NULL))
+      if (!(*bed->notice_as_needed) (abfd, info, notice_not_needed))
        goto error_free_vers;
 
       free (old_tab);
@@ -4553,8 +4559,7 @@ error_free_dyn:
 
   if (old_tab != NULL)
     {
-      if (!(*info->callbacks->notice) (info, NULL, abfd, NULL,
-                                      notice_needed, 0, NULL))
+      if (!(*bed->notice_as_needed) (abfd, info, notice_needed))
        goto error_free_vers;
       free (old_tab);
       old_tab = NULL;
@@ -4665,7 +4670,7 @@ error_free_dyn:
          struct elf_link_hash_entry *hlook;
          asection *slook;
          bfd_vma vlook;
-         size_t i, j, idx;
+         size_t i, j, idx = 0;
 
          hlook = weaks;
          weaks = hlook->u.weakdef;
@@ -7468,6 +7473,7 @@ struct elf_outext_info
   bfd_boolean localsyms;
   bfd_boolean need_second_pass;
   bfd_boolean second_pass;
+  bfd_boolean file_sym_done;
   struct elf_final_link_info *flinfo;
 };
 
@@ -8686,6 +8692,22 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
                || h->root.type == bfd_link_hash_defweak)
               && h->root.u.def.section->output_section != NULL))
        return TRUE;
+
+      if (!eoinfo->file_sym_done
+         && (eoinfo->second_pass ? eoinfo->flinfo->filesym_count == 1
+                                 : eoinfo->flinfo->filesym_count > 1))
+       {
+         /* Output a FILE symbol so that following locals are not associated
+            with the wrong input file.  */
+         memset (&sym, 0, sizeof (sym));
+         sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
+         sym.st_shndx = SHN_ABS;
+         if (!elf_link_output_sym (eoinfo->flinfo, NULL, &sym,
+                                   bfd_und_section_ptr, NULL))
+           return FALSE;
+
+         eoinfo->file_sym_done = TRUE;
+       }
     }
   else
     {
@@ -10970,17 +10992,6 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
          }
     }
 
-  /* Output a FILE symbol so that following locals are not associated
-     with the wrong input file.  */
-  memset (&elfsym, 0, sizeof (elfsym));
-  elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FILE);
-  elfsym.st_shndx = SHN_ABS;
-
-  if (flinfo.filesym_count > 1
-      && !elf_link_output_sym (&flinfo, NULL, &elfsym,
-                              bfd_und_section_ptr, NULL))
-    return FALSE;
-
   /* Output any global symbols that got converted to local in a
      version script or due to symbol visibility.  We do this in a
      separate step since ELF requires all local symbols to appear
@@ -10992,15 +11003,11 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
   eoinfo.localsyms = TRUE;
   eoinfo.need_second_pass = FALSE;
   eoinfo.second_pass = FALSE;
+  eoinfo.file_sym_done = FALSE;
   bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
   if (eoinfo.failed)
     return FALSE;
 
-  if (flinfo.filesym_count == 1
-      && !elf_link_output_sym (&flinfo, NULL, &elfsym,
-                              bfd_und_section_ptr, NULL))
-    return FALSE;
-
   if (eoinfo.need_second_pass)
     {
       eoinfo.second_pass = TRUE;
This page took 0.036248 seconds and 4 git commands to generate.