* linux-arm-low.c: Include <signal.h>.
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 53765b626df330cb707f08ce8a33a8c025038863..9ccf37df051d075f24d945f21cf273dada6742bd 100644 (file)
@@ -36,7 +36,6 @@
 struct elf_info_failed
 {
   struct bfd_link_info *info;
-  struct bfd_elf_version_tree *verdefs;
   bfd_boolean failed;
 };
 
@@ -1820,20 +1819,14 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
     return TRUE;
 
   if (h->dynindx == -1
-      && (h->def_regular
-         || h->ref_regular))
+      && (h->def_regular || h->ref_regular)
+      && ! bfd_hide_sym_by_version (eif->info->version_info,
+                                   h->root.root.string))
     {
-      bfd_boolean hide;
-
-      if (eif->verdefs == NULL
-         || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide)
-             && !hide))
+      if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
        {
-         if (! bfd_elf_link_record_dynamic_symbol (eif->info, h))
-           {
-             eif->failed = TRUE;
-             return FALSE;
-           }
+         eif->failed = TRUE;
+         return FALSE;
        }
     }
 
@@ -1981,7 +1974,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
        }
 
       /* Look for the version.  If we find it, it is no longer weak.  */
-      for (t = sinfo->verdefs; t != NULL; t = t->next)
+      for (t = sinfo->info->version_info; t != NULL; t = t->next)
        {
          if (strcmp (t->name, p) == 0)
            {
@@ -2050,9 +2043,12 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
          version_index = 1;
          /* Don't count anonymous version tag.  */
-         if (sinfo->verdefs != NULL && sinfo->verdefs->vernum == 0)
+         if (sinfo->info->version_info != NULL
+             && sinfo->info->version_info->vernum == 0)
            version_index = 0;
-         for (pp = &sinfo->verdefs; *pp != NULL; pp = &(*pp)->next)
+         for (pp = &sinfo->info->version_info;
+              *pp != NULL;
+              pp = &(*pp)->next)
            ++version_index;
          t->vernum = version_index;
 
@@ -2078,12 +2074,13 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
 
   /* If we don't have a version for this symbol, see if we can find
      something.  */
-  if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL)
+  if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL)
     {
       bfd_boolean hide;
 
-      h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs,
-                                                h->root.root.string, &hide);
+      h->verinfo.vertree
+       = bfd_find_version_for_sym (sinfo->info->version_info,
+                                   h->root.root.string, &hide);
       if (h->verinfo.vertree != NULL && hide)
        (*bed->elf_backend_hide_symbol) (info, h, TRUE);
     }
@@ -5493,8 +5490,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
                               const char *depaudit,
                               const char * const *auxiliary_filters,
                               struct bfd_link_info *info,
-                              asection **sinterpptr,
-                              struct bfd_elf_version_tree *verdefs)
+                              asection **sinterpptr)
 {
   bfd_size_type soname_indx;
   bfd *dynobj;
@@ -5671,7 +5667,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
        }
 
       eif.info = info;
-      eif.verdefs = verdefs;
       eif.failed = FALSE;
 
       /* If we are supposed to export all symbols into the dynamic symbol
@@ -5687,7 +5682,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
        }
 
       /* Make all global versions with definition.  */
-      for (t = verdefs; t != NULL; t = t->next)
+      for (t = info->version_info; t != NULL; t = t->next)
        for (d = t->globals.list; d != NULL; d = d->next)
          if (!d->symver && d->literal)
            {
@@ -5740,7 +5735,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       /* Attach all the symbols to their version information.  */
       asvinfo.info = info;
-      asvinfo.verdefs = verdefs;
       asvinfo.failed = FALSE;
 
       elf_link_hash_traverse (elf_hash_table (info),
@@ -5753,7 +5747,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
        {
          /* Check if all global versions have a definition.  */
          all_defined = TRUE;
-         for (t = verdefs; t != NULL; t = t->next)
+         for (t = info->version_info; t != NULL; t = t->next)
            for (d = t->globals.list; d != NULL; d = d->next)
              if (d->literal && !d->symver && !d->script)
                {
@@ -5886,6 +5880,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       unsigned long section_sym_count;
+      struct bfd_elf_version_tree *verdefs;
       asection *s;
 
       /* Set up the version definition section.  */
@@ -5894,7 +5889,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
 
       /* We may have created additional version definitions if we are
         just linking a regular application.  */
-      verdefs = asvinfo.verdefs;
+      verdefs = info->version_info;
 
       /* Skip anonymous version tag.  */
       if (verdefs != NULL && verdefs->vernum == 0)
@@ -11694,13 +11689,18 @@ struct elf_gc_sweep_symbol_info
 static bfd_boolean
 elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data)
 {
-  if ((h->root.type == bfd_link_hash_defined
-       || h->root.type == bfd_link_hash_defweak)
-      && !h->root.u.def.section->gc_mark
-      && !(h->root.u.def.section->owner->flags & DYNAMIC))
+  if (((h->root.type == bfd_link_hash_defined
+       || h->root.type == bfd_link_hash_defweak)
+       && !h->root.u.def.section->gc_mark
+       && (!(h->root.u.def.section->owner->flags & DYNAMIC)
+          || (h->plt.refcount <= 0
+              && h->got.refcount <= 0)))
+      || (h->root.type == bfd_link_hash_undefined
+         && h->plt.refcount <= 0
+         && h->got.refcount <= 0))
     {
       struct elf_gc_sweep_symbol_info *inf =
-          (struct elf_gc_sweep_symbol_info *) data;
+       (struct elf_gc_sweep_symbol_info *) data;
       (*inf->hide_symbol) (inf->info, h, TRUE);
     }
 
@@ -11913,7 +11913,9 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf)
          || (!info->executable
              && h->def_regular
              && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL
-             && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN)))
+             && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN
+             && !bfd_hide_sym_by_version (info->version_info,
+                                          h->root.root.string))))
     h->root.u.def.section->flags |= SEC_KEEP;
 
   return TRUE;
@@ -12502,208 +12504,84 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   return ret;
 }
 
-/* For a SHT_GROUP section, return the group signature.  For other
-   sections, return the normal section name.  */
-
-static const char *
-section_signature (asection *sec)
-{
-  if ((sec->flags & SEC_GROUP) != 0
-      && elf_next_in_group (sec) != NULL
-      && elf_group_name (elf_next_in_group (sec)) != NULL)
-    return elf_group_name (elf_next_in_group (sec));
-  return sec->name;
-}
-
 bfd_boolean
 _bfd_elf_section_already_linked (bfd *abfd,
-                                struct already_linked *linked,
+                                asection *sec,
                                 struct bfd_link_info *info)
 {
   flagword flags;
-  const char *name, *p;
+  const char *name, *key;
   struct bfd_section_already_linked *l;
   struct bfd_section_already_linked_hash_entry *already_linked_list;
-  asection *sec, *l_sec;
-  bfd_boolean matched;
-
-  p = name = linked->comdat_key;
-  if (name)
-    {
-      sec = NULL;
-      flags = SEC_GROUP | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD;
-    }
-  else
-    {
-      sec = linked->u.sec;
-      if (sec->output_section == bfd_abs_section_ptr)
-       return FALSE;
-
-      flags = sec->flags;
-
-      /* Return if it isn't a linkonce section.  A comdat group section
-        also has SEC_LINK_ONCE set.  */
-      if ((flags & SEC_LINK_ONCE) == 0)
-       return FALSE;
-
-      /* Don't put group member sections on our list of already linked
-        sections.  They are handled as a group via their group section.
-        */
-      if (elf_sec_group (sec) != NULL)
-       return FALSE;
 
-      /* FIXME: When doing a relocatable link, we may have trouble
-        copying relocations in other sections that refer to local symbols
-        in the section being discarded.  Those relocations will have to
-        be converted somehow; as of this writing I'm not sure that any of
-        the backends handle that correctly.
+  if (sec->output_section == bfd_abs_section_ptr)
+    return FALSE;
 
-        It is tempting to instead not discard link once sections when
-        doing a relocatable link (technically, they should be discarded
-        whenever we are building constructors).  However, that fails,
-        because the linker winds up combining all the link once sections
-        into a single large link once section, which defeats the purpose
-        of having link once sections in the first place.
+  flags = sec->flags;
 
-        Also, not merging link once sections in a relocatable link
-        causes trouble for MIPS ELF, which relies on link once semantics
-        to handle the .reginfo section correctly.  */
+  /* Return if it isn't a linkonce section.  A comdat group section
+     also has SEC_LINK_ONCE set.  */
+  if ((flags & SEC_LINK_ONCE) == 0)
+    return FALSE;
 
-      name = section_signature (sec);
+  /* Don't put group member sections on our list of already linked
+     sections.  They are handled as a group via their group section.  */
+  if (elf_sec_group (sec) != NULL)
+    return FALSE;
 
+  /* For a SHT_GROUP section, use the group signature as the key.  */
+  name = sec->name;
+  if ((flags & SEC_GROUP) != 0
+      && elf_next_in_group (sec) != NULL
+      && elf_group_name (elf_next_in_group (sec)) != NULL)
+    key = elf_group_name (elf_next_in_group (sec));
+  else
+    {
+      /* Otherwise we should have a .gnu.linkonce.<type>.<key> section.  */
       if (CONST_STRNEQ (name, ".gnu.linkonce.")
-         && ((p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.'))
-             != NULL))
-       p++;
+         && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+       key++;
       else
-       p = name;
+       /* Must be a user linkonce section that doesn't follow gcc's
+          naming convention.  In this case we won't be matching
+          single member groups.  */
+       key = name;
     }
 
-  already_linked_list = bfd_section_already_linked_table_lookup (p);
+  already_linked_list = bfd_section_already_linked_table_lookup (key);
 
   for (l = already_linked_list->entry; l != NULL; l = l->next)
     {
-      flagword l_flags;
-      bfd *l_owner;
-      const char *l_name = l->linked.comdat_key;
-      if (l_name)
-       {
-         l_sec = NULL;
-         l_owner = l->linked.u.abfd;
-         l_flags = (SEC_GROUP
-                    | SEC_LINK_ONCE
-                    | SEC_LINK_DUPLICATES_DISCARD);
-       }
-      else
-       {
-         l_sec = l->linked.u.sec;
-         l_owner = l_sec->owner;
-         l_flags = l_sec->flags;
-         l_name = section_signature (l_sec);
-       }
-
       /* We may have 2 different types of sections on the list: group
-        sections and linkonce sections.  Match like sections.  */
-      if ((flags & SEC_GROUP) == (l_flags & SEC_GROUP)
-         && strcmp (name, l_name) == 0)
+        sections with a signature of <key> (<key> is some string),
+        and linkonce sections named .gnu.linkonce.<type>.<key>.
+        Match like sections.  LTO plugin sections are an exception.
+        They are always named .gnu.linkonce.t.<key> and match either
+        type of section.  */
+      if (((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+          && ((flags & SEC_GROUP) != 0
+              || strcmp (name, l->sec->name) == 0))
+         || (l->sec->owner->flags & BFD_PLUGIN) != 0)
        {
          /* The section has already been linked.  See if we should
             issue a warning.  */
-         switch (flags & SEC_LINK_DUPLICATES)
-           {
-           default:
-             abort ();
-
-           case SEC_LINK_DUPLICATES_DISCARD:
-             /* If we found an LTO IR match for this comdat group on
-                the first pass, replace it with the LTO output on the
-                second pass.  We can't simply choose real object
-                files over IR because the first pass may contain a
-                mix of LTO and normal objects and we must keep the
-                first match, be it IR or real.  */
-             if (info->loading_lto_outputs
-                 && (l_owner->flags & BFD_PLUGIN) != 0)
-               {
-                 l->linked = *linked;
-                 return FALSE;
-               }
-             break;
-
-           case SEC_LINK_DUPLICATES_ONE_ONLY:
-             (*_bfd_error_handler)
-               (_("%B: ignoring duplicate section `%A'"),
-                abfd, sec);
-             break;
-
-           case SEC_LINK_DUPLICATES_SAME_SIZE:
-             if (!sec || !l_sec)
-               abort ();
-
-             if (sec->size != l_sec->size)
-               (*_bfd_error_handler)
-                 (_("%B: duplicate section `%A' has different size"),
-                  abfd, sec);
-             break;
-
-           case SEC_LINK_DUPLICATES_SAME_CONTENTS:
-             if (!sec || !l_sec)
-               abort ();
-
-             if (sec->size != l_sec->size)
-               (*_bfd_error_handler)
-                 (_("%B: duplicate section `%A' has different size"),
-                  abfd, sec);
-             else if (sec->size != 0)
-               {
-                 bfd_byte *sec_contents, *l_sec_contents;
-
-                 if (!bfd_malloc_and_get_section (abfd, sec, &sec_contents))
-                   (*_bfd_error_handler)
-                     (_("%B: warning: could not read contents of section `%A'"),
-                      abfd, sec);
-                 else if (!bfd_malloc_and_get_section (l_sec->owner, l_sec,
-                                                       &l_sec_contents))
-                   (*_bfd_error_handler)
-                     (_("%B: warning: could not read contents of section `%A'"),
-                      l_sec->owner, l_sec);
-                 else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0)
-                   (*_bfd_error_handler)
-                     (_("%B: warning: duplicate section `%A' has different contents"),
-                      abfd, sec);
-
-                 if (sec_contents)
-                   free (sec_contents);
-                 if (l_sec_contents)
-                   free (l_sec_contents);
-               }
-             break;
-           }
+         if (!_bfd_handle_already_linked (sec, l, info))
+           return FALSE;
 
-         if (sec)
+         if (flags & SEC_GROUP)
            {
-             /* Set the output_section field so that lang_add_section
-                does not create a lang_input_section structure for this
-                section.  Since there might be a symbol in the section
-                being discarded, we must retain a pointer to the section
-                which we are really going to use.  */
-             sec->output_section = bfd_abs_section_ptr;
-             sec->kept_section = l_sec;
+             asection *first = elf_next_in_group (sec);
+             asection *s = first;
 
-             if (flags & SEC_GROUP)
+             while (s != NULL)
                {
-                 asection *first = elf_next_in_group (sec);
-                 asection *s = first;
-
-                 while (s != NULL)
-                   {
-                     s->output_section = bfd_abs_section_ptr;
-                     /* Record which group discards it.  */
-                     s->kept_section = l_sec;
-                     s = elf_next_in_group (s);
-                     /* These lists are circular.  */
-                     if (s == first)
-                       break;
-                   }
+                 s->output_section = bfd_abs_section_ptr;
+                 /* Record which group discards it.  */
+                 s->kept_section = l->sec;
+                 s = elf_next_in_group (s);
+                 /* These lists are circular.  */
+                 if (s == first)
+                   break;
                }
            }
 
@@ -12711,108 +12589,67 @@ _bfd_elf_section_already_linked (bfd *abfd,
        }
     }
 
-  matched = FALSE;
-  if (sec)
+  /* A single member comdat group section may be discarded by a
+     linkonce section and vice versa.  */
+  if ((flags & SEC_GROUP) != 0)
     {
-      /* A single member comdat group section may be discarded by a
-        linkonce section and vice versa.  */
+      asection *first = elf_next_in_group (sec);
 
-      if ((flags & SEC_GROUP) != 0)
+      if (first != NULL && elf_next_in_group (first) == first)
+       /* Check this single member group against linkonce sections.  */
+       for (l = already_linked_list->entry; l != NULL; l = l->next)
+         if ((l->sec->flags & SEC_GROUP) == 0
+             && bfd_elf_match_symbols_in_sections (l->sec, first, info))
+           {
+             first->output_section = bfd_abs_section_ptr;
+             first->kept_section = l->sec;
+             sec->output_section = bfd_abs_section_ptr;
+             break;
+           }
+    }
+  else
+    /* Check this linkonce section against single member groups.  */
+    for (l = already_linked_list->entry; l != NULL; l = l->next)
+      if (l->sec->flags & SEC_GROUP)
        {
-         asection *first = elf_next_in_group (sec);
+         asection *first = elf_next_in_group (l->sec);
 
-         if (first != NULL && elf_next_in_group (first) == first)
-           /* Check this single member group against linkonce sections.  */
-           for (l = already_linked_list->entry; l != NULL; l = l->next)
-             {
-               if (l->linked.comdat_key == NULL)
-                 {
-                   l_sec = l->linked.u.sec;
-
-                   if ((l_sec->flags & SEC_GROUP) == 0
-                       && bfd_coff_get_comdat_section (l_sec->owner,
-                                                       l_sec) == NULL
-                       && bfd_elf_match_symbols_in_sections (l_sec,
-                                                             first,
-                                                             info))
-                     {
-                       first->output_section = bfd_abs_section_ptr;
-                       first->kept_section = l_sec;
-                       sec->output_section = bfd_abs_section_ptr;
-                       matched = TRUE;
-                       break;
-                     }
-                 }
-             }
+         if (first != NULL
+             && elf_next_in_group (first) == first
+             && bfd_elf_match_symbols_in_sections (first, sec, info))
+           {
+             sec->output_section = bfd_abs_section_ptr;
+             sec->kept_section = first;
+             break;
+           }
        }
-      else
-       /* Check this linkonce section against single member groups.  */
-       for (l = already_linked_list->entry; l != NULL; l = l->next)
-         {
-           if (l->linked.comdat_key == NULL)
-             {
-               l_sec = l->linked.u.sec;
-
-               if (l_sec->flags & SEC_GROUP)
-                 {
-                   asection *first = elf_next_in_group (l_sec);
-
-                   if (first != NULL
-                       && elf_next_in_group (first) == first
-                       && bfd_elf_match_symbols_in_sections (first,
-                                                             sec,
-                                                             info))
-                     {
-                       sec->output_section = bfd_abs_section_ptr;
-                       sec->kept_section = first;
-                       matched = TRUE;
-                       break;
-                     }
-                 }
-             }
-         }
-
-      /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
-        referencing its discarded `.gnu.linkonce.t.F' counterpart -
-        g++-3.4 specific as g++-4.x is using COMDAT groups (without the
-        `.gnu.linkonce' prefix) instead.  `.gnu.linkonce.r.*' were the
-        `.rodata' part of its matching `.gnu.linkonce.t.*'.  If
-        `.gnu.linkonce.r.F' is not discarded but its `.gnu.linkonce.t.F'
-        is discarded means we chose one-only `.gnu.linkonce.t.F' section
-        from a different bfd not requiring any `.gnu.linkonce.r.F'.
-        Thus `.gnu.linkonce.r.F' should be discarded.  The reverse order
-        cannot happen as there is never a bfd with only the
-        `.gnu.linkonce.r.F' section.  The order of sections in a bfd
-        does not matter as here were are looking only for cross-bfd
-        sections.  */
-
-      if ((flags & SEC_GROUP) == 0
-         && CONST_STRNEQ (name, ".gnu.linkonce.r."))
-       for (l = already_linked_list->entry; l != NULL; l = l->next)
-         {
-           if (l->linked.comdat_key == NULL)
-             {
-               l_sec = l->linked.u.sec;
 
-               if ((l_sec->flags & SEC_GROUP) == 0
-                   && CONST_STRNEQ (l_sec->name, ".gnu.linkonce.t."))
-                 {
-                   if (abfd != l_sec->owner)
-                     {
-                       sec->output_section = bfd_abs_section_ptr;
-                       matched = TRUE;
-                     }
-                   break;
-                 }
-             }
-         }
-    }
+  /* Do not complain on unresolved relocations in `.gnu.linkonce.r.F'
+     referencing its discarded `.gnu.linkonce.t.F' counterpart - g++-3.4
+     specific as g++-4.x is using COMDAT groups (without the `.gnu.linkonce'
+     prefix) instead.  `.gnu.linkonce.r.*' were the `.rodata' part of its
+     matching `.gnu.linkonce.t.*'.  If `.gnu.linkonce.r.F' is not discarded
+     but its `.gnu.linkonce.t.F' is discarded means we chose one-only
+     `.gnu.linkonce.t.F' section from a different bfd not requiring any
+     `.gnu.linkonce.r.F'.  Thus `.gnu.linkonce.r.F' should be discarded.
+     The reverse order cannot happen as there is never a bfd with only the
+     `.gnu.linkonce.r.F' section.  The order of sections in a bfd does not
+     matter as here were are looking only for cross-bfd sections.  */
+
+  if ((flags & SEC_GROUP) == 0 && CONST_STRNEQ (name, ".gnu.linkonce.r."))
+    for (l = already_linked_list->entry; l != NULL; l = l->next)
+      if ((l->sec->flags & SEC_GROUP) == 0
+         && CONST_STRNEQ (l->sec->name, ".gnu.linkonce.t."))
+       {
+         if (abfd != l->sec->owner)
+           sec->output_section = bfd_abs_section_ptr;
+         break;
+       }
 
   /* This is the first section with this name.  Record it.  */
-  if (! bfd_section_already_linked_table_insert (already_linked_list,
-                                                linked))
+  if (!bfd_section_already_linked_table_insert (already_linked_list, sec))
     info->callbacks->einfo (_("%F%P: already_linked_table: %E\n"));
-  return matched;
+  return sec->output_section == bfd_abs_section_ptr;
 }
 
 bfd_boolean
This page took 0.031091 seconds and 4 git commands to generate.