Don't add DT_NEEDED for unmatched symbol
[deliverable/binutils-gdb.git] / bfd / elf64-x86-64.c
index f8bb0d5e4ec54db3b6fb0e4eb4b61942902c9ae4..88ed00e2d16ff0d2c002dad0489efc4f438f8751 100644 (file)
@@ -1,5 +1,5 @@
 /* X86-64 specific support for ELF
-   Copyright (C) 2000-2015 Free Software Foundation, Inc.
+   Copyright (C) 2000-2016 Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -3127,12 +3127,22 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
          /* STT_GNU_IFUNC must keep GOTPCREL relocations.  We also
             avoid optimizing GOTPCREL relocations againt _DYNAMIC
             since ld.so may use its link-time address.  */
-         if ((h->root.type == bfd_link_hash_defined
+         if ((h->def_regular
+              || h->root.type == bfd_link_hash_defined
               || h->root.type == bfd_link_hash_defweak)
              && h->type != STT_GNU_IFUNC
              && h != htab->elf.hdynamic
              && SYMBOL_REFERENCES_LOCAL (link_info, h))
            {
+             /* bfd_link_hash_new or bfd_link_hash_undefined is
+                set by an assignment in a linker script in
+                bfd_elf_record_link_assignment.  FIXME: If we
+                ever get a linker error due relocation overflow,
+                we will skip this optimization.  */
+             if (h->def_regular
+                 && (h->root.type == bfd_link_hash_new
+                     || h->root.type == bfd_link_hash_undefined))
+               goto convert;
              tsec = h->root.u.def.section;
              toff = h->root.u.def.value;
              symtype = h->type;
@@ -3213,10 +3223,12 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
            continue;
        }
 
+convert:
       if (opcode == 0xff)
        {
          /* We have "call/jmp *foo@GOTPCREL(%rip)".  */
          unsigned int nop;
+         unsigned int disp;
          bfd_vma nop_offset;
 
          /* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to
@@ -3224,7 +3236,6 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
          modrm = bfd_get_8 (abfd, contents + roff - 1);
          if (modrm == 0x25)
            {
-             unsigned int disp;
              /* Convert to "jmp foo nop".  */
              modrm = 0xe9;
              nop = NOP_OPCODE;
@@ -3238,8 +3249,16 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
              /* Convert to "nop call foo".  ADDR_PREFIX_OPCODE
                 is a nop prefix.  */
              modrm = 0xe8;
-             nop = ADDR_PREFIX_OPCODE;
-             nop_offset = irel->r_offset - 2;
+             nop = link_info->call_nop_byte;
+             if (link_info->call_nop_as_suffix)
+               {
+                 nop_offset = irel->r_offset + 3;
+                 disp = bfd_get_32 (abfd, contents + irel->r_offset);
+                 irel->r_offset -= 1;
+                 bfd_put_32 (abfd, disp, contents + irel->r_offset);
+               }
+             else
+               nop_offset = irel->r_offset - 2;
            }
          bfd_put_8 (abfd, nop, contents + nop_offset);
          bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
@@ -3850,6 +3869,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
   bfd_vma *local_got_offsets;
   bfd_vma *local_tlsdesc_gotents;
   Elf_Internal_Rela *rel;
+  Elf_Internal_Rela *wrel;
   Elf_Internal_Rela *relend;
   const unsigned int plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd);
 
@@ -3865,9 +3885,9 @@ elf_x86_64_relocate_section (bfd *output_bfd,
 
   elf_x86_64_set_tls_module_base (info);
 
-  rel = relocs;
+  rel = wrel = relocs;
   relend = relocs + input_section->reloc_count;
-  for (; rel < relend; rel++)
+  for (; rel < relend; wrel++, rel++)
     {
       unsigned int r_type;
       reloc_howto_type *howto;
@@ -3887,7 +3907,11 @@ elf_x86_64_relocate_section (bfd *output_bfd,
       r_type = ELF32_R_TYPE (rel->r_info);
       if (r_type == (int) R_X86_64_GNU_VTINHERIT
          || r_type == (int) R_X86_64_GNU_VTENTRY)
-       continue;
+       {
+         if (wrel != rel)
+           *wrel = *rel;
+         continue;
+       }
 
       if (r_type >= (int) R_X86_64_standard)
        {
@@ -3945,11 +3969,29 @@ elf_x86_64_relocate_section (bfd *output_bfd,
        }
 
       if (sec != NULL && discarded_section (sec))
-       RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
-                                        rel, 1, relend, howto, 0, contents);
+       {
+         _bfd_clear_contents (howto, input_bfd, input_section,
+                              contents + rel->r_offset);
+         wrel->r_offset = rel->r_offset;
+         wrel->r_info = 0;
+         wrel->r_addend = 0;
+
+         /* For ld -r, remove relocations in debug sections against
+            sections defined in discarded sections.  Not done for
+            eh_frame editing code expects to be present.  */
+          if (bfd_link_relocatable (info)
+              && (input_section->flags & SEC_DEBUGGING))
+            wrel--;
+
+         continue;
+       }
 
       if (bfd_link_relocatable (info))
-       continue;
+       {
+         if (wrel != rel)
+           *wrel = *rel;
+         continue;
+       }
 
       if (rel->r_addend == 0 && !ABI_64_P (output_bfd))
        {
@@ -4766,6 +4808,7 @@ direct:
                              contents + roff + 8 + largepic);
                  /* Skip R_X86_64_PC32/R_X86_64_PLT32/R_X86_64_PLTOFF64.  */
                  rel++;
+                 wrel++;
                  continue;
                }
              else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
@@ -5048,6 +5091,7 @@ direct:
                              contents + roff + 8 + largepic);
                  /* Skip R_X86_64_PLT32/R_X86_64_PLTOFF64.  */
                  rel++;
+                 wrel++;
                  continue;
                }
              else if (ELF32_R_TYPE (rel->r_info) == R_X86_64_GOTPC32_TLSDESC)
@@ -5132,6 +5176,7 @@ direct:
                        "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12);
              /* Skip R_X86_64_PC32/R_X86_64_PLT32/R_X86_64_PLTOFF64.  */
              rel++;
+             wrel++;
              continue;
            }
 
@@ -5248,6 +5293,29 @@ check_relocation_error:
              return FALSE;
            }
        }
+
+      if (wrel != rel)
+       *wrel = *rel;
+    }
+
+  if (wrel != rel)
+    {
+      Elf_Internal_Shdr *rel_hdr;
+      size_t deleted = rel - wrel;
+
+      rel_hdr = _bfd_elf_single_rel_hdr (input_section->output_section);
+      rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+      if (rel_hdr->sh_size == 0)
+       {
+         /* It is too late to remove an empty reloc section.  Leave
+            one NONE reloc.
+            ??? What is wrong with an empty section???  */
+         rel_hdr->sh_size = rel_hdr->sh_entsize;
+         deleted -= 1;
+       }
+      rel_hdr = _bfd_elf_single_rel_hdr (input_section);
+      rel_hdr->sh_size -= rel_hdr->sh_entsize * deleted;
+      input_section->reloc_count -= deleted;
     }
 
   return TRUE;
@@ -5660,19 +5728,23 @@ elf_x86_64_reloc_type_class (const struct bfd_link_info *info,
   bfd *abfd = info->output_bfd;
   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
   struct elf_x86_64_link_hash_table *htab = elf_x86_64_hash_table (info);
-  unsigned long r_symndx = htab->r_sym (rela->r_info);
-  Elf_Internal_Sym sym;
-
-  if (htab->elf.dynsym == NULL
-      || !bed->s->swap_symbol_in (abfd,
-                                 (htab->elf.dynsym->contents
-                                  + r_symndx * bed->s->sizeof_sym),
-                                 0, &sym))
-    abort ();
 
-  /* Check relocation against STT_GNU_IFUNC symbol.  */
-  if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
-    return reloc_class_ifunc;
+  if (htab->elf.dynsym != NULL
+      && htab->elf.dynsym->contents != NULL)
+    {
+      /* Check relocation against STT_GNU_IFUNC symbol if there are
+         dynamic symbols.  */
+      unsigned long r_symndx = htab->r_sym (rela->r_info);
+      Elf_Internal_Sym sym;
+      if (!bed->s->swap_symbol_in (abfd,
+                                  (htab->elf.dynsym->contents
+                                   + r_symndx * bed->s->sizeof_sym),
+                                  0, &sym))
+       abort ();
+
+      if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
+       return reloc_class_ifunc;
+    }
 
   switch ((int) ELF32_R_TYPE (rela->r_info))
     {
@@ -5994,19 +6066,20 @@ bad_return:
 
       reloc_index = H_GET_32 (abfd, (plt_contents + plt_offset
                                     + bed->plt_reloc_offset));
-      if (reloc_index >= count)
-       abort ();
-      if (plt_bnd)
+      if (reloc_index < count)
        {
-         /* This is the index in .plt section.  */
-         long plt_index = plt_offset / bed->plt_entry_size;
-         /* Store VMA + the offset in .plt.bnd section.  */
-         plt_sym_val[reloc_index] =
-           (plt_bnd->vma
-            + (plt_index - 1) * sizeof (elf_x86_64_legacy_plt2_entry));
+         if (plt_bnd)
+           {
+             /* This is the index in .plt section.  */
+             long plt_index = plt_offset / bed->plt_entry_size;
+             /* Store VMA + the offset in .plt.bnd section.  */
+             plt_sym_val[reloc_index] =
+               (plt_bnd->vma
+                + (plt_index - 1) * sizeof (elf_x86_64_legacy_plt2_entry));
+           }
+         else
+           plt_sym_val[reloc_index] = plt->vma + plt_offset;
        }
-      else
-       plt_sym_val[reloc_index] = plt->vma + plt_offset;
       plt_offset += bed->plt_entry_size;
 
       /* PR binutils/18437: Skip extra relocations in the .rela.plt
This page took 0.028011 seconds and 4 git commands to generate.