Don't add DT_NEEDED for unmatched symbol
[deliverable/binutils-gdb.git] / bfd / elflink.c
index 4f867004097beecb84d3f6cfcbba7b31f712f5e0..ac03ce5003adea4a8fef6481e638c02a7d85d177 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF linking support for BFD.
-   Copyright (C) 1995-2015 Free Software Foundation, Inc.
+   Copyright (C) 1995-2016 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -246,7 +246,7 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
 
   /* A dynamically linked executable has a .interp section, but a
      shared library does not.  */
-  if (bfd_link_executable (info))
+  if (bfd_link_executable (info) && !info->nointerp)
     {
       s = bfd_make_section_anyway_with_flags (abfd, ".interp",
                                              flags | SEC_READONLY);
@@ -1010,9 +1010,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
        *matched = TRUE;
       else
        {
-         /* OLD_HIDDEN is true if the existing symbol is only visibile
+         /* OLD_HIDDEN is true if the existing symbol is only visible
             to the symbol with the same symbol version.  NEW_HIDDEN is
-            true if the new symbol is only visibile to the symbol with
+            true if the new symbol is only visible to the symbol with
             the same symbol version.  */
          bfd_boolean old_hidden = h->versioned == versioned_hidden;
          bfd_boolean new_hidden = hi->versioned == versioned_hidden;
@@ -1715,6 +1715,13 @@ _bfd_elf_add_default_symbol (bfd *abfd,
            h->versioned = versioned;
        }
     }
+  else
+    {
+      /* PR ld/19073: We may see an unversioned definition after the
+        default version.  */
+      if (p == NULL)
+       return TRUE;
+    }
 
   bed = get_elf_backend_data (abfd);
   collect = bed->collect;
@@ -4216,7 +4223,7 @@ error_free_dyn:
 
          /* If this symbol has default visibility and the user has
             requested we not re-export it, then mark it as hidden.  */
-         if (definition
+         if (!bfd_is_und_section (sec)
              && !dynamic
              && abfd->no_export
              && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
@@ -4555,8 +4562,10 @@ error_free_dyn:
                break;
              }
 
-         /* Don't add DT_NEEDED for references from the dummy bfd.  */
+         /* Don't add DT_NEEDED for references from the dummy bfd nor
+            for unmatched symbol.  */
          if (!add_needed
+             && matched
              && definition
              && ((dynsym
                   && h->ref_regular_nonweak
@@ -5763,7 +5772,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
       bfd_boolean all_defined;
 
       *sinterpptr = bfd_get_linker_section (dynobj, ".interp");
-      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info));
+      BFD_ASSERT (*sinterpptr != NULL || !bfd_link_executable (info) || info->nointerp);
 
       if (soname != NULL)
        {
@@ -6814,7 +6823,7 @@ merge_sections_remove_hook (bfd *abfd ATTRIBUTE_UNUSED,
 /* Finish SHF_MERGE section merging.  */
 
 bfd_boolean
-_bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
+_bfd_elf_merge_sections (bfd *obfd, struct bfd_link_info *info)
 {
   bfd *ibfd;
   asection *sec;
@@ -6823,7 +6832,10 @@ _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
     return FALSE;
 
   for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
-    if ((ibfd->flags & DYNAMIC) == 0)
+    if ((ibfd->flags & DYNAMIC) == 0
+       && bfd_get_flavour (ibfd) == bfd_target_elf_flavour
+       && (elf_elfheader (ibfd)->e_ident[EI_CLASS]
+           == get_elf_backend_data (obfd)->s->elfclass))
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
        if ((sec->flags & SEC_MERGE) != 0
            && !bfd_is_abs_section (sec->output_section))
@@ -6831,7 +6843,7 @@ _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
            struct bfd_elf_section_data *secdata;
 
            secdata = elf_section_data (sec);
-           if (! _bfd_add_merge_section (abfd,
+           if (! _bfd_add_merge_section (obfd,
                                          &elf_hash_table (info)->merge_info,
                                          sec, &secdata->sec_info))
              return FALSE;
@@ -6840,7 +6852,7 @@ _bfd_elf_merge_sections (bfd *abfd, struct bfd_link_info *info)
          }
 
   if (elf_hash_table (info)->merge_info != NULL)
-    _bfd_merge_sections (abfd, info, elf_hash_table (info)->merge_info,
+    _bfd_merge_sections (obfd, info, elf_hash_table (info)->merge_info,
                         merge_sections_remove_hook);
   return TRUE;
 }
@@ -8193,7 +8205,7 @@ ext64b_r_offset (const void *p)
    referenced must be updated.  Update all the relocations found in
    RELDATA.  */
 
-static void
+static bfd_boolean
 elf_link_adjust_relocs (bfd *abfd,
                        struct bfd_elf_section_reloc_data *reldata,
                        bfd_boolean sort)
@@ -8259,7 +8271,7 @@ elf_link_adjust_relocs (bfd *abfd,
       bfd_vma r_off;
       size_t elt_size;
       bfd_byte *base, *end, *p, *loc;
-      bfd_byte buf[sizeof (Elf64_External_Rela)];
+      bfd_byte *buf = NULL;
 
       if (bed->s->arch_size == 32)
        {
@@ -8282,12 +8294,12 @@ elf_link_adjust_relocs (bfd *abfd,
            abort ();
        }
 
-      /*  Must use a stable sort here.  Insertion sort, since the
-         relocs are mostly sorted already.  */
+      /*  Must use a stable sort here.  A modified insertion sort,
+         since the relocs are mostly sorted already.  */
       elt_size = reldata->hdr->sh_entsize;
       base = reldata->hdr->contents;
       end = base + count * elt_size;
-      if (elt_size > sizeof (buf))
+      if (elt_size > sizeof (Elf64_External_Rela))
        abort ();
 
       /* Ensure the first element is lowest.  This acts as a sentinel,
@@ -8307,9 +8319,10 @@ elf_link_adjust_relocs (bfd *abfd,
          /* Don't just swap *base and *loc as that changes the order
             of the original base[0] and base[1] if they happen to
             have the same r_offset.  */
-         memcpy (buf, loc, elt_size);
+         bfd_byte onebuf[sizeof (Elf64_External_Rela)];
+         memcpy (onebuf, loc, elt_size);
          memmove (base + elt_size, base, loc - base);
-         memcpy (base, buf, elt_size);
+         memcpy (base, onebuf, elt_size);
        }
 
       for (p = base + elt_size; (p += elt_size) < end; )
@@ -8323,15 +8336,46 @@ elf_link_adjust_relocs (bfd *abfd,
          loc += elt_size;
          if (loc != p)
            {
-             memcpy (buf, p, elt_size);
-             memmove (loc + elt_size, loc, p - loc);
-             memcpy (loc, buf, elt_size);
+             /* Chances are there is a run of relocs to insert here,
+                from one of more input files.  Files are not always
+                linked in order due to the way elf_link_input_bfd is
+                called.  See pr17666.  */
+             size_t sortlen = p - loc;
+             bfd_vma r_off2 = (*ext_r_off) (loc);
+             size_t runlen = elt_size;
+             size_t buf_size = 96 * 1024;
+             while (p + runlen < end
+                    && (sortlen <= buf_size
+                        || runlen + elt_size <= buf_size)
+                    && r_off2 > (*ext_r_off) (p + runlen))
+               runlen += elt_size;
+             if (buf == NULL)
+               {
+                 buf = bfd_malloc (buf_size);
+                 if (buf == NULL)
+                   return FALSE;
+               }
+             if (runlen < sortlen)
+               {
+                 memcpy (buf, p, runlen);
+                 memmove (loc + runlen, loc, sortlen);
+                 memcpy (loc, buf, runlen);
+               }
+             else
+               {
+                 memcpy (buf, loc, sortlen);
+                 memmove (loc, p, runlen);
+                 memcpy (loc + runlen, buf, sortlen);
+               }
+             p += runlen - elt_size;
            }
        }
       /* Hashes are no longer valid.  */
       free (reldata->hashes);
       reldata->hashes = NULL;
+      free (buf);
     }
+  return TRUE;
 }
 
 struct elf_link_sort_rela
@@ -10946,6 +10990,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       for (p = o->map_head.link_order; p != NULL; p = p->next)
        {
          unsigned int reloc_count = 0;
+         unsigned int additional_reloc_count = 0;
          struct bfd_elf_section_data *esdi = NULL;
 
          if (p->type == bfd_section_reloc_link_order
@@ -10974,7 +11019,15 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                   reloc sections themselves can't have relocations.  */
                reloc_count = 0;
              else if (emit_relocs)
-               reloc_count = sec->reloc_count;
+               {
+                 reloc_count = sec->reloc_count;
+                 if (bed->elf_backend_count_additional_relocs)
+                   {
+                     int c;
+                     c = (*bed->elf_backend_count_additional_relocs) (sec);
+                     additional_reloc_count += c;
+                   }
+               }
              else if (bed->elf_backend_count_relocs)
                reloc_count = (*bed->elf_backend_count_relocs) (info, sec);
 
@@ -11000,7 +11053,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                    max_sym_count = sym_count;
 
                  if (sym_count > max_sym_shndx_count
-                     && elf_symtab_shndx (sec->owner) != 0)
+                     && elf_symtab_shndx_list (sec->owner) != NULL)
                    max_sym_shndx_count = sym_count;
 
                  if ((sec->flags & SEC_RELOC) != 0)
@@ -11023,14 +11076,21 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
          if (reloc_count == 0)
            continue;
 
+         reloc_count += additional_reloc_count;
          o->reloc_count += reloc_count;
 
          if (p->type == bfd_indirect_link_order && emit_relocs)
            {
              if (esdi->rel.hdr)
-               esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr);
+               {
+                 esdo->rel.count += NUM_SHDR_ENTRIES (esdi->rel.hdr);
+                 esdo->rel.count += additional_reloc_count;
+               }
              if (esdi->rela.hdr)
-               esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr);
+               {
+                 esdo->rela.count += NUM_SHDR_ENTRIES (esdi->rela.hdr);
+                 esdo->rela.count += additional_reloc_count;
+               }
            }
          else
            {
@@ -11337,15 +11397,20 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
                    {
                      const char *iclass, *oclass;
 
-                     if (bed->s->elfclass == ELFCLASS64)
+                     switch (bed->s->elfclass)
                        {
-                         iclass = "ELFCLASS32";
-                         oclass = "ELFCLASS64";
+                       case ELFCLASS64: oclass = "ELFCLASS64"; break;
+                       case ELFCLASS32: oclass = "ELFCLASS32"; break;
+                       case ELFCLASSNONE: oclass = "ELFCLASSNONE"; break;
+                       default: abort ();
                        }
-                     else
+
+                     switch (elf_elfheader (sub)->e_ident[EI_CLASS])
                        {
-                         iclass = "ELFCLASS64";
-                         oclass = "ELFCLASS32";
+                       case ELFCLASS64: iclass = "ELFCLASS64"; break;
+                       case ELFCLASS32: iclass = "ELFCLASS32"; break;
+                       case ELFCLASSNONE: iclass = "ELFCLASSNONE"; break;
+                       default: abort ();
                        }
 
                      bfd_set_error (bfd_error_wrong_format);
@@ -11530,8 +11595,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
       Elf_Internal_Shdr *symstrtab_hdr;
       file_ptr off = symtab_hdr->sh_offset + symtab_hdr->sh_size;
 
-      symtab_shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
-      if (symtab_shndx_hdr->sh_name != 0)
+      symtab_shndx_hdr = & elf_symtab_shndx_list (abfd)->hdr;
+      if (symtab_shndx_hdr != NULL && symtab_shndx_hdr->sh_name != 0)
        {
          symtab_shndx_hdr->sh_type = SHT_SYMTAB_SHNDX;
          symtab_shndx_hdr->sh_entsize = sizeof (Elf_External_Sym_Shndx);
@@ -11577,10 +11642,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
        continue;
 
       sort = bed->sort_relocs_p == NULL || (*bed->sort_relocs_p) (o);
-      if (esdo->rel.hdr != NULL)
-       elf_link_adjust_relocs (abfd, &esdo->rel, sort);
-      if (esdo->rela.hdr != NULL)
-       elf_link_adjust_relocs (abfd, &esdo->rela, sort);
+      if (esdo->rel.hdr != NULL
+         && !elf_link_adjust_relocs (abfd, &esdo->rel, sort))
+       return FALSE;
+      if (esdo->rela.hdr != NULL
+         && !elf_link_adjust_relocs (abfd, &esdo->rela, sort))
+       return FALSE;
 
       /* Set the reloc_count field to 0 to prevent write_relocs from
         trying to swap the relocs out itself.  */
@@ -12022,8 +12089,6 @@ _bfd_elf_gc_mark_hook (asection *sec,
                       struct elf_link_hash_entry *h,
                       Elf_Internal_Sym *sym)
 {
-  const char *sec_name;
-
   if (h != NULL)
     {
       switch (h->root.type)
@@ -12035,33 +12100,6 @@ _bfd_elf_gc_mark_hook (asection *sec,
        case bfd_link_hash_common:
          return h->root.u.c.p->section;
 
-       case bfd_link_hash_undefined:
-       case bfd_link_hash_undefweak:
-         /* To work around a glibc bug, keep all XXX input sections
-            when there is an as yet undefined reference to __start_XXX
-            or __stop_XXX symbols.  The linker will later define such
-            symbols for orphan input sections that have a name
-            representable as a C identifier.  */
-         if (strncmp (h->root.root.string, "__start_", 8) == 0)
-           sec_name = h->root.root.string + 8;
-         else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
-           sec_name = h->root.root.string + 7;
-         else
-           sec_name = NULL;
-
-         if (sec_name && *sec_name != '\0')
-           {
-             bfd *i;
-
-             for (i = info->input_bfds; i; i = i->link.next)
-               {
-                 sec = bfd_get_section_by_name (i, sec_name);
-                 if (sec)
-                   sec->flags |= SEC_KEEP;
-               }
-           }
-         break;
-
        default:
          break;
        }
@@ -12079,7 +12117,8 @@ _bfd_elf_gc_mark_hook (asection *sec,
 asection *
 _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
                       elf_gc_mark_hook_fn gc_mark_hook,
-                      struct elf_reloc_cookie *cookie)
+                      struct elf_reloc_cookie *cookie,
+                      bfd_boolean *start_stop)
 {
   unsigned long r_symndx;
   struct elf_link_hash_entry *h;
@@ -12108,6 +12147,38 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec,
         handling copy relocs.  */
       if (h->u.weakdef != NULL)
        h->u.weakdef->mark = 1;
+
+      if (start_stop != NULL
+         && (h->root.type == bfd_link_hash_undefined
+             || h->root.type == bfd_link_hash_undefweak))
+       {
+         /* To work around a glibc bug, mark all XXX input sections
+            when there is an as yet undefined reference to __start_XXX
+            or __stop_XXX symbols.  The linker will later define such
+            symbols for orphan input sections that have a name
+            representable as a C identifier.  */
+         const char *sec_name = NULL;
+         if (strncmp (h->root.root.string, "__start_", 8) == 0)
+           sec_name = h->root.root.string + 8;
+         else if (strncmp (h->root.root.string, "__stop_", 7) == 0)
+           sec_name = h->root.root.string + 7;
+
+         if (sec_name != NULL && *sec_name != '\0')
+           {
+             bfd *i;
+
+             for (i = info->input_bfds; i != NULL; i = i->link.next)
+               {
+                 asection *s = bfd_get_section_by_name (i, sec_name);
+                 if (s != NULL && !s->gc_mark)
+                   {
+                     *start_stop = TRUE;
+                     return s;
+                   }
+               }
+           }
+       }
+
       return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL);
     }
 
@@ -12126,15 +12197,22 @@ _bfd_elf_gc_mark_reloc (struct bfd_link_info *info,
                        struct elf_reloc_cookie *cookie)
 {
   asection *rsec;
+  bfd_boolean start_stop = FALSE;
 
-  rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie);
-  if (rsec && !rsec->gc_mark)
+  rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie, &start_stop);
+  while (rsec != NULL)
     {
-      if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour
-         || (rsec->owner->flags & DYNAMIC) != 0)
-       rsec->gc_mark = 1;
-      else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
-       return FALSE;
+      if (!rsec->gc_mark)
+       {
+         if (bfd_get_flavour (rsec->owner) != bfd_target_elf_flavour
+             || (rsec->owner->flags & DYNAMIC) != 0)
+           rsec->gc_mark = 1;
+         else if (!_bfd_elf_gc_mark (info, rsec, gc_mark_hook))
+           return FALSE;
+       }
+      if (!start_stop)
+       break;
+      rsec = bfd_get_next_section_by_name (rsec->owner, rsec);
     }
   return TRUE;
 }
@@ -12685,7 +12763,7 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info)
              && (sec->flags & SEC_LINKER_CREATED) == 0)
            elf_eh_frame_section (sub) = sec;
          fini_reloc_cookie_for_section (&cookie, sec);
-         sec = bfd_get_next_section_by_name (sec);
+         sec = bfd_get_next_section_by_name (NULL, sec);
        }
     }
 
This page took 0.035673 seconds and 4 git commands to generate.