[AArch64] Support RAS extension for ARMv8 onwards.
[deliverable/binutils-gdb.git] / bfd / elfnn-aarch64.c
index 292470df73ed97768880b172cf7e995cbb31dc4f..5b9878e8f3123bf12f739deb29d88716f762d687 100644 (file)
@@ -575,7 +575,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO (AARCH64_R (MOVW_SABS_G0),     /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        16,                    /* bitsize */
+        17,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed,      /* complain_on_overflow */
@@ -590,7 +590,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO64 (AARCH64_R (MOVW_SABS_G1),   /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        16,                    /* bitsize */
+        17,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed,      /* complain_on_overflow */
@@ -605,7 +605,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO64 (AARCH64_R (MOVW_SABS_G2),   /* type */
         32,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        16,                    /* bitsize */
+        17,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_signed,      /* complain_on_overflow */
@@ -2639,34 +2639,21 @@ aarch64_select_branch_stub (bfd_vma value, bfd_vma place)
 /* Determine the type of stub needed, if any, for a call.  */
 
 static enum elf_aarch64_stub_type
-aarch64_type_of_stub (struct bfd_link_info *info,
-                     asection *input_sec,
+aarch64_type_of_stub (asection *input_sec,
                      const Elf_Internal_Rela *rel,
                      asection *sym_sec,
                      unsigned char st_type,
-                     struct elf_aarch64_link_hash_entry *hash,
                      bfd_vma destination)
 {
   bfd_vma location;
   bfd_signed_vma branch_offset;
   unsigned int r_type;
-  struct elf_aarch64_link_hash_table *globals;
   enum elf_aarch64_stub_type stub_type = aarch64_stub_none;
-  bfd_boolean via_plt_p;
 
   if (st_type != STT_FUNC
       && (sym_sec == input_sec))
     return stub_type;
 
-  globals = elf_aarch64_hash_table (info);
-  via_plt_p = (globals->root.splt != NULL && hash != NULL
-              && hash->root.plt.offset != (bfd_vma) - 1);
-  /* Make sure call to plt stub can fit into the branch range.  */
-  if (via_plt_p)
-    destination = (globals->root.splt->output_section->vma
-                  + globals->root.splt->output_offset
-                  + hash->root.plt.offset);
-
   /* Determine where the call point is.  */
   location = (input_sec->output_offset
              + input_sec->output_section->vma + rel->r_offset);
@@ -4142,8 +4129,8 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
                    }
 
                  /* Determine what (if any) linker stub is needed.  */
-                 stub_type = aarch64_type_of_stub
-                   (info, section, irela, sym_sec, st_type, hash, destination);
+                 stub_type = aarch64_type_of_stub (section, irela, sym_sec,
+                                                   st_type, destination);
                  if (stub_type == aarch64_stub_none)
                    continue;
 
@@ -6405,10 +6392,6 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
          break;
        }
 
-      if (!save_addend)
-       addend = 0;
-
-
       /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
          because such sections are not SEC_ALLOC and thus ld.so will
          not process them.  */
@@ -6448,6 +6431,34 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
                     name, input_bfd, input_section, rel->r_offset);
                  return FALSE;
                }
+             /* Overflow can occur when a variable is referenced with a type
+                that has a larger alignment than the type with which it was
+                declared. eg:
+                  file1.c: extern int foo; int a (void) { return foo; }
+                  file2.c: char bar, foo, baz;
+                If the variable is placed into a data section at an offset
+                that is incompatible with the larger alignment requirement
+                overflow will occur.  (Strictly speaking this is not overflow
+                but rather an alignment problem, but the bfd_reloc_ error
+                enum does not have a value to cover that situation).
+
+                Try to catch this situation here and provide a more helpful
+                error message to the user.  */
+             if (addend & ((1 << howto->rightshift) - 1)
+                 /* FIXME: Are we testing all of the appropriate reloc
+                    types here ?  */
+                 && (real_r_type == BFD_RELOC_AARCH64_LD_LO19_PCREL
+                     || real_r_type == BFD_RELOC_AARCH64_LDST16_LO12
+                     || real_r_type == BFD_RELOC_AARCH64_LDST32_LO12
+                     || real_r_type == BFD_RELOC_AARCH64_LDST64_LO12
+                     || real_r_type == BFD_RELOC_AARCH64_LDST128_LO12))
+               {
+                 info->callbacks->warning
+                   (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."),
+                    name, input_bfd, input_section, rel->r_offset);
+               }
              break;
 
            case bfd_reloc_undefined:
@@ -6482,6 +6493,9 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
              break;
            }
        }
+
+      if (!save_addend)
+       addend = 0;
     }
 
   return TRUE;
@@ -7066,6 +7080,22 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
       if (h != NULL)
        {
+         /* If a relocation refers to _GLOBAL_OFFSET_TABLE_, create the .got.
+            This shows up in particular in an R_AARCH64_PREL64 in large model
+            when calculating the pc-relative address to .got section which is
+            used to initialize the gp register.  */
+         if (h->root.root.string
+             && strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0)
+           {
+             if (htab->root.dynobj == NULL)
+               htab->root.dynobj = abfd;
+
+             if (! aarch64_elf_create_got_section (htab->root.dynobj, info))
+               return FALSE;
+
+             BFD_ASSERT (h == htab->root.hgot);
+           }
+
          /* Create the ifunc sections for static executables.  If we
             never see an indirect function symbol nor we are building
             a static executable, those sections will be empty and
@@ -8219,6 +8249,7 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
       && h->def_regular)
     return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
                                               &eh->dyn_relocs,
+                                              NULL,
                                               htab->plt_entry_size,
                                               htab->plt_header_size,
                                               GOT_ENTRY_SIZE);
This page took 0.025931 seconds and 4 git commands to generate.