daily update
[deliverable/binutils-gdb.git] / bfd / elflink.c
index f47d4646f4696147973e251ebff93a8403a1bae6..418004289310255a4287914ea6c66f398484ffd9 100644 (file)
@@ -252,9 +252,13 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
   flags = bed->dynamic_sec_flags;
 
   pltflags = flags;
-  pltflags |= SEC_CODE;
   if (bed->plt_not_loaded)
+    /* We do not clear SEC_ALLOC here because we still want the OS to
+       allocate space for the section; it's just that there's nothing
+       to read in from the object file.  */
     pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
+  else
+    pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
   if (bed->plt_readonly)
     pltflags |= SEC_READONLY;
 
@@ -3778,6 +3782,14 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
            (*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 (isym->st_other != 0 && !dynamic)
            {
              unsigned char hvis, symvis, other, nvis;
@@ -6374,30 +6386,40 @@ elf_section_ignore_discarded_relocs (asection *sec)
   return FALSE;
 }
 
-/* Return TRUE if we should complain about a reloc in SEC against a
-   symbol defined in a discarded section.  */
-
-static bfd_boolean
-elf_section_complain_discarded (asection *sec)
+enum action_discarded
+  {
+    COMPLAIN = 1,
+    PRETEND = 2
+  };
+
+/* Return a mask saying how ld should treat relocations in SEC against
+   symbols defined in discarded sections.  If this function returns
+   COMPLAIN set, ld will issue a warning message.  If this function
+   returns PRETEND set, and the discarded section was link-once and the
+   same size as the kept link-once section, ld will pretend that the
+   symbol was actually defined in the kept section.  Otherwise ld will
+   zero the reloc (at least that is the intent, but some cooperation by
+   the target dependent code is needed, particularly for REL targets).  */
+
+static unsigned int
+elf_action_discarded (asection *sec)
 {
-  if (strncmp (".stab", sec->name, 5) == 0
-      && (!sec->name[5] ||
-         (sec->name[5] == '.' && ISDIGIT (sec->name[6]))))
-    return FALSE;
+  if (sec->flags & SEC_DEBUGGING)
+    return PRETEND;
 
   if (strcmp (".eh_frame", sec->name) == 0)
-    return FALSE;
+    return 0;
 
   if (strcmp (".gcc_except_table", sec->name) == 0)
-    return FALSE;
+    return 0;
 
   if (strcmp (".PARISC.unwind", sec->name) == 0)
-    return FALSE;
+    return 0;
 
   if (strcmp (".fixup", sec->name) == 0)
-    return FALSE;
+    return 0;
 
-  return TRUE;
+  return COMPLAIN | PRETEND;
 }
 
 /* Find a match between a section and a member of a section group.  */
@@ -6692,7 +6714,7 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
          if (!elf_section_ignore_discarded_relocs (o))
            {
              Elf_Internal_Rela *rel, *relend;
-             bfd_boolean complain = elf_section_complain_discarded (o);
+             unsigned int action = elf_action_discarded (o);
 
              rel = internal_relocs;
              relend = rel + o->reloc_count * bed->s->int_rels_per_ext_rel;
@@ -6733,44 +6755,10 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                     discarded section.  */
                  if ((sec = *ps) != NULL && elf_discarded_section (sec))
                    {
-                     if ((o->flags & SEC_DEBUGGING) != 0)
-                       {
-                         BFD_ASSERT (r_symndx != 0);
-
-                         /* Try to preserve debug information.
-                            FIXME: This is quite broken.  Modifying
-                            the symbol here means we will be changing
-                            all uses of the symbol, not just those in
-                            debug sections.  The only thing that makes
-                            this half reasonable is that debug sections
-                            tend to come after other sections.  Of
-                            course, that doesn't help with globals.
-                            ??? All link-once sections of the same name
-                            ought to define the same set of symbols, so
-                            it would seem that globals ought to always
-                            be defined in the kept section.  */
-                         if (sec->kept_section != NULL)
-                           {
-                             asection *member;
+                     asection *kept;
 
-                             /* Check if it is a linkonce section or
-                                member of a comdat group.  */
-                             if (elf_sec_group (sec) == NULL
-                                 && sec->size == sec->kept_section->size)
-                               {
-                                 *ps = sec->kept_section;
-                                 continue;
-                               }
-                             else if (elf_sec_group (sec) != NULL
-                                      && (member = match_group_member (sec, sec->kept_section))
-                                      && sec->size == member->size)
-                               {
-                                 *ps = member;
-                                 continue;
-                               }
-                           }
-                       }
-                     else if (complain)
+                     BFD_ASSERT (r_symndx != 0);
+                     if (action & COMPLAIN)
                        {
                          (*_bfd_error_handler)
                            (_("`%s' referenced in section `%A' of %B: "
@@ -6778,6 +6766,30 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                             o, input_bfd, sec, sec->owner, sym_name);
                        }
 
+                     /* Try to do the best we can to support buggy old
+                        versions of gcc.  If we've warned, or this is
+                        debugging info, pretend that the symbol is
+                        really defined in the kept linkonce section.
+                        FIXME: This is quite broken.  Modifying the
+                        symbol here means we will be changing all later
+                        uses of the symbol, not just in this section.
+                        The only thing that makes this half reasonable
+                        is that we warn in non-debug sections, and
+                        debug sections tend to come after other
+                        sections.  */
+                     kept = sec->kept_section;
+                     if (kept != NULL && (action & PRETEND))
+                       {
+                         if (elf_sec_group (sec) != NULL)
+                           kept = match_group_member (sec, kept);
+                         if (kept != NULL
+                             && sec->size == kept->size)
+                           {
+                             *ps = kept;
+                             continue;
+                           }
+                       }
+
                      /* Remove the symbol reference from the reloc, but
                         don't kill the reloc completely.  This is so that
                         a zero value will be written into the section,
@@ -6788,21 +6800,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
                      rel->r_info &= r_type_mask;
                      rel->r_addend = 0;
                    }
-
-                 /* Check that loaded segments don't reference symbols
-                    in non-loaded segments.  */
-                 if ((o->flags & SEC_ALLOC) != 0
-                     && sec != NULL
-                     && !bfd_is_abs_section (sec)
-                     && !elf_discarded_section (sec)
-                     && sec->output_section != NULL
-                     && (sec->output_section->flags & SEC_ALLOC) == 0)
-                   {
-                     (*_bfd_error_handler)
-                       (_("`%s' referenced in section `%A' of %B: "
-                          "defined in non-loaded section `%A' of %B\n"),
-                        o, input_bfd, sec, sec->owner, sym_name);
-                   }
                }
            }
 
@@ -7219,7 +7216,8 @@ elf_reloc_link_order (bfd *output_bfd,
          else
            sym_name = link_order->u.reloc.p->u.name;
          if (! ((*info->callbacks->reloc_overflow)
-                (info, sym_name, howto->name, addend, NULL, NULL, 0)))
+                (info, NULL, sym_name, howto->name, addend, NULL,
+                 NULL, (bfd_vma) 0)))
            {
              free (buf);
              return FALSE;
@@ -9283,88 +9281,11 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
   return ret;
 }
 
-struct already_linked_section
-{
-  asection *sec;
-  asection *linked;
-};
-
-/* Check if the member of a single member comdat group matches a
-   linkonce section and vice versa.  */
-static bfd_boolean
-try_match_symbols_in_sections
-  (struct bfd_section_already_linked_hash_entry *h, void *info)
-{
-  struct bfd_section_already_linked *l;
-  struct already_linked_section *s
-    = (struct already_linked_section *) info;
-
-  if (elf_sec_group (s->sec) == NULL)
-    {
-      /* It is a linkonce section. Try to match it with the member of a
-        single member comdat group. */
-      for (l = h->entry; l != NULL; l = l->next)
-       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, s->sec))
-             {
-               s->linked = first;
-               return FALSE;
-             }
-         }
-    }
-  else
-    {
-      /* It is the member of a single member comdat group. Try to match
-        it with a linkonce section.  */
-      for (l = h->entry; l != NULL; l = l->next)
-       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, s->sec))
-         {
-           s->linked = l->sec;
-           return FALSE;
-         }
-    }
-
-  return TRUE;
-}
-
-static bfd_boolean
-already_linked (asection *sec, asection *group)
-{
-  struct already_linked_section result;
-
-  result.sec = sec;
-  result.linked = NULL;
-
-  bfd_section_already_linked_table_traverse
-    (try_match_symbols_in_sections, &result);
-
-  if (result.linked)
-    {
-      sec->output_section = bfd_abs_section_ptr;
-      sec->kept_section = result.linked;
-
-      /* Also discard the group section.  */
-      if (group)
-       group->output_section = bfd_abs_section_ptr;
-
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
 void
 _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
 {
   flagword flags;
-  const char *name;
+  const char *name, *p;
   struct bfd_section_already_linked *l;
   struct bfd_section_already_linked_hash_entry *already_linked_list;
   asection *group;
@@ -9414,7 +9335,13 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
 
   name = bfd_get_section_name (abfd, sec);
 
-  already_linked_list = bfd_section_already_linked_table_lookup (name);
+  if (strncmp (name, ".gnu.linkonce.", sizeof (".gnu.linkonce.") - 1) == 0
+      && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL)
+    p++;
+  else
+    p = name;
+
+  already_linked_list = bfd_section_already_linked_table_lookup (p);
 
   for (l = already_linked_list->entry; l != NULL; l = l->next)
     {
@@ -9424,10 +9351,11 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
         a linkonce section with a linkonce section, and ignore comdat
         section.  */
       if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+         && strcmp (name, l->sec->name) == 0
          && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
        {
          /* The section has already been linked.  See if we should
-             issue a warning.  */
+            issue a warning.  */
          switch (flags & SEC_LINK_DUPLICATES)
            {
            default:
@@ -9516,15 +9444,39 @@ _bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
         section. We only record the discarded comdat group. Otherwise
         the undiscarded group will be discarded incorrectly later since
         itself has been recorded.  */
-      if (! already_linked (elf_next_in_group (sec), group))
+      for (l = already_linked_list->entry; l != NULL; l = l->next)
+       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,
+                                                 elf_next_in_group (sec)))
+         {
+           elf_next_in_group (sec)->output_section = bfd_abs_section_ptr;
+           elf_next_in_group (sec)->kept_section = l->sec;
+           group->output_section = bfd_abs_section_ptr;
+           break;
+         }
+      if (l == NULL)
        return;
     }
   else
     /* There is no direct match. But for linkonce section, we should
        check if there is a match with comdat group member. We always
        record the linkonce section, discarded or not.  */
-    already_linked (sec, group);
-  
+    for (l = already_linked_list->entry; l != NULL; l = l->next)
+      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))
+           {
+             sec->output_section = bfd_abs_section_ptr;
+             sec->kept_section = l->sec;
+             break;
+           }
+       }
+
   /* This is the first section with this name.  Record it.  */
   bfd_section_already_linked_table_insert (already_linked_list, sec);
 }
This page took 0.028534 seconds and 4 git commands to generate.