[AArch64] BFD_RELOC_AARCH64_TLSLE_ADD_LO12 should enable overflow check
[deliverable/binutils-gdb.git] / bfd / elfnn-aarch64.c
index 1d896d4ea327390d5233e303160fe97985275617..26f20c587b5b7efaa5daf5f1a18d9d42b9f4bfaf 100644 (file)
@@ -848,6 +848,22 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         0xffc,                 /* dst_mask */
         FALSE),                /* pcrel_offset */
 
+  /* LD64: GOT offset to the page address of GOT table.
+     (G(S) - PAGE (_GLOBAL_OFFSET_TABLE_)) & 0x7ff8.  */
+  HOWTO64 (AARCH64_R (LD64_GOTPAGE_LO15),      /* type */
+        3,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        12,                    /* bitsize */
+        FALSE,                 /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_unsigned,    /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (LD64_GOTPAGE_LO15),     /* name */
+        FALSE,                 /* partial_inplace */
+        0x7ff8,                /* src_mask */
+        0x7ff8,                /* dst_mask */
+        FALSE),                /* pcrel_offset */
+
   /* Get to the page for the GOT entry for the symbol
      (G(S) - P) using an ADRP instruction.  */
   HOWTO (AARCH64_R (TLSGD_ADR_PAGE21), /* type */
@@ -1067,7 +1083,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         12,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
-        complain_overflow_dont,        /* complain_on_overflow */
+        complain_overflow_unsigned,    /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         AARCH64_R_STR (TLSLE_ADD_TPREL_LO12),  /* name */
         FALSE,                 /* partial_inplace */
@@ -3980,8 +3996,8 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
 
   switch (r_type)
     {
-    case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
+    case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
       return (is_local
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
              : BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21);
@@ -3996,8 +4012,8 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
              : BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19);
 
-    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
       return (is_local
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
              : BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC);
@@ -4033,29 +4049,30 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type)
 {
   switch (r_type)
     {
-    case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
-    case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
     case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
     case BFD_RELOC_AARCH64_GOT_LD_PREL19:
+    case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
+    case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
+    case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
       return GOT_NORMAL;
 
+    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
-    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
       return GOT_TLS_GD;
 
     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
     case BFD_RELOC_AARCH64_TLSDESC_CALL:
-    case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
     case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
     case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
       return GOT_TLSDESC_GD;
 
     case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
-    case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
     case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
       return GOT_TLS_IE;
 
@@ -4491,6 +4508,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     {
       asection *plt;
       const char *name;
+      bfd_vma addend = 0;
 
       if ((input_section->flags & SEC_ALLOC) == 0
          || h->plt.offset == (bfd_vma) -1)
@@ -4578,17 +4596,18 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
              return bfd_reloc_ok;
            }
          /* FALLTHROUGH */
-       case BFD_RELOC_AARCH64_JUMP26:
        case BFD_RELOC_AARCH64_CALL26:
+       case BFD_RELOC_AARCH64_JUMP26:
          value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
                                                       signed_addend,
                                                       weak_undef_p);
          return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type,
                                              howto, value);
-       case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
-       case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
        case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
        case BFD_RELOC_AARCH64_GOT_LD_PREL19:
+       case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
+       case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
+       case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
          base_got = globals->root.sgot;
          off = h->got.offset;
 
@@ -4647,11 +4666,14 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
            value = aarch64_calculate_got_entry_vma (h, globals, info,
                                                     value, output_bfd,
                                                     unresolved_reloc_p);
+         if (bfd_r_type == BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15)
+           addend = (globals->root.sgot->output_section->vma
+                     + globals->root.sgot->output_offset);
          value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
-                                                      0, weak_undef_p);
+                                                      addend, weak_undef_p);
          return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type, howto, value);
-       case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
        case BFD_RELOC_AARCH64_ADD_LO12:
+       case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
          break;
        }
     }
@@ -4746,8 +4768,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
        value += signed_addend;
       break;
 
-    case BFD_RELOC_AARCH64_JUMP26:
     case BFD_RELOC_AARCH64_CALL26:
+    case BFD_RELOC_AARCH64_JUMP26:
       {
        asection *splt = globals->root.splt;
        bfd_boolean via_plt_p =
@@ -4800,13 +4822,13 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
                                                   signed_addend, weak_undef_p);
       break;
 
-    case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
-    case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
-    case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
-    case BFD_RELOC_AARCH64_LD_LO19_PCREL:
     case BFD_RELOC_AARCH64_16_PCREL:
     case BFD_RELOC_AARCH64_32_PCREL:
     case BFD_RELOC_AARCH64_64_PCREL:
+    case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
+    case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
+    case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
+    case BFD_RELOC_AARCH64_LD_LO19_PCREL:
       if (info->shared
          && (input_section->flags & SEC_ALLOC) != 0
          && (input_section->flags & SEC_READONLY) != 0
@@ -4830,43 +4852,49 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
 #endif
     case BFD_RELOC_AARCH64_ADD_LO12:
     case BFD_RELOC_AARCH64_BRANCH19:
-    case BFD_RELOC_AARCH64_LDST8_LO12:
+    case BFD_RELOC_AARCH64_LDST128_LO12:
     case BFD_RELOC_AARCH64_LDST16_LO12:
     case BFD_RELOC_AARCH64_LDST32_LO12:
     case BFD_RELOC_AARCH64_LDST64_LO12:
-    case BFD_RELOC_AARCH64_LDST128_LO12:
-    case BFD_RELOC_AARCH64_MOVW_G0_S:
-    case BFD_RELOC_AARCH64_MOVW_G1_S:
-    case BFD_RELOC_AARCH64_MOVW_G2_S:
+    case BFD_RELOC_AARCH64_LDST8_LO12:
     case BFD_RELOC_AARCH64_MOVW_G0:
     case BFD_RELOC_AARCH64_MOVW_G0_NC:
+    case BFD_RELOC_AARCH64_MOVW_G0_S:
     case BFD_RELOC_AARCH64_MOVW_G1:
     case BFD_RELOC_AARCH64_MOVW_G1_NC:
+    case BFD_RELOC_AARCH64_MOVW_G1_S:
     case BFD_RELOC_AARCH64_MOVW_G2:
     case BFD_RELOC_AARCH64_MOVW_G2_NC:
+    case BFD_RELOC_AARCH64_MOVW_G2_S:
     case BFD_RELOC_AARCH64_MOVW_G3:
     case BFD_RELOC_AARCH64_TSTBR14:
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
                                                   signed_addend, weak_undef_p);
       break;
 
-    case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
-    case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
     case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
     case BFD_RELOC_AARCH64_GOT_LD_PREL19:
+    case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
+    case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
+    case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
       if (globals->root.sgot == NULL)
        BFD_ASSERT (h != NULL);
 
       if (h != NULL)
        {
+         bfd_vma addend = 0;
          value = aarch64_calculate_got_entry_vma (h, globals, info, value,
                                                   output_bfd,
                                                   unresolved_reloc_p);
+         if (bfd_r_type == BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15)
+           addend = (globals->root.sgot->output_section->vma
+                     + globals->root.sgot->output_offset);
          value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
-                                                      0, weak_undef_p);
+                                                      addend, weak_undef_p);
        }
       else
       {
+       bfd_vma addend = 0;
        struct elf_aarch64_local_symbol *locals
          = elf_aarch64_locals (input_bfd);
 
@@ -4915,16 +4943,22 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
        /* Update the relocation value to GOT entry addr as we have transformed
           the direct data access into indirect data access through GOT.  */
        value = got_entry_addr;
+
+       if (bfd_r_type == BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15)
+         addend = base_got->output_section->vma + base_got->output_offset;
+
+       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+                                                    addend, weak_undef_p);
       }
 
       break;
 
+    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
-    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
-    case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
     case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
+    case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
     case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
       if (globals->root.sgot == NULL)
        return bfd_reloc_notsupported;
@@ -5008,8 +5042,8 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
 
   switch (elfNN_aarch64_bfd_reloc_from_type (r_type))
     {
-    case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
+    case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
       if (is_local)
        {
          /* GD->LE relaxation:
@@ -5407,9 +5441,9 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
 
       switch (elfNN_aarch64_bfd_reloc_from_type (r_type))
        {
+       case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
        case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
        case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
-       case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
          if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx))
            {
              bfd_boolean need_relocs = FALSE;
@@ -5537,14 +5571,14 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
            }
          break;
 
-       case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
        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_MOVW_TPREL_G2:
-       case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
-       case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_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:
+       case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
+       case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
          break;
 
        case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
@@ -5910,6 +5944,7 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
        case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
        case BFD_RELOC_AARCH64_GOT_LD_PREL19:
        case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
+       case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
        case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
        case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
        case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
@@ -5961,13 +5996,13 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
            h->plt.refcount -= 1;
          break;
 
+       case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
+       case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
+       case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
        case BFD_RELOC_AARCH64_MOVW_G0_NC:
        case BFD_RELOC_AARCH64_MOVW_G1_NC:
        case BFD_RELOC_AARCH64_MOVW_G2_NC:
        case BFD_RELOC_AARCH64_MOVW_G3:
-       case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
-       case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
-       case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
        case BFD_RELOC_AARCH64_NN:
          if (h != NULL && info->executable)
            {
@@ -6260,15 +6295,16 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            default:
              break;
 
-           case BFD_RELOC_AARCH64_NN:
+           case BFD_RELOC_AARCH64_ADD_LO12:
+           case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
+           case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
            case BFD_RELOC_AARCH64_CALL26:
+           case BFD_RELOC_AARCH64_GOT_LD_PREL19:
            case BFD_RELOC_AARCH64_JUMP26:
            case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
+           case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
            case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
-           case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
-           case BFD_RELOC_AARCH64_GOT_LD_PREL19:
-           case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
-           case BFD_RELOC_AARCH64_ADD_LO12:
+           case BFD_RELOC_AARCH64_NN:
              if (htab->root.dynobj == NULL)
                htab->root.dynobj = abfd;
              if (!_bfd_elf_create_ifunc_sections (htab->root.dynobj, info))
@@ -6378,6 +6414,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
        case BFD_RELOC_AARCH64_GOT_LD_PREL19:
        case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
+       case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
        case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
        case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
        case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
This page took 0.029171 seconds and 4 git commands to generate.