ELF: Move dyn_relocs to struct elf_link_hash_entry
[deliverable/binutils-gdb.git] / bfd / elfnn-aarch64.c
index 9d4df11f9d42c39fad5742f92a5edb561e809259..cbf10deaa4b937039546da08c3b9f2cd00f8d339 100644 (file)
@@ -1,5 +1,5 @@
 /* AArch64-specific support for NN-bit ELF.
-   Copyright (C) 2009-2019 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of BFD, the Binary File Descriptor library.
 #include "objalloc.h"
 #include "elf/aarch64.h"
 #include "elfxx-aarch64.h"
+#include "cpu-aarch64.h"
 
 #define ARCH_SIZE      NN
 
 #define PLT_SMALL_ENTRY_SIZE           (16)
 #define PLT_TLSDESC_ENTRY_SIZE         (32)
 /* PLT sizes with BTI insn.  */
-#define PLT_BTI_ENTRY_SIZE             (36)
-#define PLT_BTI_SMALL_ENTRY_SIZE       (20)
-#define PLT_BTI_TLSDESC_ENTRY_SIZE     (36)
+#define PLT_BTI_SMALL_ENTRY_SIZE       (24)
 /* PLT sizes with PAC insn.  */
-#define PLT_PAC_ENTRY_SIZE             (36)
-#define PLT_PAC_SMALL_ENTRY_SIZE       (20)
+#define PLT_PAC_SMALL_ENTRY_SIZE       (24)
 /* PLT sizes with BTI and PAC insn.  */
-#define PLT_BTI_PAC_ENTRY_SIZE         (40)
 #define PLT_BTI_PAC_SMALL_ENTRY_SIZE   (24)
 
 /* Encoding of the nop instruction.  */
@@ -307,7 +304,7 @@ static const bfd_byte elfNN_aarch64_small_plt0_entry[PLT_ENTRY_SIZE] =
   0x1f, 0x20, 0x03, 0xd5,      /* nop */
 };
 
-static const bfd_byte elfNN_aarch64_small_plt0_bti_entry[PLT_BTI_ENTRY_SIZE] =
+static const bfd_byte elfNN_aarch64_small_plt0_bti_entry[PLT_ENTRY_SIZE] =
 {
   0x5f, 0x24, 0x03, 0xd5,      /* bti c.  */
   0xf0, 0x7b, 0xbf, 0xa9,      /* stp x16, x30, [sp, #-16]!  */
@@ -322,45 +319,6 @@ static const bfd_byte elfNN_aarch64_small_plt0_bti_entry[PLT_BTI_ENTRY_SIZE] =
   0x20, 0x02, 0x1f, 0xd6,      /* br x17  */
   0x1f, 0x20, 0x03, 0xd5,      /* nop */
   0x1f, 0x20, 0x03, 0xd5,      /* nop */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
-};
-
-static const bfd_byte elfNN_aarch64_small_plt0_pac_entry[PLT_PAC_ENTRY_SIZE] =
-{
-  0xf0, 0x7b, 0xbf, 0xa9,      /* stp x16, x30, [sp, #-16]!  */
-  0x10, 0x00, 0x00, 0x90,      /* adrp x16, (GOT+16)  */
-#if ARCH_SIZE == 64
-  0x11, 0x0A, 0x40, 0xf9,      /* ldr x17, [x16, #PLT_GOT+0x10]  */
-  0x10, 0x42, 0x00, 0x91,      /* add x16, x16,#PLT_GOT+0x10   */
-#else
-  0x11, 0x0A, 0x40, 0xb9,      /* ldr w17, [x16, #PLT_GOT+0x8]  */
-  0x10, 0x22, 0x00, 0x11,      /* add w16, w16,#PLT_GOT+0x8   */
-#endif
-  0x9f, 0x21, 0x03, 0xd5,      /* autia1716 */
-  0x20, 0x02, 0x1f, 0xd6,      /* br x17  */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
-};
-
-static const bfd_byte
-elfNN_aarch64_small_plt0_bti_pac_entry[PLT_BTI_PAC_ENTRY_SIZE] =
-{
-  0x5f, 0x24, 0x03, 0xd5,      /* bti c.  */
-  0xf0, 0x7b, 0xbf, 0xa9,      /* stp x16, x30, [sp, #-16]!  */
-  0x10, 0x00, 0x00, 0x90,      /* adrp x16, (GOT+16)  */
-#if ARCH_SIZE == 64
-  0x11, 0x0A, 0x40, 0xf9,      /* ldr x17, [x16, #PLT_GOT+0x10]  */
-  0x10, 0x42, 0x00, 0x91,      /* add x16, x16,#PLT_GOT+0x10   */
-#else
-  0x11, 0x0A, 0x40, 0xb9,      /* ldr w17, [x16, #PLT_GOT+0x8]  */
-  0x10, 0x22, 0x00, 0x11,      /* add w16, w16,#PLT_GOT+0x8   */
-#endif
-  0x9f, 0x21, 0x03, 0xd5,      /* autia1716 */
-  0x20, 0x02, 0x1f, 0xd6,      /* br x17  */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
 };
 
 /* Per function entry in a procedure linkage table looks like this
@@ -392,6 +350,7 @@ elfNN_aarch64_small_plt_bti_entry[PLT_BTI_SMALL_ENTRY_SIZE] =
   0x10, 0x02, 0x00, 0x11,      /* add w16, w16, :lo12:PLTGOT + n * 4  */
 #endif
   0x20, 0x02, 0x1f, 0xd6,      /* br x17.  */
+  0x1f, 0x20, 0x03, 0xd5,      /* nop */
 };
 
 static const bfd_byte
@@ -407,6 +366,7 @@ elfNN_aarch64_small_plt_pac_entry[PLT_PAC_SMALL_ENTRY_SIZE] =
 #endif
   0x9f, 0x21, 0x03, 0xd5,      /* autia1716 */
   0x20, 0x02, 0x1f, 0xd6,      /* br x17.  */
+  0x1f, 0x20, 0x03, 0xd5,      /* nop */
 };
 
 static const bfd_byte
@@ -444,7 +404,7 @@ elfNN_aarch64_tlsdesc_small_plt_entry[PLT_TLSDESC_ENTRY_SIZE] =
 };
 
 static const bfd_byte
-elfNN_aarch64_tlsdesc_small_plt_bti_entry[PLT_BTI_TLSDESC_ENTRY_SIZE] =
+elfNN_aarch64_tlsdesc_small_plt_bti_entry[PLT_TLSDESC_ENTRY_SIZE] =
 {
   0x5f, 0x24, 0x03, 0xd5,      /* bti c.  */
   0xe2, 0x0f, 0xbf, 0xa9,      /* stp x2, x3, [sp, #-16]! */
@@ -459,7 +419,6 @@ elfNN_aarch64_tlsdesc_small_plt_bti_entry[PLT_BTI_TLSDESC_ENTRY_SIZE] =
 #endif
   0x40, 0x00, 0x1f, 0xd6,      /* br x2 */
   0x1f, 0x20, 0x03, 0xd5,      /* nop */
-  0x1f, 0x20, 0x03, 0xd5,      /* nop */
 };
 
 #define elf_info_to_howto              elfNN_aarch64_info_to_howto
@@ -759,7 +718,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
      PC relative address inline.  */
 
   /* MOV[NZ]:   ((S+A-P) >>  0) & 0xffff */
-  HOWTO64 (AARCH64_R (MOVW_PREL_G0),   /* type */
+  HOWTO (AARCH64_R (MOVW_PREL_G0),     /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         17,                    /* bitsize */
@@ -774,7 +733,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         TRUE),         /* pcrel_offset */
 
   /* MOVK:   ((S+A-P) >>  0) & 0xffff [no overflow check] */
-  HOWTO64 (AARCH64_R (MOVW_PREL_G0_NC),        /* type */
+  HOWTO (AARCH64_R (MOVW_PREL_G0_NC),  /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         16,                    /* bitsize */
@@ -789,7 +748,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         TRUE),         /* pcrel_offset */
 
   /* MOV[NZ]:   ((S+A-P) >> 16) & 0xffff */
-  HOWTO64 (AARCH64_R (MOVW_PREL_G1),   /* type */
+  HOWTO (AARCH64_R (MOVW_PREL_G1),     /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
         17,                    /* bitsize */
@@ -2611,9 +2570,6 @@ struct elf_aarch64_link_hash_entry
 {
   struct elf_link_hash_entry root;
 
-  /* Track dynamic relocs copied for this symbol.  */
-  struct elf_dyn_relocs *dyn_relocs;
-
   /* Since PLT entries have variable size, we need to record the
      index into .got.plt instead of recomputing it from the PLT
      offset.  */
@@ -2670,10 +2626,7 @@ struct elf_aarch64_link_hash_table
   int fix_erratum_835769;
 
   /* Fix erratum 843419.  */
-  int fix_erratum_843419;
-
-  /* Enable ADRP->ADR rewrite for erratum 843419 workaround.  */
-  int fix_erratum_843419_adr;
+  erratum_84319_opts fix_erratum_843419;
 
   /* Don't apply link-time values for dynamic relocations.  */
   int no_apply_dynamic_relocs;
@@ -2726,6 +2679,9 @@ struct elf_aarch64_link_hash_table
   unsigned int top_index;
   asection **input_list;
 
+  /* JUMP_SLOT relocs for variant PCS symbols may be present.  */
+  int variant_pcs;
+
   /* The offset into splt of the PLT entry for the TLS descriptor
      resolver.  Special values are 0, if not necessary (or not found
      to be necessary yet), and -1 if needed but not determined
@@ -2769,7 +2725,6 @@ elfNN_aarch64_link_hash_newfunc (struct bfd_hash_entry *entry,
                                     table, string));
   if (ret != NULL)
     {
-      ret->dyn_relocs = NULL;
       ret->got_type = GOT_UNKNOWN;
       ret->plt_got_offset = (bfd_vma) - 1;
       ret->stub_cache = NULL;
@@ -2896,20 +2851,20 @@ elfNN_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
   edir = (struct elf_aarch64_link_hash_entry *) dir;
   eind = (struct elf_aarch64_link_hash_entry *) ind;
 
-  if (eind->dyn_relocs != NULL)
+  if (ind->dyn_relocs != NULL)
     {
-      if (edir->dyn_relocs != NULL)
+      if (dir->dyn_relocs != NULL)
        {
          struct elf_dyn_relocs **pp;
          struct elf_dyn_relocs *p;
 
          /* Add reloc counts against the indirect sym to the direct sym
             list.  Merge any entries against the same section.  */
-         for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
+         for (pp = &ind->dyn_relocs; (p = *pp) != NULL;)
            {
              struct elf_dyn_relocs *q;
 
-             for (q = edir->dyn_relocs; q != NULL; q = q->next)
+             for (q = dir->dyn_relocs; q != NULL; q = q->next)
                if (q->sec == p->sec)
                  {
                    q->pc_count += p->pc_count;
@@ -2920,11 +2875,11 @@ elfNN_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
              if (q == NULL)
                pp = &p->next;
            }
-         *pp = edir->dyn_relocs;
+         *pp = dir->dyn_relocs;
        }
 
-      edir->dyn_relocs = eind->dyn_relocs;
-      eind->dyn_relocs = NULL;
+      dir->dyn_relocs = ind->dyn_relocs;
+      ind->dyn_relocs = NULL;
     }
 
   if (ind->root.type == bfd_link_hash_indirect)
@@ -2940,6 +2895,31 @@ elfNN_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 
+/* Merge non-visibility st_other attributes.  */
+
+static void
+elfNN_aarch64_merge_symbol_attribute (struct elf_link_hash_entry *h,
+                                     const Elf_Internal_Sym *isym,
+                                     bfd_boolean definition ATTRIBUTE_UNUSED,
+                                     bfd_boolean dynamic ATTRIBUTE_UNUSED)
+{
+  unsigned int isym_sto = isym->st_other & ~ELF_ST_VISIBILITY (-1);
+  unsigned int h_sto = h->other & ~ELF_ST_VISIBILITY (-1);
+
+  if (isym_sto == h_sto)
+    return;
+
+  if (isym_sto & ~STO_AARCH64_VARIANT_PCS)
+    /* Not fatal, this callback cannot fail.  */
+    _bfd_error_handler (_("unknown attribute for symbol `%s': 0x%02x"),
+                       h->root.root.string, isym_sto);
+
+  /* Note: Ideally we would warn about any attribute mismatch, but
+     this api does not allow that without substantial changes.  */
+  if (isym_sto & STO_AARCH64_VARIANT_PCS)
+    h->other |= STO_AARCH64_VARIANT_PCS;
+}
+
 /* Destroy an AArch64 elf linker hash table.  */
 
 static void
@@ -2963,7 +2943,7 @@ static struct bfd_link_hash_table *
 elfNN_aarch64_link_hash_table_create (bfd *abfd)
 {
   struct elf_aarch64_link_hash_table *ret;
-  bfd_size_type amt = sizeof (struct elf_aarch64_link_hash_table);
+  size_t amt = sizeof (struct elf_aarch64_link_hash_table);
 
   ret = bfd_zmalloc (amt);
   if (ret == NULL)
@@ -3021,7 +3001,8 @@ aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
           + offset);
 
   r_type = elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
-  value = _bfd_aarch64_elf_resolve_relocation (r_type, place, value, 0, FALSE);
+  value = _bfd_aarch64_elf_resolve_relocation (input_bfd, r_type, place,
+                                              value, 0, FALSE);
   return _bfd_aarch64_elf_put_addend (input_bfd,
                                      input_section->contents + offset, r_type,
                                      howto, value) == bfd_reloc_ok;
@@ -3271,7 +3252,10 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name,
   asection *stub_sec;
   struct elf_aarch64_stub_hash_entry *stub_entry;
 
-  stub_sec = _bfd_aarch64_get_stub_for_link_section (link_section, htab);
+  stub_sec = NULL;
+  /* Only create the actual stub if we will end up needing it.  */
+  if (htab->fix_erratum_843419 & ERRAT_ADRP)
+    stub_sec = _bfd_aarch64_get_stub_for_link_section (link_section, htab);
   stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table, stub_name,
                                         TRUE, FALSE);
   if (stub_entry == NULL)
@@ -3290,7 +3274,7 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name,
 
 static bfd_boolean
 aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
-                       void *in_arg ATTRIBUTE_UNUSED)
+                       void *in_arg)
 {
   struct elf_aarch64_stub_hash_entry *stub_entry;
   asection *stub_sec;
@@ -3303,10 +3287,22 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
   unsigned int template_size;
   const uint32_t *template;
   unsigned int i;
+  struct bfd_link_info *info;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
 
+  info = (struct bfd_link_info *) in_arg;
+
+  /* Fail if the target section could not be assigned to an output
+     section.  The user should fix his linker script.  */
+  if (stub_entry->target_section->output_section == NULL
+      && info->non_contiguous_regions)
+    info->callbacks->einfo (_("%F%P: Could not assign '%pA' to an output section. "
+                             "Retry without "
+                             "--enable-non-contiguous-regions.\n"),
+                           stub_entry->target_section);
+
   stub_sec = stub_entry->stub_sec;
 
   /* Make a note of the offset within the stubs for this entry.  */
@@ -3416,14 +3412,15 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
    we know stub section sizes.  */
 
 static bfd_boolean
-aarch64_size_one_stub (struct bfd_hash_entry *gen_entry,
-                      void *in_arg ATTRIBUTE_UNUSED)
+aarch64_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
 {
   struct elf_aarch64_stub_hash_entry *stub_entry;
+  struct elf_aarch64_link_hash_table *htab;
   int size;
 
   /* Massage our args to the form they really have.  */
   stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
+  htab = (struct elf_aarch64_link_hash_table *) in_arg;
 
   switch (stub_entry->stub_type)
     {
@@ -3437,7 +3434,11 @@ aarch64_size_one_stub (struct bfd_hash_entry *gen_entry,
       size = sizeof (aarch64_erratum_835769_stub);
       break;
     case aarch64_stub_erratum_843419_veneer:
-      size = sizeof (aarch64_erratum_843419_stub);
+      {
+       if (htab->fix_erratum_843419 == ERRAT_ADR)
+         return TRUE;
+       size = sizeof (aarch64_erratum_843419_stub);
+      }
       break;
     default:
       abort ();
@@ -3463,7 +3464,7 @@ elfNN_aarch64_setup_section_lists (bfd *output_bfd,
   unsigned int top_id, top_index;
   asection *section;
   asection **input_list, **list;
-  bfd_size_type amt;
+  size_t amt;
   struct elf_aarch64_link_hash_table *htab =
     elf_aarch64_hash_table (info);
 
@@ -3541,7 +3542,7 @@ elfNN_aarch64_next_input_section (struct bfd_link_info *info, asection *isec)
     {
       asection **list = htab->input_list + isec->output_section->index;
 
-      if (*list != bfd_abs_section_ptr)
+      if (*list != bfd_abs_section_ptr && (isec->flags & SEC_CODE) != 0)
        {
          /* Steal the link_sec pointer for our list.  */
          /* This happens to make the list in reverse order,
@@ -3562,67 +3563,96 @@ elfNN_aarch64_next_input_section (struct bfd_link_info *info, asection *isec)
 static void
 group_sections (struct elf_aarch64_link_hash_table *htab,
                bfd_size_type stub_group_size,
-               bfd_boolean stubs_always_before_branch)
+               bfd_boolean stubs_always_after_branch)
 {
-  asection **list = htab->input_list + htab->top_index;
+  asection **list = htab->input_list;
 
   do
     {
       asection *tail = *list;
+      asection *head;
 
       if (tail == bfd_abs_section_ptr)
        continue;
 
+      /* Reverse the list: we must avoid placing stubs at the
+        beginning of the section because the beginning of the text
+        section may be required for an interrupt vector in bare metal
+        code.  */
+#define NEXT_SEC PREV_SEC
+      head = NULL;
       while (tail != NULL)
+       {
+         /* Pop from tail.  */
+         asection *item = tail;
+         tail = PREV_SEC (item);
+
+         /* Push on head.  */
+         NEXT_SEC (item) = head;
+         head = item;
+       }
+
+      while (head != NULL)
        {
          asection *curr;
-         asection *prev;
-         bfd_size_type total;
+         asection *next;
+         bfd_vma stub_group_start = head->output_offset;
+         bfd_vma end_of_next;
 
-         curr = tail;
-         total = tail->size;
-         while ((prev = PREV_SEC (curr)) != NULL
-                && ((total += curr->output_offset - prev->output_offset)
-                    < stub_group_size))
-           curr = prev;
+         curr = head;
+         while (NEXT_SEC (curr) != NULL)
+           {
+             next = NEXT_SEC (curr);
+             end_of_next = next->output_offset + next->size;
+             if (end_of_next - stub_group_start >= stub_group_size)
+               /* End of NEXT is too far from start, so stop.  */
+               break;
+             /* Add NEXT to the group.  */
+             curr = next;
+           }
 
-         /* OK, the size from the start of CURR to the end is less
+         /* OK, the size from the start to the start of CURR is less
             than stub_group_size and thus can be handled by one stub
-            section.  (Or the tail section is itself larger than
+            section.  (Or the head section is itself larger than
             stub_group_size, in which case we may be toast.)
             We should really be keeping track of the total size of
             stubs added here, as stubs contribute to the final output
             section size.  */
          do
            {
-             prev = PREV_SEC (tail);
+             next = NEXT_SEC (head);
              /* Set up this stub group.  */
-             htab->stub_group[tail->id].link_sec = curr;
+             htab->stub_group[head->id].link_sec = curr;
            }
-         while (tail != curr && (tail = prev) != NULL);
+         while (head != curr && (head = next) != NULL);
 
          /* But wait, there's more!  Input sections up to stub_group_size
-            bytes before the stub section can be handled by it too.  */
-         if (!stubs_always_before_branch)
+            bytes after the stub section can be handled by it too.  */
+         if (!stubs_always_after_branch)
            {
-             total = 0;
-             while (prev != NULL
-                    && ((total += tail->output_offset - prev->output_offset)
-                        < stub_group_size))
+             stub_group_start = curr->output_offset + curr->size;
+
+             while (next != NULL)
                {
-                 tail = prev;
-                 prev = PREV_SEC (tail);
-                 htab->stub_group[tail->id].link_sec = curr;
+                 end_of_next = next->output_offset + next->size;
+                 if (end_of_next - stub_group_start >= stub_group_size)
+                   /* End of NEXT is too far from stubs, so stop.  */
+                   break;
+                 /* Add NEXT to the stub group.  */
+                 head = next;
+                 next = NEXT_SEC (head);
+                 htab->stub_group[head->id].link_sec = curr;
                }
            }
-         tail = prev;
+         head = next;
        }
     }
-  while (list-- != htab->input_list);
+  while (list++ != htab->input_list + htab->top_index);
 
   free (htab->input_list);
 }
 
+#undef PREV_SEC
 #undef PREV_SEC
 
 #define AARCH64_BITS(x, pos, n) (((x) >> (pos)) & ((1 << (n)) - 1))
@@ -4102,8 +4132,10 @@ _bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab)
       /* Ensure all stub sections have a size which is a multiple of
         4096.  This is important in order to ensure that the insertion
         of stub sections does not in itself move existing code around
-        in such a way that new errata sequences are created.  */
-      if (htab->fix_erratum_843419)
+        in such a way that new errata sequences are created.  We only do this
+        when the ADRP workaround is enabled.  If only the ADR workaround is
+        enabled then the stubs workaround won't ever be used.  */
+      if (htab->fix_erratum_843419 & ERRAT_ADRP)
        if (section->size)
          section->size = BFD_ALIGN (section->size, 0x1000);
     }
@@ -4318,15 +4350,21 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
 
       for (input_bfd = info->input_bfds;
           input_bfd != NULL; input_bfd = input_bfd->link.next)
-       if (!_bfd_aarch64_erratum_835769_scan (input_bfd, info,
-                                              &num_erratum_835769_fixes))
-         return FALSE;
+       {
+         if (!is_aarch64_elf (input_bfd)
+             || (input_bfd->flags & BFD_LINKER_CREATED) != 0)
+           continue;
+
+         if (!_bfd_aarch64_erratum_835769_scan (input_bfd, info,
+                                                &num_erratum_835769_fixes))
+           return FALSE;
+       }
 
       _bfd_aarch64_resize_stubs (htab);
       (*htab->layout_sections_again) ();
     }
 
-  if (htab->fix_erratum_843419)
+  if (htab->fix_erratum_843419 != ERRAT_NONE)
     {
       bfd *input_bfd;
 
@@ -4336,6 +4374,10 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
        {
          asection *section;
 
+         if (!is_aarch64_elf (input_bfd)
+             || (input_bfd->flags & BFD_LINKER_CREATED) != 0)
+           continue;
+
          for (section = input_bfd->sections;
               section != NULL;
               section = section->next)
@@ -4358,6 +4400,10 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
          asection *section;
          Elf_Internal_Sym *local_syms = NULL;
 
+         if (!is_aarch64_elf (input_bfd)
+             || (input_bfd->flags & BFD_LINKER_CREATED) != 0)
+           continue;
+
          /* We'll need the symbol table in a second.  */
          symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
          if (symtab_hdr->sh_info == 0)
@@ -4620,7 +4666,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
 
   return TRUE;
 
-error_ret_free_local:
+ error_ret_free_local:
   return FALSE;
 }
 
@@ -4758,9 +4804,7 @@ setup_plt_values (struct bfd_link_info *link_info,
 
   if (plt_type == PLT_BTI_PAC)
     {
-      globals->plt_header_size = PLT_BTI_PAC_ENTRY_SIZE;
-      globals->plt0_entry = elfNN_aarch64_small_plt0_bti_pac_entry;
-      globals->tlsdesc_plt_entry_size = PLT_BTI_TLSDESC_ENTRY_SIZE;
+      globals->plt0_entry = elfNN_aarch64_small_plt0_bti_entry;
 
       /* Only in ET_EXEC we need PLTn with BTI.  */
       if (bfd_link_pde (link_info))
@@ -4776,9 +4820,7 @@ setup_plt_values (struct bfd_link_info *link_info,
     }
   else if (plt_type == PLT_BTI)
     {
-      globals->plt_header_size = PLT_BTI_ENTRY_SIZE;
       globals->plt0_entry = elfNN_aarch64_small_plt0_bti_entry;
-      globals->tlsdesc_plt_entry_size = PLT_BTI_TLSDESC_ENTRY_SIZE;
 
       /* Only in ET_EXEC we need PLTn with BTI.  */
       if (bfd_link_pde (link_info))
@@ -4789,9 +4831,6 @@ setup_plt_values (struct bfd_link_info *link_info,
     }
   else if (plt_type == PLT_PAC)
     {
-      globals->plt_header_size = PLT_PAC_ENTRY_SIZE;
-      globals->plt0_entry = elfNN_aarch64_small_plt0_pac_entry;
-      globals->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE;
       globals->plt_entry_size = PLT_PAC_SMALL_ENTRY_SIZE;
       globals->plt_entry = elfNN_aarch64_small_plt_pac_entry;
     }
@@ -4804,7 +4843,7 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
                               int no_enum_warn,
                               int no_wchar_warn, int pic_veneer,
                               int fix_erratum_835769,
-                              int fix_erratum_843419,
+                              erratum_84319_opts fix_erratum_843419,
                               int no_apply_dynamic_relocs,
                               aarch64_bti_pac_info bp_info)
 {
@@ -4813,8 +4852,10 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
   globals = elf_aarch64_hash_table (link_info);
   globals->pic_veneer = pic_veneer;
   globals->fix_erratum_835769 = fix_erratum_835769;
+  /* If the default options are used, then ERRAT_ADR will be set by default
+     which will enable the ADRP->ADR workaround for the erratum 843419
+     workaround.  */
   globals->fix_erratum_843419 = fix_erratum_843419;
-  globals->fix_erratum_843419_adr = TRUE;
   globals->no_apply_dynamic_relocs = no_apply_dynamic_relocs;
 
   BFD_ASSERT (is_aarch64_elf (output_bfd));
@@ -5284,9 +5325,18 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry,
       || stub_entry->stub_type != aarch64_stub_erratum_843419_veneer)
     return TRUE;
 
-  insn = bfd_getl32 (contents + stub_entry->target_value);
-  bfd_putl32 (insn,
-             stub_entry->stub_sec->contents + stub_entry->stub_offset);
+  BFD_ASSERT (((htab->fix_erratum_843419 & ERRAT_ADRP) && stub_entry->stub_sec)
+             || (htab->fix_erratum_843419 & ERRAT_ADR));
+
+  /* Only update the stub section if we have one.  We should always have one if
+     we're allowed to use the ADRP errata workaround, otherwise it is not
+     required.  */
+  if (stub_entry->stub_sec)
+    {
+      insn = bfd_getl32 (contents + stub_entry->target_value);
+      bfd_putl32 (insn,
+                 stub_entry->stub_sec->contents + stub_entry->stub_offset);
+    }
 
   place = (section->output_section->vma + section->output_offset
           + stub_entry->adrp_offset);
@@ -5300,14 +5350,16 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry,
      ((bfd_vma) _bfd_aarch64_decode_adrp_imm (insn) << 12, 33)
      - (place & 0xfff));
 
-  if (htab->fix_erratum_843419_adr
+  if ((htab->fix_erratum_843419 & ERRAT_ADR)
       && (imm >= AARCH64_MIN_ADRP_IMM  && imm <= AARCH64_MAX_ADRP_IMM))
     {
       insn = (_bfd_aarch64_reencode_adr_imm (AARCH64_ADR_OP, imm)
              | AARCH64_RT (insn));
       bfd_putl32 (insn, contents + stub_entry->adrp_offset);
+      /* Stub is not needed, don't map it out.  */
+      stub_entry->stub_type = aarch64_stub_none;
     }
-  else
+  else if (htab->fix_erratum_843419 & ERRAT_ADRP)
     {
       bfd_vma veneered_insn_loc;
       bfd_vma veneer_entry_loc;
@@ -5334,6 +5386,21 @@ _bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry,
       branch_insn |= branch_offset;
       bfd_putl32 (branch_insn, contents + stub_entry->target_value);
     }
+  else
+    {
+      abfd = stub_entry->target_section->owner;
+      _bfd_error_handler
+       (_("%pB: error: erratum 843419 immediate 0x%" BFD_VMA_FMT "x "
+          "out of range for ADR (input file too large) and "
+          "--fix-cortex-a53-843419=adr used.  Run the linker with "
+          "--fix-cortex-a53-843419=full instead"), abfd, imm);
+      bfd_set_error (bfd_error_bad_value);
+      /* This function is called inside a hashtable traversal and the error
+        handlers called above turn into non-fatal errors.  Which means this
+        case ld returns an exit code 0 and also produces a broken object file.
+        To prevent this, issue a hard abort.  */
+      BFD_FAIL ();
+    }
   return TRUE;
 }
 
@@ -5423,6 +5490,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
   bfd_vma orig_value = value;
   bfd_boolean resolved_to_zero;
   bfd_boolean abs_symbol_p;
+  bfd_boolean via_plt_p;
 
   globals = elf_aarch64_hash_table (info);
 
@@ -5444,6 +5512,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
                  : bfd_is_und_section (sym_sec));
   abs_symbol_p = h != NULL && bfd_is_abs_symbol (&h->root);
 
+  via_plt_p = (globals->root.splt != NULL && h != NULL
+              && h->plt.offset != (bfd_vma) - 1);
 
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle
      it here if it is defined in a non-shared object.  */
@@ -5491,7 +5561,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
       switch (bfd_r_type)
        {
        default:
-bad_ifunc_reloc:
+       bad_ifunc_reloc:
          if (h->root.root.string)
            name = h->root.root.string;
          else
@@ -5571,7 +5641,8 @@ bad_ifunc_reloc:
          /* FALLTHROUGH */
        case BFD_RELOC_AARCH64_CALL26:
        case BFD_RELOC_AARCH64_JUMP26:
-         value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+         value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                      place, value,
                                                       signed_addend,
                                                       weak_undef_p);
          return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type,
@@ -5648,7 +5719,8 @@ bad_ifunc_reloc:
            addend = (globals->root.sgot->output_section->vma
                      + globals->root.sgot->output_offset);
 
-         value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+         value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                      place, value,
                                                       addend, weak_undef_p);
          return _bfd_aarch64_elf_put_addend (input_bfd, hit_data, bfd_r_type, howto, value);
        case BFD_RELOC_AARCH64_ADD_LO12:
@@ -5777,12 +5849,23 @@ bad_ifunc_reloc:
        value += signed_addend;
       break;
 
+    case BFD_RELOC_AARCH64_BRANCH19:
+    case BFD_RELOC_AARCH64_TSTBR14:
+      /* A conditional branch to an undefined weak symbol is converted to a
+        branch to itself.  */
+      if (weak_undef_p && !via_plt_p)
+       {
+         value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                      place, value,
+                                                      signed_addend,
+                                                      weak_undef_p);
+         break;
+       }
+      /* Fall through.  */
     case BFD_RELOC_AARCH64_CALL26:
     case BFD_RELOC_AARCH64_JUMP26:
       {
        asection *splt = globals->root.splt;
-       bfd_boolean via_plt_p =
-         splt != NULL && h != NULL && h->plt.offset != (bfd_vma) - 1;
 
        /* A call to an undefined weak symbol is converted to a jump to
           the next instruction unless a PLT entry will be created.
@@ -5826,7 +5909,8 @@ bad_ifunc_reloc:
            signed_addend = 0;
          }
       }
-      value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+      value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                  place, value,
                                                   signed_addend, weak_undef_p);
       *unresolved_reloc_p = FALSE;
       break;
@@ -5869,7 +5953,6 @@ bad_ifunc_reloc:
     case BFD_RELOC_AARCH64_32:
 #endif
     case BFD_RELOC_AARCH64_ADD_LO12:
-    case BFD_RELOC_AARCH64_BRANCH19:
     case BFD_RELOC_AARCH64_LDST128_LO12:
     case BFD_RELOC_AARCH64_LDST16_LO12:
     case BFD_RELOC_AARCH64_LDST32_LO12:
@@ -5885,8 +5968,8 @@ bad_ifunc_reloc:
     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,
+      value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                  place, value,
                                                   signed_addend, weak_undef_p);
       break;
 
@@ -5931,7 +6014,8 @@ bad_ifunc_reloc:
          if (aarch64_relocation_aginst_gp_p (bfd_r_type))
            addend = (globals->root.sgot->output_section->vma
                      + globals->root.sgot->output_offset);
-         value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+         value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                      place, value,
                                                       addend, weak_undef_p);
        }
       else
@@ -5978,7 +6062,8 @@ bad_ifunc_reloc:
        if (aarch64_relocation_aginst_gp_p (bfd_r_type))
          addend = base_got->output_section->vma + base_got->output_offset;
 
-       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+       value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                    place, value,
                                                     addend, weak_undef_p);
       }
 
@@ -6015,7 +6100,8 @@ bad_ifunc_reloc:
               + globals->root.sgot->output_section->vma
               + globals->root.sgot->output_offset);
 
-      value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+      value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                  place, value,
                                                   0, weak_undef_p);
       *unresolved_reloc_p = FALSE;
       break;
@@ -6028,7 +6114,8 @@ bad_ifunc_reloc:
        return bfd_reloc_notsupported;
 
       value = symbol_got_offset (input_bfd, h, r_symndx);
-      value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+      value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                  place, value,
                                                   0, weak_undef_p);
       *unresolved_reloc_p = FALSE;
       break;
@@ -6049,10 +6136,26 @@ bad_ifunc_reloc:
     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
     case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
-      value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
-                                                  signed_addend - dtpoff_base (info),
-                                                  weak_undef_p);
-      break;
+      {
+       if (!(weak_undef_p || elf_hash_table (info)->tls_sec))
+         {
+           int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: TLS relocation %s against undefined symbol `%s'"),
+                input_bfd, elfNN_aarch64_howto_table[howto_index].name,
+                h->root.root.string);
+           bfd_set_error (bfd_error_bad_value);
+           return bfd_reloc_notsupported;
+         }
+
+       bfd_vma def_value
+         = weak_undef_p ? 0 : signed_addend - dtpoff_base (info);
+       value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                    place, value,
+                                                    def_value, weak_undef_p);
+       break;
+      }
 
     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
@@ -6070,11 +6173,27 @@ bad_ifunc_reloc:
     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:
-      value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
-                                                  signed_addend - tpoff_base (info),
-                                                  weak_undef_p);
-      *unresolved_reloc_p = FALSE;
-      break;
+      {
+       if (!(weak_undef_p || elf_hash_table (info)->tls_sec))
+         {
+           int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+           _bfd_error_handler
+             /* xgettext:c-format */
+             (_("%pB: TLS relocation %s against undefined symbol `%s'"),
+                input_bfd, elfNN_aarch64_howto_table[howto_index].name,
+                h->root.root.string);
+           bfd_set_error (bfd_error_bad_value);
+           return bfd_reloc_notsupported;
+         }
+
+       bfd_vma def_value
+         = weak_undef_p ? 0 : signed_addend - tpoff_base (info);
+       value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                    place, value,
+                                                    def_value, weak_undef_p);
+        *unresolved_reloc_p = FALSE;
+       break;
+      }
 
     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
     case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
@@ -6089,7 +6208,8 @@ bad_ifunc_reloc:
               + globals->root.sgotplt->output_offset
               + globals->sgotplt_jump_table_size);
 
-      value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+      value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                  place, value,
                                                   0, weak_undef_p);
       *unresolved_reloc_p = FALSE;
       break;
@@ -6107,7 +6227,8 @@ bad_ifunc_reloc:
       value -= (globals->root.sgot->output_section->vma
                + globals->root.sgot->output_offset);
 
-      value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
+      value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+                                                  place, value,
                                                   0, weak_undef_p);
       *unresolved_reloc_p = FALSE;
       break;
@@ -6203,7 +6324,7 @@ static void
 clear_erratum_843419_entry (struct elf_aarch64_link_hash_table *globals,
                            bfd_vma adrp_offset, asection *input_section)
 {
-  if (globals->fix_erratum_843419)
+  if (globals->fix_erratum_843419 & ERRAT_ADRP)
     {
       struct erratum_843419_branch_to_stub_clear_data data;
       data.adrp_offset = adrp_offset;
@@ -6733,7 +6854,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
          name = (bfd_elf_string_from_elf_section
                  (input_bfd, symtab_hdr->sh_link, sym->st_name));
          if (name == NULL || *name == '\0')
-           name = bfd_section_name (input_bfd, sec);
+           name = bfd_section_name (sec);
        }
 
       if (r_symndx != 0
@@ -7216,7 +7337,7 @@ elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
 
       for (sec = ibfd->sections; sec != NULL; sec = sec->next)
        {
-         if ((bfd_get_section_flags (ibfd, sec)
+         if ((bfd_section_flags (sec)
               & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
              == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
            only_data_sections = FALSE;
@@ -7267,7 +7388,7 @@ readonly_dynrelocs (struct elf_link_hash_entry *h)
 {
   struct elf_dyn_relocs *p;
 
-  for (p = elf_aarch64_hash_entry (h)->dyn_relocs; p != NULL; p = p->next)
+  for (p = h->dyn_relocs; p != NULL; p = p->next)
     {
       asection *s = p->sec->output_section;
 
@@ -7285,7 +7406,7 @@ need_copy_relocation_p (struct elf_aarch64_link_hash_entry *eh)
   struct elf_dyn_relocs *p;
   asection *s;
 
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+  for (p = eh->root.dyn_relocs; p != NULL; p = p->next)
     {
       /* If there is any pc-relative reference, we need to keep copy relocation
         to avoid propagating the relocation into runtime that current glibc
@@ -7462,13 +7583,13 @@ aarch64_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
                                          (bed->dynamic_sec_flags
                                           | SEC_READONLY));
   if (s == NULL
-      || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
   htab->srelgot = s;
 
   s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
   if (s == NULL
-      || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+      || !bfd_set_section_alignment (s, bed->s->log_file_align))
     return FALSE;
   htab->sgot = s;
   htab->sgot->size += GOT_ENTRY_SIZE;
@@ -7490,8 +7611,7 @@ aarch64_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
     {
       s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
       if (s == NULL
-         || !bfd_set_section_alignment (abfd, s,
-                                        bed->s->log_file_align))
+         || !bfd_set_section_alignment (s, bed->s->log_file_align))
        return FALSE;
       htab->sgotplt = s;
     }
@@ -7765,9 +7885,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
               relocations we need for this symbol.  */
            if (h != NULL)
              {
-               struct elf_aarch64_link_hash_entry *eh;
-               eh = (struct elf_aarch64_link_hash_entry *) h;
-               head = &eh->dyn_relocs;
+               head = &h->dyn_relocs;
              }
            else
              {
@@ -7796,7 +7914,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            p = *head;
            if (p == NULL || p->sec != sec)
              {
-               bfd_size_type amt = sizeof *p;
+               size_t amt = sizeof *p;
                p = ((struct elf_dyn_relocs *)
                     bfd_zalloc (htab->root.dynobj, amt));
                if (p == NULL)
@@ -7910,6 +8028,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            break;
          }
 
+       case BFD_RELOC_AARCH64_BRANCH19:
+       case BFD_RELOC_AARCH64_TSTBR14:
        case BFD_RELOC_AARCH64_CALL26:
        case BFD_RELOC_AARCH64_JUMP26:
          /* If this is a local symbol then we resolve it
@@ -7942,116 +8062,43 @@ elfNN_aarch64_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED,
                                             BFD_AARCH64_SPECIAL_SYM_TYPE_ANY);
 }
 
-/* This is a copy of elf_find_function () from elf.c except that
-   AArch64 mapping symbols are ignored when looking for function names.  */
+/* If the ELF symbol SYM might be a function in SEC, return the
+   function size and set *CODE_OFF to the function's entry point,
+   otherwise return zero.  */
 
-static bfd_boolean
-aarch64_elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
-                          asymbol **symbols,
-                          asection *section,
-                          bfd_vma offset,
-                          const char **filename_ptr,
-                          const char **functionname_ptr)
+static bfd_size_type
+elfNN_aarch64_maybe_function_sym (const asymbol *sym, asection *sec,
+                                 bfd_vma *code_off)
 {
-  const char *filename = NULL;
-  asymbol *func = NULL;
-  bfd_vma low_func = 0;
-  asymbol **p;
-
-  for (p = symbols; *p != NULL; p++)
-    {
-      elf_symbol_type *q;
+  bfd_size_type size;
 
-      q = (elf_symbol_type *) * p;
+  if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+                    | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0
+      || sym->section != sec)
+    return 0;
 
-      switch (ELF_ST_TYPE (q->internal_elf_sym.st_info))
-       {
-       default:
-         break;
-       case STT_FILE:
-         filename = bfd_asymbol_name (&q->symbol);
-         break;
+  if (!(sym->flags & BSF_SYNTHETIC))
+    switch (ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info))
+      {
        case STT_FUNC:
        case STT_NOTYPE:
-         /* Skip mapping symbols.  */
-         if ((q->symbol.flags & BSF_LOCAL)
-             && (bfd_is_aarch64_special_symbol_name
-                 (q->symbol.name, BFD_AARCH64_SPECIAL_SYM_TYPE_ANY)))
-           continue;
-         /* Fall through.  */
-         if (bfd_get_section (&q->symbol) == section
-             && q->symbol.value >= low_func && q->symbol.value <= offset)
-           {
-             func = (asymbol *) q;
-             low_func = q->symbol.value;
-           }
          break;
-       }
-    }
-
-  if (func == NULL)
-    return FALSE;
-
-  if (filename_ptr)
-    *filename_ptr = filename;
-  if (functionname_ptr)
-    *functionname_ptr = bfd_asymbol_name (func);
-
-  return TRUE;
-}
-
-
-/* Find the nearest line to a particular section and offset, for error
-   reporting.   This code is a duplicate of the code in elf.c, except
-   that it uses aarch64_elf_find_function.  */
-
-static bfd_boolean
-elfNN_aarch64_find_nearest_line (bfd *abfd,
-                                asymbol **symbols,
-                                asection *section,
-                                bfd_vma offset,
-                                const char **filename_ptr,
-                                const char **functionname_ptr,
-                                unsigned int *line_ptr,
-                                unsigned int *discriminator_ptr)
-{
-  bfd_boolean found = FALSE;
-
-  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
-                                    filename_ptr, functionname_ptr,
-                                    line_ptr, discriminator_ptr,
-                                    dwarf_debug_sections, 0,
-                                    &elf_tdata (abfd)->dwarf2_find_line_info))
-    {
-      if (!*functionname_ptr)
-       aarch64_elf_find_function (abfd, symbols, section, offset,
-                                  *filename_ptr ? NULL : filename_ptr,
-                                  functionname_ptr);
-
-      return TRUE;
-    }
-
-  /* Skip _bfd_dwarf1_find_nearest_line since no known AArch64
-     toolchain uses DWARF1.  */
-
-  if (!_bfd_stab_section_find_nearest_line (abfd, symbols, section, offset,
-                                           &found, filename_ptr,
-                                           functionname_ptr, line_ptr,
-                                           &elf_tdata (abfd)->line_info))
-    return FALSE;
-
-  if (found && (*functionname_ptr || *line_ptr))
-    return TRUE;
-
-  if (symbols == NULL)
-    return FALSE;
+       default:
+         return 0;
+      }
 
-  if (!aarch64_elf_find_function (abfd, symbols, section, offset,
-                                 filename_ptr, functionname_ptr))
-    return FALSE;
+  if ((sym->flags & BSF_LOCAL)
+      && bfd_is_aarch64_special_symbol_name (sym->name,
+                                            BFD_AARCH64_SPECIAL_SYM_TYPE_ANY))
+    return 0;
 
-  *line_ptr = 0;
-  return TRUE;
+  *code_off = sym->value;
+  size = 0;
+  if (!(sym->flags & BSF_SYNTHETIC))
+    size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size;
+  if (size == 0)
+    size = 1;
+  return size;
 }
 
 static bfd_boolean
@@ -8068,16 +8115,17 @@ elfNN_aarch64_find_inliner_info (bfd *abfd,
 }
 
 
-static void
-elfNN_aarch64_post_process_headers (bfd *abfd,
-                                   struct bfd_link_info *link_info)
+static bfd_boolean
+elfNN_aarch64_init_file_header (bfd *abfd, struct bfd_link_info *link_info)
 {
   Elf_Internal_Ehdr *i_ehdrp;  /* ELF file header, internal form.  */
 
+  if (!_bfd_elf_init_file_header (abfd, link_info))
+    return FALSE;
+
   i_ehdrp = elf_elfheader (abfd);
   i_ehdrp->e_ident[EI_ABIVERSION] = AARCH64_ELF_ABI_VERSION;
-
-  _bfd_elf_post_process_headers (abfd, link_info);
+  return TRUE;
 }
 
 static enum elf_reloc_type_class
@@ -8434,7 +8482,7 @@ elfNN_aarch64_new_section_hook (bfd *abfd, asection *sec)
   if (!sec->used_by_bfd)
     {
       _aarch64_elf_section_data *sdata;
-      bfd_size_type amt = sizeof (*sdata);
+      size_t amt = sizeof (*sdata);
 
       sdata = bfd_zalloc (abfd, amt);
       if (sdata == NULL)
@@ -8585,6 +8633,12 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
             updated.  */
 
          htab->root.srelplt->reloc_count++;
+
+         /* Mark the DSO in case R_<CLS>_JUMP_SLOT relocs against
+            variant PCS symbols are present.  */
+         if (h->other & STO_AARCH64_VARIANT_PCS)
+           htab->variant_pcs = 1;
+
        }
       else
        {
@@ -8692,7 +8746,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       h->got.offset = (bfd_vma) - 1;
     }
 
-  if (eh->dyn_relocs == NULL)
+  if (h->dyn_relocs == NULL)
     return TRUE;
 
   /* In the shared -Bsymbolic case, discard space allocated for
@@ -8713,7 +8767,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
        {
          struct elf_dyn_relocs **pp;
 
-         for (pp = &eh->dyn_relocs; (p = *pp) != NULL;)
+         for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
            {
              p->count -= p->pc_count;
              p->pc_count = 0;
@@ -8726,11 +8780,11 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       /* Also discard relocs on undefined weak syms with non-default
         visibility.  */
-      if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak)
+      if (h->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak)
        {
          if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
              || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
-           eh->dyn_relocs = NULL;
+           h->dyn_relocs = NULL;
 
          /* Make sure undefined weak symbols are output as a dynamic
             symbol in PIEs.  */
@@ -8769,13 +8823,13 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
            goto keep;
        }
 
-      eh->dyn_relocs = NULL;
+      h->dyn_relocs = NULL;
 
     keep:;
     }
 
   /* Finally, allocate space.  */
-  for (p = eh->dyn_relocs; p != NULL; p = p->next)
+  for (p = h->dyn_relocs; p != NULL; p = p->next)
     {
       asection *sreloc;
 
@@ -8798,7 +8852,6 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
 {
   struct bfd_link_info *info;
   struct elf_aarch64_link_hash_table *htab;
-  struct elf_aarch64_link_hash_entry *eh;
 
   /* An example of a bfd_link_hash_indirect symbol is versioned
      symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
@@ -8818,14 +8871,12 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
   info = (struct bfd_link_info *) inf;
   htab = elf_aarch64_hash_table (info);
 
-  eh = (struct elf_aarch64_link_hash_entry *) h;
-
   /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
      here if it is defined and referenced in a non-shared object.  */
   if (h->type == STT_GNU_IFUNC
       && h->def_regular)
     return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
-                                              &eh->dyn_relocs,
+                                              &h->dyn_relocs,
                                               NULL,
                                               htab->plt_entry_size,
                                               htab->plt_header_size,
@@ -8834,25 +8885,6 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h,
   return TRUE;
 }
 
-/* Allocate space in .plt, .got and associated reloc sections for
-   local dynamic relocs.  */
-
-static bfd_boolean
-elfNN_aarch64_allocate_local_dynrelocs (void **slot, void *inf)
-{
-  struct elf_link_hash_entry *h
-    = (struct elf_link_hash_entry *) *slot;
-
-  if (h->type != STT_GNU_IFUNC
-      || !h->def_regular
-      || !h->ref_regular
-      || !h->forced_local
-      || h->root.type != bfd_link_hash_defined)
-    abort ();
-
-  return elfNN_aarch64_allocate_dynrelocs (h, inf);
-}
-
 /* Allocate space in .plt, .got and associated reloc sections for
    local ifunc dynamic relocs.  */
 
@@ -9040,11 +9072,6 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   elf_link_hash_traverse (&htab->root, elfNN_aarch64_allocate_ifunc_dynrelocs,
                          info);
 
-  /* Allocate .plt and .got entries, and space for local symbols.  */
-  htab_traverse (htab->loc_hash_table,
-                elfNN_aarch64_allocate_local_dynrelocs,
-                info);
-
   /* Allocate .plt and .got entries, and space for local ifunc symbols.  */
   htab_traverse (htab->loc_hash_table,
                 elfNN_aarch64_allocate_local_ifunc_dynrelocs,
@@ -9105,7 +9132,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
          /* Strip this section if we don't need it; see the
             comment below.  */
        }
-      else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rela"))
+      else if (CONST_STRNEQ (bfd_section_name (s), ".rela"))
        {
          if (s->size != 0 && s != htab->root.srelplt)
            relocs = TRUE;
@@ -9173,6 +9200,10 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              || !add_dynamic_entry (DT_JMPREL, 0))
            return FALSE;
 
+         if (htab->variant_pcs
+             && !add_dynamic_entry (DT_AARCH64_VARIANT_PCS, 0))
+           return FALSE;
+
          if (htab->tlsdesc_plt
              && !(info->flags & DF_BIND_NOW)
              && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
@@ -9511,7 +9542,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
        }
       else
        {
-do_glob_dat:
+       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);
@@ -9720,7 +9751,6 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
          if (type == PLT_BTI || type == PLT_BTI_PAC)
            {
              entry = elfNN_aarch64_tlsdesc_small_plt_bti_entry;
-             htab->tlsdesc_plt_entry_size = PLT_BTI_TLSDESC_ENTRY_SIZE;
            }
 
          memcpy (htab->root.splt->contents + htab->tlsdesc_plt,
@@ -9896,7 +9926,6 @@ elfNN_aarch64_plt_sym_val (bfd_vma i, const asection *plt,
 
   if (elf_aarch64_tdata (plt->owner)->plt_type == PLT_BTI_PAC)
     {
-      plt0_size = PLT_BTI_PAC_ENTRY_SIZE;
       if (elf_elfheader (plt->owner)->e_type == ET_EXEC)
        pltn_size = PLT_BTI_PAC_SMALL_ENTRY_SIZE;
       else
@@ -9904,13 +9933,11 @@ elfNN_aarch64_plt_sym_val (bfd_vma i, const asection *plt,
     }
   else if (elf_aarch64_tdata (plt->owner)->plt_type == PLT_BTI)
     {
-      plt0_size = PLT_BTI_ENTRY_SIZE;
       if (elf_elfheader (plt->owner)->e_type == ET_EXEC)
        pltn_size = PLT_BTI_SMALL_ENTRY_SIZE;
     }
   else if (elf_aarch64_tdata (plt->owner)->plt_type == PLT_PAC)
     {
-      plt0_size = PLT_PAC_ENTRY_SIZE;
       pltn_size = PLT_PAC_SMALL_ENTRY_SIZE;
     }
 
@@ -9990,14 +10017,14 @@ elfNN_aarch64_merge_gnu_properties (struct bfd_link_info *info,
       if ((aprop && !(aprop->u.number & GNU_PROPERTY_AARCH64_FEATURE_1_BTI))
           || !aprop)
        {
-         _bfd_error_handler (_("%pB: warning: BTI turned on by --force-bti when "
+         _bfd_error_handler (_("%pB: warning: BTI turned on by -force-bti when "
                                "all inputs do not have BTI in NOTE section."),
                              abfd);
        }
       if ((bprop && !(bprop->u.number & GNU_PROPERTY_AARCH64_FEATURE_1_BTI))
           || !bprop)
        {
-         _bfd_error_handler (_("%pB: warning: BTI turned on by --force-bti when "
+         _bfd_error_handler (_("%pB: warning: BTI turned on by -force-bti when "
                                "all inputs do not have BTI in NOTE section."),
                              bbfd);
        }
@@ -10077,9 +10104,6 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define bfd_elfNN_find_inliner_info            \
   elfNN_aarch64_find_inliner_info
 
-#define bfd_elfNN_find_nearest_line            \
-  elfNN_aarch64_find_nearest_line
-
 #define bfd_elfNN_get_synthetic_symtab         \
   elfNN_aarch64_get_synthetic_symtab
 
@@ -10101,6 +10125,9 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_copy_indirect_symbol       \
   elfNN_aarch64_copy_indirect_symbol
 
+#define elf_backend_merge_symbol_attribute     \
+  elfNN_aarch64_merge_symbol_attribute
+
 /* Create .dynbss, and .rela.bss sections in DYNOBJ, and set up shortcuts
    to them in our hash.  */
 #define elf_backend_create_dynamic_sections    \
@@ -10121,11 +10148,14 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_output_arch_local_syms     \
   elfNN_aarch64_output_arch_local_syms
 
+#define elf_backend_maybe_function_sym         \
+  elfNN_aarch64_maybe_function_sym
+
 #define elf_backend_plt_sym_val                        \
   elfNN_aarch64_plt_sym_val
 
-#define elf_backend_post_process_headers       \
-  elfNN_aarch64_post_process_headers
+#define elf_backend_init_file_header           \
+  elfNN_aarch64_init_file_header
 
 #define elf_backend_relocate_section           \
   elfNN_aarch64_relocate_section
This page took 0.043642 seconds and 4 git commands to generate.