daily update
[deliverable/binutils-gdb.git] / bfd / elfnn-aarch64.c
index 3424ae2f8f723fad0982e02fc52ac363dab40caa..4dfb6043ae67564fb39173d625e80389f85a6833 100644 (file)
@@ -1,5 +1,5 @@
 /* AArch64-specific support for NN-bit ELF.
-   Copyright 2009-2013  Free Software Foundation, Inc.
+   Copyright (C) 2009-2014 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -1297,7 +1297,11 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
+#if ARCH_SIZE == 64
+        AARCH64_R_STR (TLS_DTPMOD64),  /* name */
+#else
         AARCH64_R_STR (TLS_DTPMOD),    /* name */
+#endif
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         ALL_ONES,              /* dst_mask */
@@ -1311,7 +1315,11 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
+#if ARCH_SIZE == 64
+        AARCH64_R_STR (TLS_DTPREL64),  /* name */
+#else
         AARCH64_R_STR (TLS_DTPREL),    /* name */
+#endif
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         ALL_ONES,              /* dst_mask */
@@ -1325,7 +1333,11 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
+#if ARCH_SIZE == 64
+        AARCH64_R_STR (TLS_TPREL64),   /* name */
+#else
         AARCH64_R_STR (TLS_TPREL),     /* name */
+#endif
         FALSE,                 /* partial_inplace */
         0,                     /* src_mask */
         ALL_ONES,              /* dst_mask */
@@ -1536,9 +1548,9 @@ elfNN_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
-#define TARGET_LITTLE_SYM               bfd_elfNN_littleaarch64_vec
+#define TARGET_LITTLE_SYM               aarch64_elfNN_le_vec
 #define TARGET_LITTLE_NAME              "elfNN-littleaarch64"
-#define TARGET_BIG_SYM                  bfd_elfNN_bigaarch64_vec
+#define TARGET_BIG_SYM                  aarch64_elfNN_be_vec
 #define TARGET_BIG_NAME                 "elfNN-bigaarch64"
 
 /* The linker script knows the section names for placement.
@@ -2043,6 +2055,23 @@ elfNN_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 
+/* Destroy an AArch64 elf linker hash table.  */
+
+static void
+elfNN_aarch64_link_hash_table_free (bfd *obfd)
+{
+  struct elf_aarch64_link_hash_table *ret
+    = (struct elf_aarch64_link_hash_table *) obfd->link.hash;
+
+  if (ret->loc_hash_table)
+    htab_delete (ret->loc_hash_table);
+  if (ret->loc_hash_memory)
+    objalloc_free ((struct objalloc *) ret->loc_hash_memory);
+
+  bfd_hash_table_free (&ret->stub_hash_table);
+  _bfd_elf_link_hash_table_free (obfd);
+}
+
 /* Create an AArch64 elf linker hash table.  */
 
 static struct bfd_link_hash_table *
@@ -2071,7 +2100,7 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
   if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc,
                            sizeof (struct elf_aarch64_stub_hash_entry)))
     {
-      free (ret);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -2082,30 +2111,14 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      elfNN_aarch64_link_hash_table_free (abfd);
       return NULL;
     }
+  ret->root.root.hash_table_free = elfNN_aarch64_link_hash_table_free;
 
   return &ret->root.root;
 }
 
-/* Free the derived linker hash table.  */
-
-static void
-elfNN_aarch64_hash_table_free (struct bfd_link_hash_table *hash)
-{
-  struct elf_aarch64_link_hash_table *ret
-    = (struct elf_aarch64_link_hash_table *) hash;
-
-  if (ret->loc_hash_table)
-    htab_delete (ret->loc_hash_table);
-  if (ret->loc_hash_memory)
-    objalloc_free ((struct objalloc *) ret->loc_hash_memory);
-
-  bfd_hash_table_free (&ret->stub_hash_table);
-  _bfd_elf_link_hash_table_free (hash);
-}
-
 static bfd_boolean
 aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
                  bfd_vma offset, bfd_vma value)
@@ -2475,7 +2488,7 @@ elfNN_aarch64_setup_section_lists (bfd *output_bfd,
 
   /* Count the number of input BFDs and find the top input section id.  */
   for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
-       input_bfd != NULL; input_bfd = input_bfd->link_next)
+       input_bfd != NULL; input_bfd = input_bfd->link.next)
     {
       bfd_count += 1;
       for (section = input_bfd->sections;
@@ -2679,7 +2692,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
       asection *stub_sec;
 
       for (input_bfd = info->input_bfds, bfd_indx = 0;
-          input_bfd != NULL; input_bfd = input_bfd->link_next, bfd_indx++)
+          input_bfd != NULL; input_bfd = input_bfd->link.next, bfd_indx++)
        {
          Elf_Internal_Shdr *symtab_hdr;
          asection *section;
@@ -3289,8 +3302,7 @@ tpoff_base (struct bfd_link_info *info)
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   /* If tls_sec is NULL, we should have signalled an error already.  */
-  if (htab->tls_sec == NULL)
-    return 0;
+  BFD_ASSERT (htab->tls_sec != NULL);
 
   bfd_vma base = align_power ((bfd_vma) TCB_SIZE,
                              htab->tls_sec->alignment_power);
@@ -3577,7 +3589,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 
              if (globals->root.splt != NULL)
                {
-                 plt_index = h->plt.offset / globals->plt_entry_size - 1;
+                 plt_index = ((h->plt.offset - globals->plt_header_size) /
+                              globals->plt_entry_size);
                  off = (plt_index + 3) * GOT_ENTRY_SIZE;
                  base_got = globals->root.sgotplt;
                }
@@ -3831,7 +3844,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 
       value = (symbol_got_offset (input_bfd, h, r_symndx)
               + globals->root.sgot->output_section->vma
-              + globals->root.sgot->output_section->output_offset);
+              + globals->root.sgot->output_offset);
 
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
                                                   0, weak_undef_p);
@@ -3860,10 +3873,9 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     case BFD_RELOC_AARCH64_TLSDESC_LDR:
       if (globals->root.sgot == NULL)
        return bfd_reloc_notsupported;
-
       value = (symbol_tlsdesc_got_offset (input_bfd, h, r_symndx)
               + globals->root.sgotplt->output_section->vma
-              + globals->root.sgotplt->output_section->output_offset
+              + globals->root.sgotplt->output_offset
               + globals->sgotplt_jump_table_size);
 
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
@@ -3926,7 +3938,6 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
             or
             adrp x0, :tlsdesc:var   =>   adrp x0, :gottprel:var
           */
-         insn = bfd_getl32 (contents + rel->r_offset);
          return bfd_reloc_continue;
        }
 
@@ -3945,7 +3956,7 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
             ldr xd, [x0, #:tlsdesc_lo12:var] => ldr x0, [x0, #:gottprel_lo12:var]
           */
          insn = bfd_getl32 (contents + rel->r_offset);
-         insn &= 0xfffffff0;
+         insn &= 0xffffffe0;
          bfd_putl32 (insn, contents + rel->r_offset);
          return bfd_reloc_continue;
        }
@@ -4147,15 +4158,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
                                         rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
-       {
-         /* This is a relocatable link.  We don't have to change
-            anything, unless the reloc is against a section symbol,
-            in which case we have to adjust according to where the
-            section symbol winds up in the output section.  */
-         if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-           rel->r_addend += sec->output_offset;
-         continue;
-       }
+       continue;
 
       if (h != NULL)
        name = h->root.root.string;
@@ -4525,31 +4528,6 @@ elfNN_aarch64_set_private_flags (bfd *abfd, flagword flags)
   return TRUE;
 }
 
-/* Copy backend specific data from one object module to another.  */
-
-static bfd_boolean
-elfNN_aarch64_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
-{
-  flagword in_flags;
-
-  if (!is_aarch64_elf (ibfd) || !is_aarch64_elf (obfd))
-    return TRUE;
-
-  in_flags = elf_elfheader (ibfd)->e_flags;
-
-  elf_elfheader (obfd)->e_flags = in_flags;
-  elf_flags_init (obfd) = TRUE;
-
-  /* Also copy the EI_OSABI field.  */
-  elf_elfheader (obfd)->e_ident[EI_OSABI] =
-    elf_elfheader (ibfd)->e_ident[EI_OSABI];
-
-  /* Copy object attributes.  */
-  _bfd_elf_copy_obj_attributes (ibfd, obfd);
-
-  return TRUE;
-}
-
 /* Merge backend specific data from an object file to the output
    object file when linking.  */
 
@@ -5491,7 +5469,7 @@ elfNN_aarch64_post_process_headers (bfd *abfd,
   i_ehdrp = elf_elfheader (abfd);
   i_ehdrp->e_ident[EI_ABIVERSION] = AARCH64_ELF_ABI_VERSION;
 
-  _bfd_elf_set_osabi (abfd, link_info);
+  _bfd_elf_post_process_headers (abfd, link_info);
 }
 
 static enum elf_reloc_type_class
@@ -5512,17 +5490,6 @@ elfNN_aarch64_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSE
     }
 }
 
-/* Set the right machine number for an AArch64 ELF file.  */
-
-static bfd_boolean
-elfNN_aarch64_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr)
-{
-  if (hdr->sh_type == SHT_NOTE)
-    *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS;
-
-  return TRUE;
-}
-
 /* Handle an AArch64 specific section when reading an object file.  This is
    called when bfd_section_from_shdr finds a section with an unknown
    type.  */
@@ -6315,7 +6282,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       struct elf_aarch64_local_symbol *locals = NULL;
       Elf_Internal_Shdr *symtab_hdr;
@@ -6639,7 +6606,7 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
 
   plt_entry = plt->contents + h->plt.offset;
   plt_entry_address = plt->output_section->vma
-    + plt->output_section->output_offset + h->plt.offset;
+    + plt->output_offset + h->plt.offset;
   gotplt_entry_address = gotplt->output_section->vma +
     gotplt->output_offset + got_offset;
 
@@ -6811,7 +6778,34 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
                       + htab->root.sgot->output_offset
                       + (h->got.offset & ~(bfd_vma) 1));
 
-      if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
+      if (h->def_regular
+         && h->type == STT_GNU_IFUNC)
+       {
+         if (info->shared)
+           {
+             /* Generate R_AARCH64_GLOB_DAT.  */
+             goto do_glob_dat;
+           }
+         else
+           {
+             asection *plt;
+
+             if (!h->pointer_equality_needed)
+               abort ();
+
+             /* For non-shared object, we can't use .got.plt, which
+                contains the real function address if we need pointer
+                equality.  We load the GOT entry with the PLT entry.  */
+             plt = htab->root.splt ? htab->root.splt : htab->root.iplt;
+             bfd_put_NN (output_bfd, (plt->output_section->vma
+                                      + plt->output_offset
+                                      + h->plt.offset),
+                         htab->root.sgot->contents
+                         + (h->got.offset & ~(bfd_vma) 1));
+             return TRUE;
+           }
+       }
+      else if (info->shared && SYMBOL_REFERENCES_LOCAL (info, h))
        {
          if (!h->def_regular)
            return FALSE;
@@ -6824,6 +6818,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
        }
       else
        {
+do_glob_dat:
          BFD_ASSERT ((h->got.offset & 1) == 0);
          bfd_put_NN (output_bfd, (bfd_vma) 0,
                      htab->root.sgot->contents + h->got.offset);
@@ -6918,7 +6913,7 @@ elfNN_aarch64_init_small_plt0_entry (bfd *output_bfd ATTRIBUTE_UNUSED,
                  + GOT_ENTRY_SIZE * 2);
 
   plt_base = htab->root.splt->output_section->vma +
-    htab->root.splt->output_section->output_offset;
+    htab->root.splt->output_offset;
 
   /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
      ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
@@ -6978,7 +6973,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PLTRELSZ:
-             s = htab->root.srelplt->output_section;
+             s = htab->root.srelplt;
              dyn.d_un.d_val = s->size;
              break;
 
@@ -6992,7 +6987,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
                 about changing the DT_RELA entry.  */
              if (htab->root.srelplt != NULL)
                {
-                 s = htab->root.srelplt->output_section;
+                 s = htab->root.srelplt;
                  dyn.d_un.d_val -= s->size;
                }
              break;
@@ -7185,9 +7180,6 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define bfd_elfNN_close_and_cleanup             \
   elfNN_aarch64_close_and_cleanup
 
-#define bfd_elfNN_bfd_copy_private_bfd_data    \
-  elfNN_aarch64_copy_private_bfd_data
-
 #define bfd_elfNN_bfd_free_cached_info          \
   elfNN_aarch64_bfd_free_cached_info
 
@@ -7197,9 +7189,6 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define bfd_elfNN_bfd_link_hash_table_create    \
   elfNN_aarch64_link_hash_table_create
 
-#define bfd_elfNN_bfd_link_hash_table_free      \
-  elfNN_aarch64_hash_table_free
-
 #define bfd_elfNN_bfd_merge_private_bfd_data   \
   elfNN_aarch64_merge_private_bfd_data
 
@@ -7274,9 +7263,6 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_reloc_type_class           \
   elfNN_aarch64_reloc_type_class
 
-#define elf_backend_section_flags              \
-  elfNN_aarch64_section_flags
-
 #define elf_backend_section_from_shdr          \
   elfNN_aarch64_section_from_shdr
 
@@ -7294,6 +7280,7 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_may_use_rel_p      0
 #define elf_backend_may_use_rela_p     1
 #define elf_backend_default_use_rela_p 1
+#define elf_backend_rela_normal        1
 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 3)
 #define elf_backend_default_execstack  0
 
This page took 0.029529 seconds and 4 git commands to generate.