Fix check_relocs/gc_sweep_hook mismatch
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 55f00da08c912deb6287359c765375b134b78881..47e48024385227028935a877cfb8be153ed5e912 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
@@ -3344,6 +3366,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
   long old_dynsymcount = 0;
   bfd_size_type old_dynstr_size = 0;
   size_t tabsize = 0;
+  asection *s;
 
   htab = elf_hash_table (info);
   bed = get_elf_backend_data (abfd);
@@ -3385,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 && !info->shared)
-               {
-                 /* 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;
            }
        }
     }
@@ -3479,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;
@@ -3777,8 +3788,7 @@ 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.  Remember some pointers into the
@@ -4427,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
@@ -4472,8 +4485,6 @@ error_free_dyn:
       unsigned int i;
 
       /* Restore the symbol table.  */
-      if (bed->as_needed_cleanup)
-       (*bed->as_needed_cleanup) (abfd, info);
       old_ent = (char *) old_tab + tabsize;
       memset (elf_sym_hashes (abfd), 0,
              extsymcount * sizeof (struct elf_link_hash_entry *));
@@ -4535,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);
@@ -4549,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;
@@ -7464,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;
 };
 
@@ -8682,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
     {
@@ -9523,7 +9549,16 @@ elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
         file, so the contents field will not have been set by any of
         the routines which work on output files.  */
       if (elf_section_data (o)->this_hdr.contents != NULL)
-       contents = elf_section_data (o)->this_hdr.contents;
+       {
+         contents = elf_section_data (o)->this_hdr.contents;
+         if (bed->caches_rawsize
+             && o->rawsize != 0
+             && o->rawsize < o->size)
+           {
+             memcpy (flinfo->contents, contents, o->rawsize);
+             contents = flinfo->contents;
+           }
+       }
       else
        {
          contents = flinfo->contents;
@@ -10966,17 +11001,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
@@ -10988,15 +11012,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;
@@ -11972,7 +11992,9 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info)
             info we collected before.  */
          if (gc_sweep_hook
              && (o->flags & SEC_RELOC) != 0
-             && o->reloc_count > 0
+             && o->reloc_count != 0
+             && !((info->strip == strip_all || info->strip == strip_debugger)
+                  && (o->flags & SEC_DEBUGGING) != 0)
              && !bfd_is_abs_section (o->output_section))
            {
              Elf_Internal_Rela *internal_relocs;
@@ -12120,14 +12142,19 @@ bfd_boolean
 bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
 {
   struct bfd_link_info *info = (struct bfd_link_info *) inf;
+  struct bfd_elf_dynamic_list *d = info->dynamic_list;
 
   if ((h->root.type == bfd_link_hash_defined
        || h->root.type == bfd_link_hash_defweak)
       && (h->ref_dynamic
-         || ((!info->executable || info->export_dynamic)
-             && h->def_regular
+         || (h->def_regular
              && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
              && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
+             && (!info->executable
+                 || info->export_dynamic
+                 || (h->dynamic
+                     && d != NULL
+                     && (*d->match) (&d->head, NULL, h->root.root.string)))
              && (strchr (h->root.root.string, ELF_VER_CHR) != NULL
                  || !bfd_hide_sym_by_version (info->version_info,
                                               h->root.root.string)))))
This page took 0.034885 seconds and 4 git commands to generate.