Automatic date update in version.in
[deliverable/binutils-gdb.git] / bfd / elfnn-aarch64.c
index e1797b39930075c7528b9259b219cc8c108f9158..3ccca779ff79cb83d3f2fc7de50bb258a55f94bb 100644 (file)
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12       \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12       \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC    \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12    \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12    \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12    \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12     \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC  \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0                \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC     \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1                \
@@ -1635,6 +1643,126 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         0xfff,                 /* dst_mask */
         FALSE),                /* pcrel_offset */
 
+  /* LD/ST16: bit[11:1] of byte offset to module TLS base address.  */
+  HOWTO (AARCH64_R (TLSLE_LDST16_TPREL_LO12),  /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        11,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_unsigned,    /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST16_TPREL_LO12),       /* name */
+        FALSE,                 /* partial_inplace */
+        0x1ffc00,              /* src_mask */
+        0x1ffc00,              /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* Same as BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12, but no overflow check.  */
+  HOWTO (AARCH64_R (TLSLE_LDST16_TPREL_LO12_NC),       /* type */
+        1,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        11,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont,        /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST16_TPREL_LO12_NC),    /* name */
+        FALSE,                 /* partial_inplace */
+        0x1ffc00,              /* src_mask */
+        0x1ffc00,              /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* LD/ST32: bit[11:2] of byte offset to module TLS base address.  */
+  HOWTO (AARCH64_R (TLSLE_LDST32_TPREL_LO12),  /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        10,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_unsigned,    /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST32_TPREL_LO12),       /* name */
+        FALSE,                 /* partial_inplace */
+        0xffc00,               /* src_mask */
+        0xffc00,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* Same as BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12, but no overflow check.  */
+  HOWTO (AARCH64_R (TLSLE_LDST32_TPREL_LO12_NC),       /* type */
+        2,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        10,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont,        /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST32_TPREL_LO12_NC),    /* name */
+        FALSE,                 /* partial_inplace */
+        0xffc00,               /* src_mask */
+        0xffc00,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* LD/ST64: bit[11:3] of byte offset to module TLS base address.  */
+  HOWTO (AARCH64_R (TLSLE_LDST64_TPREL_LO12),  /* type */
+        3,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        9,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_unsigned,    /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST64_TPREL_LO12),       /* name */
+        FALSE,                 /* partial_inplace */
+        0x7fc00,               /* src_mask */
+        0x7fc00,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* Same as BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12, but no overflow check.  */
+  HOWTO (AARCH64_R (TLSLE_LDST64_TPREL_LO12_NC),       /* type */
+        3,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        9,                     /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont,        /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST64_TPREL_LO12_NC),    /* name */
+        FALSE,                 /* partial_inplace */
+        0x7fc00,               /* src_mask */
+        0x7fc00,               /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* LD/ST8: bit[11:0] of byte offset to module TLS base address.  */
+  HOWTO (AARCH64_R (TLSLE_LDST8_TPREL_LO12),   /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        12,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_unsigned,    /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST8_TPREL_LO12),        /* name */
+        FALSE,                 /* partial_inplace */
+        0x3ffc00,              /* src_mask */
+        0x3ffc00,              /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
+  /* Same as BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12, but no overflow check.  */
+  HOWTO (AARCH64_R (TLSLE_LDST8_TPREL_LO12_NC),        /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        12,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        10,                    /* bitpos */
+        complain_overflow_dont,        /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSLE_LDST8_TPREL_LO12_NC),     /* name */
+        FALSE,                 /* partial_inplace */
+        0x3ffc00,              /* src_mask */
+        0x3ffc00,              /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
   HOWTO (AARCH64_R (TLSDESC_LD_PREL19),        /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
@@ -1972,7 +2100,7 @@ elfNN_aarch64_bfd_reloc_from_howto (reloc_howto_type *howto)
 /* Given R_TYPE, return the bfd internal relocation enumerator.  */
 
 static bfd_reloc_code_real_type
-elfNN_aarch64_bfd_reloc_from_type (unsigned int r_type)
+elfNN_aarch64_bfd_reloc_from_type (bfd *abfd, unsigned int r_type)
 {
   static bfd_boolean initialized_p = FALSE;
   /* Indexed by R_TYPE, values are offsets in the howto_table.  */
@@ -1995,7 +2123,8 @@ elfNN_aarch64_bfd_reloc_from_type (unsigned int r_type)
   /* PR 17512: file: b371e70a.  */
   if (r_type >= R_AARCH64_end)
     {
-      _bfd_error_handler (_("Invalid AArch64 reloc number: %d"), r_type);
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+                         abfd, r_type);
       bfd_set_error (bfd_error_bad_value);
       return BFD_RELOC_AARCH64_NONE;
     }
@@ -2054,7 +2183,7 @@ elfNN_aarch64_howto_from_bfd_reloc (bfd_reloc_code_real_type code)
 }
 
 static reloc_howto_type *
-elfNN_aarch64_howto_from_type (unsigned int r_type)
+elfNN_aarch64_howto_from_type (bfd *abfd, unsigned int r_type)
 {
   bfd_reloc_code_real_type val;
   reloc_howto_type *howto;
@@ -2070,7 +2199,7 @@ elfNN_aarch64_howto_from_type (unsigned int r_type)
   if (r_type == R_AARCH64_NONE)
     return &elfNN_aarch64_howto_none;
 
-  val = elfNN_aarch64_bfd_reloc_from_type (r_type);
+  val = elfNN_aarch64_bfd_reloc_from_type (abfd, r_type);
   howto = elfNN_aarch64_howto_from_bfd_reloc (val);
 
   if (howto != NULL)
@@ -2080,14 +2209,22 @@ elfNN_aarch64_howto_from_type (unsigned int r_type)
   return NULL;
 }
 
-static void
-elfNN_aarch64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *bfd_reloc,
+static bfd_boolean
+elfNN_aarch64_info_to_howto (bfd *abfd, arelent *bfd_reloc,
                             Elf_Internal_Rela *elf_reloc)
 {
   unsigned int r_type;
 
   r_type = ELFNN_R_TYPE (elf_reloc->r_info);
-  bfd_reloc->howto = elfNN_aarch64_howto_from_type (r_type);
+  bfd_reloc->howto = elfNN_aarch64_howto_from_type (abfd, r_type);
+
+  if (bfd_reloc->howto == NULL)
+    {
+      /* xgettext:c-format */
+      _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type);
+      return FALSE;
+    }
+  return TRUE;
 }
 
 static reloc_howto_type *
@@ -2727,11 +2864,11 @@ aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
   reloc_howto_type *howto;
   bfd_vma place;
 
-  howto = elfNN_aarch64_howto_from_type (r_type);
+  howto = elfNN_aarch64_howto_from_type (input_bfd, r_type);
   place = (input_section->output_section->vma + input_section->output_offset
           + offset);
 
-  r_type = elfNN_aarch64_bfd_reloc_from_type (r_type);
+  r_type = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
   value = _bfd_aarch64_elf_resolve_relocation (r_type, place, value, 0, FALSE);
   return _bfd_aarch64_elf_put_addend (input_bfd,
                                      input_section->contents + offset, r_type,
@@ -3804,8 +3941,10 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab)
       if (!strstr (section->name, STUB_SUFFIX))
        continue;
 
+      /* Add space for a branch.  Add 8 bytes to keep section 8 byte aligned,
+        as long branch stubs contain a 64-bit address.  */
       if (section->size)
-       section->size += 4;
+       section->size += 8;
 
       /* Ensure all stub sections have a size which is a multiple of
         4096.  This is important in order to ensure that the insertion
@@ -3817,9 +3956,7 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab)
     }
 }
 
-
-/* Construct an erratum 843419 workaround stub name.
- */
+/* Construct an erratum 843419 workaround stub name.  */
 
 static char *
 _bfd_aarch64_erratum_843419_stub_name (asection *input_section,
@@ -4361,8 +4498,11 @@ elfNN_aarch64_build_stubs (struct bfd_link_info *info)
        return FALSE;
       stub_sec->size = 0;
 
+      /* Add a branch around the stub section, and a nop, to keep it 8 byte
+        aligned, as long branch stubs contain a 64-bit address.  */
       bfd_putl32 (0x14000000 | (size >> 2), stub_sec->contents);
-      stub_sec->size += 4;
+      bfd_putl32 (INSN_NOP, stub_sec->contents + 4);
+      stub_sec->size += 8;
     }
 
   /* Build the stubs as directed by the stub hash table.  */
@@ -4708,7 +4848,7 @@ aarch64_tls_transition (bfd *input_bfd,
                        unsigned long r_symndx)
 {
   bfd_reloc_code_real_type bfd_r_type
-    = elfNN_aarch64_bfd_reloc_from_type (r_type);
+    = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
 
   if (! aarch64_can_relax_tls (input_bfd, info, bfd_r_type, h, r_symndx))
     return bfd_r_type;
@@ -4884,7 +5024,7 @@ make_branch_to_erratum_835769_stub (struct bfd_hash_entry *gen_entry,
   abfd = stub_entry->target_section->owner;
   if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc))
     _bfd_error_handler
-      (_("%pB: error: Erratum 835769 stub out "
+      (_("%pB: error: erratum 835769 stub out "
         "of range (input file too large)"), abfd);
 
   target = stub_entry->target_value;
@@ -4965,7 +5105,7 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry,
       abfd = stub_entry->target_section->owner;
       if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc))
        _bfd_error_handler
-         (_("%pB: error: Erratum 843419 stub out "
+         (_("%pB: error: erratum 843419 stub out "
             "of range (input file too large)"), abfd);
 
       branch_insn = 0x14000000;
@@ -5062,6 +5202,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
   asection *base_got;
   bfd_vma orig_value = value;
   bfd_boolean resolved_to_zero;
+  bfd_boolean abs_symbol_p;
 
   globals = elf_aarch64_hash_table (info);
 
@@ -5081,6 +5222,9 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 
   weak_undef_p = (h ? h->root.type == bfd_link_hash_undefweak
                  : bfd_is_und_section (sym_sec));
+  abs_symbol_p = (h !=NULL && h->root.type == bfd_link_hash_defined
+                 && bfd_is_abs_section (h->root.u.def.section));
+
 
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle
      it here if it is defined in a non-shared object.  */
@@ -5094,6 +5238,11 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 
       if ((input_section->flags & SEC_ALLOC) == 0)
        {
+         /* If this is a SHT_NOTE section without SHF_ALLOC, treat
+            STT_GNU_IFUNC symbol as STT_FUNC.  */
+         if (elf_section_type (input_section) == SHT_NOTE)
+           goto skip_ifunc;
+
          /* Dynamic relocs are not propagated for SEC_DEBUGGING
             sections because such sections are not SEC_ALLOC and
             thus ld.so will not process them.  */
@@ -5289,6 +5438,7 @@ bad_ifunc_reloc:
        }
     }
 
+ skip_ifunc:
   resolved_to_zero = (h != NULL
                      && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
 
@@ -5348,6 +5498,12 @@ bad_ifunc_reloc:
              skip = TRUE;
              relocate = TRUE;
            }
+         else if (abs_symbol_p)
+           {
+             /* Local absolute symbol.  */
+             skip = (h->forced_local || (h->dynindx == -1));
+             relocate = skip;
+           }
 
          outrel.r_offset += (input_section->output_section->vma
                              + input_section->output_offset);
@@ -5357,8 +5513,7 @@ bad_ifunc_reloc:
          else if (h != NULL
                   && h->dynindx != -1
                   && (!bfd_link_pic (info)
-                      || !(bfd_link_pie (info)
-                           || SYMBOLIC_BIND (info, h))
+                      || !(bfd_link_pie (info) || SYMBOLIC_BIND (info, h))
                       || !h->def_regular))
            outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
          else
@@ -5571,7 +5726,7 @@ bad_ifunc_reloc:
            int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
            _bfd_error_handler
              /* xgettext:c-format */
-             (_("%pB: Local symbol descriptor table be NULL when applying "
+             (_("%pB: local symbol descriptor table be NULL when applying "
                 "relocation %s against local symbol"),
               input_bfd, elfNN_aarch64_howto_table[howto_index].name);
            abort ();
@@ -5683,6 +5838,14 @@ bad_ifunc_reloc:
     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
+    case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
+    case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
+    case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
+    case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
     case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
@@ -5793,7 +5956,7 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 
   BFD_ASSERT (globals && input_bfd && contents && rel);
 
-  switch (elfNN_aarch64_bfd_reloc_from_type (r_type))
+  switch (elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type))
     {
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
@@ -6215,7 +6378,8 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
       r_symndx = ELFNN_R_SYM (rel->r_info);
       r_type = ELFNN_R_TYPE (rel->r_info);
 
-      howto = bfd_reloc.howto = elfNN_aarch64_howto_from_type (r_type);
+      bfd_reloc.howto = elfNN_aarch64_howto_from_type (input_bfd, r_type);
+      howto = bfd_reloc.howto;
 
       if (howto == NULL)
        return _bfd_unrecognized_reloc (input_bfd, input_section, r_type);
@@ -6343,7 +6507,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
                                               h, &unresolved_reloc,
                                               save_addend, &addend, sym);
 
-      switch (elfNN_aarch64_bfd_reloc_from_type (r_type))
+      switch (elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type))
        {
        case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
        case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
@@ -6386,7 +6550,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
                  bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc);
 
                  bfd_reloc_code_real_type real_type =
-                   elfNN_aarch64_bfd_reloc_from_type (r_type);
+                   elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
 
                  if (real_type == BFD_RELOC_AARCH64_TLSLD_ADR_PREL21
                      || real_type == BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21
@@ -6581,7 +6745,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
       if (r != bfd_reloc_ok && r != bfd_reloc_continue)
        {
          bfd_reloc_code_real_type real_r_type
-           = elfNN_aarch64_bfd_reloc_from_type (r_type);
+           = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
 
          switch (r)
            {
@@ -6594,7 +6758,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
                {
                  (*info->callbacks->warning)
                    (info,
-                    _("Too many GOT entries for -fpic, "
+                    _("too many GOT entries for -fpic, "
                       "please recompile with -fPIC"),
                     name, input_bfd, input_section, rel->r_offset);
                  return FALSE;
@@ -6622,9 +6786,9 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
                      || real_r_type == BFD_RELOC_AARCH64_LDST128_LO12))
                {
                  info->callbacks->warning
-                   (info, _("One possible cause of this error is that the \
+                   (info, _("one possible cause of this error is that the \
 symbol is being referenced in the indicated code as if it had a larger \
-alignment than was declared where it was defined."),
+alignment than was declared where it was defined"),
                     name, input_bfd, input_section, rel->r_offset);
                }
              break;
This page took 0.029726 seconds and 4 git commands to generate.