[AArch64] PR18270, fix handling of GOT entry for local symbol
[deliverable/binutils-gdb.git] / bfd / elfnn-aarch64.c
index 0573d6a0f1faf54906a712f1b96e3f6188ce3c55..c252b13f515e1b9a892ae40b91e29ed0187cb857 100644 (file)
@@ -1,5 +1,5 @@
 /* AArch64-specific support for NN-bit ELF.
-   Copyright 2009-2013  Free Software Foundation, Inc.
+   Copyright (C) 2009-2015 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 #define IS_AARCH64_TLS_RELOC(R_TYPE)                           \
   ((R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21              \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADR_PREL21           \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC          \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1     \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC  \
 
 #define IS_AARCH64_TLSDESC_RELOC(R_TYPE)                       \
   ((R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD_PREL19             \
-   || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21         \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21         \
+   || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21         \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC                \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC       \
    || (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC       \
@@ -296,7 +297,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
 #if ARCH_SIZE == 64
   HOWTO (R_AARCH64_NULL,       /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -310,7 +311,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
 #else
   HOWTO (R_AARCH64_NONE,       /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -863,6 +864,20 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
         0x1fffff,              /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
+  HOWTO (AARCH64_R (TLSGD_ADR_PREL21), /* type */
+        0,                     /* rightshift */
+        2,                     /* size (0 = byte, 1 = short, 2 = long) */
+        21,                    /* bitsize */
+        TRUE,                  /* pc_relative */
+        0,                     /* bitpos */
+        complain_overflow_dont,        /* complain_on_overflow */
+        bfd_elf_generic_reloc, /* special_function */
+        AARCH64_R_STR (TLSGD_ADR_PREL21),      /* name */
+        FALSE,                 /* partial_inplace */
+        0x1fffff,              /* src_mask */
+        0x1fffff,              /* dst_mask */
+        TRUE),                 /* pcrel_offset */
+
   /* ADD: GOT offset G(S) & 0xff8 [no overflow check] */
   HOWTO (AARCH64_R (TLSGD_ADD_LO12_NC),        /* type */
         0,                     /* rightshift */
@@ -895,7 +910,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO64 (AARCH64_R (TLSIE_MOVW_GOTTPREL_G0_NC),      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        32,                    /* bitsize */
+        16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
@@ -951,7 +966,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO (AARCH64_R (TLSIE_LD_GOTTPREL_PREL19), /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        21,                    /* bitsize */
+        19,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
@@ -965,10 +980,10 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G2),    /* type */
         32,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        12,                    /* bitsize */
+        16,                    /* 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_MOVW_TPREL_G2),   /* name */
         FALSE,                 /* partial_inplace */
@@ -979,7 +994,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G1),      /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        12,                    /* bitsize */
+        16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
@@ -993,7 +1008,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO64 (AARCH64_R (TLSLE_MOVW_TPREL_G1_NC), /* type */
         16,                    /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        12,                    /* bitsize */
+        16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
@@ -1007,7 +1022,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0),      /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        12,                    /* bitsize */
+        16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
@@ -1021,7 +1036,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO (AARCH64_R (TLSLE_MOVW_TPREL_G0_NC),   /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        12,                    /* bitsize */
+        16,                    /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
@@ -1038,7 +1053,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_HI12),  /* name */
         FALSE,                 /* partial_inplace */
@@ -1077,15 +1092,15 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO (AARCH64_R (TLSDESC_LD_PREL19),        /* type */
         2,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        21,                    /* bitsize */
+        19,                    /* bitsize */
         TRUE,                  /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
         bfd_elf_generic_reloc, /* special_function */
         AARCH64_R_STR (TLSDESC_LD_PREL19),     /* name */
         FALSE,                 /* partial_inplace */
-        0x1ffffc,              /* src_mask */
-        0x1ffffc,              /* dst_mask */
+        0x0ffffe0,             /* src_mask */
+        0x0ffffe0,             /* dst_mask */
         TRUE),                 /* pcrel_offset */
 
   HOWTO (AARCH64_R (TLSDESC_ADR_PREL21),       /* type */
@@ -1222,7 +1237,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
   HOWTO (AARCH64_R (TLSDESC_CALL),     /* type */
         0,                     /* rightshift */
         2,                     /* size (0 = byte, 1 = short, 2 = long) */
-        12,                    /* bitsize */
+        0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
         complain_overflow_dont,        /* complain_on_overflow */
@@ -1377,7 +1392,7 @@ static reloc_howto_type elfNN_aarch64_howto_table[] =
 static reloc_howto_type elfNN_aarch64_howto_none =
   HOWTO (R_AARCH64_NONE,       /* type */
         0,                     /* rightshift */
-        0,                     /* size (0 = byte, 1 = short, 2 = long) */
+        3,                     /* size (0 = byte, 1 = short, 2 = long) */
         0,                     /* bitsize */
         FALSE,                 /* pc_relative */
         0,                     /* bitpos */
@@ -1431,6 +1446,14 @@ elfNN_aarch64_bfd_reloc_from_type (unsigned int r_type)
   if (r_type == R_AARCH64_NONE || r_type == R_AARCH64_NULL)
     return BFD_RELOC_AARCH64_NONE;
 
+  /* PR 17512: file: b371e70a.  */
+  if (r_type >= R_AARCH64_end)
+    {
+      _bfd_error_handler (_("Invalid AArch64 reloc number: %d"), r_type);
+      bfd_set_error (bfd_error_bad_value);
+      return BFD_RELOC_AARCH64_NONE;
+    }
+
   return BFD_RELOC_AARCH64_RELOC_START + offsets[r_type];
 }
 
@@ -1548,9 +1571,9 @@ elfNN_aarch64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
   return NULL;
 }
 
-#define TARGET_LITTLE_SYM               bfd_elfNN_littleaarch64_vec
+#define TARGET_LITTLE_SYM               aarch64_elfNN_le_vec
 #define TARGET_LITTLE_NAME              "elfNN-littleaarch64"
-#define TARGET_BIG_SYM                  bfd_elfNN_bigaarch64_vec
+#define TARGET_BIG_SYM                  aarch64_elfNN_be_vec
 #define TARGET_BIG_NAME                 "elfNN-bigaarch64"
 
 /* The linker script knows the section names for placement.
@@ -1611,6 +1634,18 @@ static const uint32_t aarch64_long_branch_stub[] =
   0x00000000,
 };
 
+static const uint32_t aarch64_erratum_835769_stub[] =
+{
+  0x00000000,    /* Placeholder for multiply accumulate.  */
+  0x14000000,    /* b <label> */
+};
+
+static const uint32_t aarch64_erratum_843419_stub[] =
+{
+  0x00000000,    /* Placeholder for LDR instruction.  */
+  0x14000000,    /* b <label> */
+};
+
 /* Section name for stubs is the associated section name plus this
    string.  */
 #define STUB_SUFFIX ".stub"
@@ -1620,6 +1655,8 @@ enum elf_aarch64_stub_type
   aarch64_stub_none,
   aarch64_stub_adrp_branch,
   aarch64_stub_long_branch,
+  aarch64_stub_erratum_835769_veneer,
+  aarch64_stub_erratum_843419_veneer,
 };
 
 struct elf_aarch64_stub_hash_entry
@@ -1654,6 +1691,13 @@ struct elf_aarch64_stub_hash_entry
      stub name in the hash table has to be unique; this does not, so
      it can be friendlier.  */
   char *output_name;
+
+  /* The instruction which caused this stub to be generated (only valid for
+     erratum 835769 workaround stubs at present).  */
+  uint32_t veneered_insn;
+
+  /* In an erratum 843419 workaround stub, the ADRP instruction offset.  */
+  bfd_vma adrp_offset;
 };
 
 /* Used to build a map of a section.  This is required for mixed-endian
@@ -1799,6 +1843,15 @@ struct elf_aarch64_link_hash_table
   /* Nonzero to force PIC branch veneers.  */
   int pic_veneer;
 
+  /* Fix erratum 835769.  */
+  int fix_erratum_835769;
+
+  /* Fix erratum 843419.  */
+  int fix_erratum_843419;
+
+  /* Enable ADRP->ADR rewrite for erratum 843419 workaround.  */
+  int fix_erratum_843419_adr;
+
   /* The number of bytes in the initial entry in the PLT.  */
   bfd_size_type plt_header_size;
 
@@ -1920,6 +1973,7 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
 
       /* Initialize the local fields.  */
       eh = (struct elf_aarch64_stub_hash_entry *) entry;
+      eh->adrp_offset = 0;
       eh->stub_sec = NULL;
       eh->stub_offset = 0;
       eh->target_value = 0;
@@ -2055,6 +2109,23 @@ elfNN_aarch64_copy_indirect_symbol (struct bfd_link_info *info,
   _bfd_elf_link_hash_copy_indirect (info, dir, ind);
 }
 
+/* Destroy an AArch64 elf linker hash table.  */
+
+static void
+elfNN_aarch64_link_hash_table_free (bfd *obfd)
+{
+  struct elf_aarch64_link_hash_table *ret
+    = (struct elf_aarch64_link_hash_table *) obfd->link.hash;
+
+  if (ret->loc_hash_table)
+    htab_delete (ret->loc_hash_table);
+  if (ret->loc_hash_memory)
+    objalloc_free ((struct objalloc *) ret->loc_hash_memory);
+
+  bfd_hash_table_free (&ret->stub_hash_table);
+  _bfd_elf_link_hash_table_free (obfd);
+}
+
 /* Create an AArch64 elf linker hash table.  */
 
 static struct bfd_link_hash_table *
@@ -2083,7 +2154,7 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
   if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc,
                            sizeof (struct elf_aarch64_stub_hash_entry)))
     {
-      free (ret);
+      _bfd_elf_link_hash_table_free (abfd);
       return NULL;
     }
 
@@ -2094,30 +2165,14 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
   ret->loc_hash_memory = objalloc_create ();
   if (!ret->loc_hash_table || !ret->loc_hash_memory)
     {
-      free (ret);
+      elfNN_aarch64_link_hash_table_free (abfd);
       return NULL;
     }
+  ret->root.root.hash_table_free = elfNN_aarch64_link_hash_table_free;
 
   return &ret->root.root;
 }
 
-/* Free the derived linker hash table.  */
-
-static void
-elfNN_aarch64_hash_table_free (struct bfd_link_hash_table *hash)
-{
-  struct elf_aarch64_link_hash_table *ret
-    = (struct elf_aarch64_link_hash_table *) hash;
-
-  if (ret->loc_hash_table)
-    htab_delete (ret->loc_hash_table);
-  if (ret->loc_hash_memory)
-    objalloc_free ((struct objalloc *) ret->loc_hash_memory);
-
-  bfd_hash_table_free (&ret->stub_hash_table);
-  _bfd_elf_link_hash_table_free (hash);
-}
-
 static bfd_boolean
 aarch64_relocate (unsigned int r_type, bfd *input_bfd, asection *input_section,
                  bfd_vma offset, bfd_vma value)
@@ -2277,44 +2332,72 @@ elfNN_aarch64_get_stub_entry (const asection *input_section,
   return stub_entry;
 }
 
-/* Add a new stub entry to the stub hash.  Not all fields of the new
-   stub entry are initialised.  */
+
+/* Create a stub section.  */
+
+static asection *
+_bfd_aarch64_create_stub_section (asection *section,
+                                 struct elf_aarch64_link_hash_table *htab)
+{
+  size_t namelen;
+  bfd_size_type len;
+  char *s_name;
+
+  namelen = strlen (section->name);
+  len = namelen + sizeof (STUB_SUFFIX);
+  s_name = bfd_alloc (htab->stub_bfd, len);
+  if (s_name == NULL)
+    return NULL;
+
+  memcpy (s_name, section->name, namelen);
+  memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
+  return (*htab->add_stub_section) (s_name, section);
+}
+
+
+/* Find or create a stub section for a link section.
+
+   Fix or create the stub section used to collect stubs attached to
+   the specified link section.  */
+
+static asection *
+_bfd_aarch64_get_stub_for_link_section (asection *link_section,
+                                       struct elf_aarch64_link_hash_table *htab)
+{
+  if (htab->stub_group[link_section->id].stub_sec == NULL)
+    htab->stub_group[link_section->id].stub_sec
+      = _bfd_aarch64_create_stub_section (link_section, htab);
+  return htab->stub_group[link_section->id].stub_sec;
+}
+
+
+/* Find or create a stub section in the stub group for an input
+   section.  */
+
+static asection *
+_bfd_aarch64_create_or_find_stub_sec (asection *section,
+                                     struct elf_aarch64_link_hash_table *htab)
+{
+  asection *link_sec = htab->stub_group[section->id].link_sec;
+  return _bfd_aarch64_get_stub_for_link_section (link_sec, htab);
+}
+
+
+/* Add a new stub entry in the stub group associated with an input
+   section to the stub hash.  Not all fields of the new stub entry are
+   initialised.  */
 
 static struct elf_aarch64_stub_hash_entry *
-elfNN_aarch64_add_stub (const char *stub_name,
-                       asection *section,
-                       struct elf_aarch64_link_hash_table *htab)
+_bfd_aarch64_add_stub_entry_in_group (const char *stub_name,
+                                     asection *section,
+                                     struct elf_aarch64_link_hash_table *htab)
 {
   asection *link_sec;
   asection *stub_sec;
   struct elf_aarch64_stub_hash_entry *stub_entry;
 
   link_sec = htab->stub_group[section->id].link_sec;
-  stub_sec = htab->stub_group[section->id].stub_sec;
-  if (stub_sec == NULL)
-    {
-      stub_sec = htab->stub_group[link_sec->id].stub_sec;
-      if (stub_sec == NULL)
-       {
-         size_t namelen;
-         bfd_size_type len;
-         char *s_name;
-
-         namelen = strlen (link_sec->name);
-         len = namelen + sizeof (STUB_SUFFIX);
-         s_name = bfd_alloc (htab->stub_bfd, len);
-         if (s_name == NULL)
-           return NULL;
-
-         memcpy (s_name, link_sec->name, namelen);
-         memcpy (s_name + namelen, STUB_SUFFIX, sizeof (STUB_SUFFIX));
-         stub_sec = (*htab->add_stub_section) (s_name, link_sec);
-         if (stub_sec == NULL)
-           return NULL;
-         htab->stub_group[link_sec->id].stub_sec = stub_sec;
-       }
-      htab->stub_group[section->id].stub_sec = stub_sec;
-    }
+  stub_sec = _bfd_aarch64_create_or_find_stub_sec (section, htab);
 
   /* Enter this entry into the linker stub hash table.  */
   stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table, stub_name,
@@ -2333,6 +2416,34 @@ elfNN_aarch64_add_stub (const char *stub_name,
   return stub_entry;
 }
 
+/* Add a new stub entry in the final stub section to the stub hash.
+   Not all fields of the new stub entry are initialised.  */
+
+static struct elf_aarch64_stub_hash_entry *
+_bfd_aarch64_add_stub_entry_after (const char *stub_name,
+                                  asection *link_section,
+                                  struct elf_aarch64_link_hash_table *htab)
+{
+  asection *stub_sec;
+  struct elf_aarch64_stub_hash_entry *stub_entry;
+
+  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)
+    {
+      (*_bfd_error_handler) (_("cannot create stub entry %s"), stub_name);
+      return NULL;
+    }
+
+  stub_entry->stub_sec = stub_sec;
+  stub_entry->stub_offset = 0;
+  stub_entry->id_sec = link_section;
+
+  return stub_entry;
+}
+
+
 static bfd_boolean
 aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
                        void *in_arg ATTRIBUTE_UNUSED)
@@ -2342,6 +2453,9 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
   bfd *stub_bfd;
   bfd_byte *loc;
   bfd_vma sym_value;
+  bfd_vma veneered_insn_loc;
+  bfd_vma veneer_entry_loc;
+  bfd_signed_vma branch_offset = 0;
   unsigned int template_size;
   const uint32_t *template;
   unsigned int i;
@@ -2382,9 +2496,16 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
       template = aarch64_long_branch_stub;
       template_size = sizeof (aarch64_long_branch_stub);
       break;
+    case aarch64_stub_erratum_835769_veneer:
+      template = aarch64_erratum_835769_stub;
+      template_size = sizeof (aarch64_erratum_835769_stub);
+      break;
+    case aarch64_stub_erratum_843419_veneer:
+      template = aarch64_erratum_843419_stub;
+      template_size = sizeof (aarch64_erratum_843419_stub);
+      break;
     default:
-      BFD_FAIL ();
-      return FALSE;
+      abort ();
     }
 
   for (i = 0; i < (template_size / sizeof template[0]); i++)
@@ -2405,27 +2526,43 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry,
           of range.  */
        BFD_FAIL ();
 
-      _bfd_final_link_relocate
-       (elfNN_aarch64_howto_from_type (AARCH64_R (ADD_ABS_LO12_NC)),
-        stub_bfd,
-        stub_sec,
-        stub_sec->contents,
-        stub_entry->stub_offset + 4,
-        sym_value,
-        0);
+      if (aarch64_relocate (AARCH64_R (ADD_ABS_LO12_NC), stub_bfd, stub_sec,
+                           stub_entry->stub_offset + 4, sym_value))
+       BFD_FAIL ();
       break;
 
     case aarch64_stub_long_branch:
       /* We want the value relative to the address 12 bytes back from the
          value itself.  */
-      _bfd_final_link_relocate (elfNN_aarch64_howto_from_type
-                               (AARCH64_R (PRELNN)), stub_bfd, stub_sec,
-                               stub_sec->contents,
-                               stub_entry->stub_offset + 16,
-                               sym_value + 12, 0);
+      if (aarch64_relocate (AARCH64_R (PRELNN), stub_bfd, stub_sec,
+                           stub_entry->stub_offset + 16, sym_value + 12))
+       BFD_FAIL ();
       break;
-    default:
+
+    case aarch64_stub_erratum_835769_veneer:
+      veneered_insn_loc = stub_entry->target_section->output_section->vma
+                         + stub_entry->target_section->output_offset
+                         + stub_entry->target_value;
+      veneer_entry_loc = stub_entry->stub_sec->output_section->vma
+                         + stub_entry->stub_sec->output_offset
+                         + stub_entry->stub_offset;
+      branch_offset = veneered_insn_loc - veneer_entry_loc;
+      branch_offset >>= 2;
+      branch_offset &= 0x3ffffff;
+      bfd_putl32 (stub_entry->veneered_insn,
+                 stub_sec->contents + stub_entry->stub_offset);
+      bfd_putl32 (template[1] | branch_offset,
+                 stub_sec->contents + stub_entry->stub_offset + 4);
       break;
+
+    case aarch64_stub_erratum_843419_veneer:
+      if (aarch64_relocate (AARCH64_R (JUMP26), stub_bfd, stub_sec,
+                           stub_entry->stub_offset + 4, sym_value + 4))
+       BFD_FAIL ();
+      break;
+
+    default:
+      abort ();
     }
 
   return TRUE;
@@ -2452,10 +2589,14 @@ aarch64_size_one_stub (struct bfd_hash_entry *gen_entry,
     case aarch64_stub_long_branch:
       size = sizeof (aarch64_long_branch_stub);
       break;
-    default:
-      BFD_FAIL ();
-      return FALSE;
+    case aarch64_stub_erratum_835769_veneer:
+      size = sizeof (aarch64_erratum_835769_stub);
+      break;
+    case aarch64_stub_erratum_843419_veneer:
+      size = sizeof (aarch64_erratum_843419_stub);
       break;
+    default:
+      abort ();
     }
 
   size = (size + 7) & ~7;
@@ -2487,7 +2628,7 @@ elfNN_aarch64_setup_section_lists (bfd *output_bfd,
 
   /* Count the number of input BFDs and find the top input section id.  */
   for (input_bfd = info->input_bfds, bfd_count = 0, top_id = 0;
-       input_bfd != NULL; input_bfd = input_bfd->link_next)
+       input_bfd != NULL; input_bfd = input_bfd->link.next)
     {
       bfd_count += 1;
       for (section = input_bfd->sections;
@@ -2638,7 +2779,647 @@ group_sections (struct elf_aarch64_link_hash_table *htab,
   free (htab->input_list);
 }
 
-#undef PREV_SEC
+#undef PREV_SEC
+
+#define AARCH64_BITS(x, pos, n) (((x) >> (pos)) & ((1 << (n)) - 1))
+
+#define AARCH64_RT(insn) AARCH64_BITS (insn, 0, 5)
+#define AARCH64_RT2(insn) AARCH64_BITS (insn, 10, 5)
+#define AARCH64_RA(insn) AARCH64_BITS (insn, 10, 5)
+#define AARCH64_RD(insn) AARCH64_BITS (insn, 0, 5)
+#define AARCH64_RN(insn) AARCH64_BITS (insn, 5, 5)
+#define AARCH64_RM(insn) AARCH64_BITS (insn, 16, 5)
+
+#define AARCH64_MAC(insn) (((insn) & 0xff000000) == 0x9b000000)
+#define AARCH64_BIT(insn, n) AARCH64_BITS (insn, n, 1)
+#define AARCH64_OP31(insn) AARCH64_BITS (insn, 21, 3)
+#define AARCH64_ZR 0x1f
+
+/* All ld/st ops.  See C4-182 of the ARM ARM.  The encoding space for
+   LD_PCREL, LDST_RO, LDST_UI and LDST_UIMM cover prefetch ops.  */
+
+#define AARCH64_LD(insn) (AARCH64_BIT (insn, 22) == 1)
+#define AARCH64_LDST(insn) (((insn) & 0x0a000000) == 0x08000000)
+#define AARCH64_LDST_EX(insn) (((insn) & 0x3f000000) == 0x08000000)
+#define AARCH64_LDST_PCREL(insn) (((insn) & 0x3b000000) == 0x18000000)
+#define AARCH64_LDST_NAP(insn) (((insn) & 0x3b800000) == 0x28000000)
+#define AARCH64_LDSTP_PI(insn) (((insn) & 0x3b800000) == 0x28800000)
+#define AARCH64_LDSTP_O(insn) (((insn) & 0x3b800000) == 0x29000000)
+#define AARCH64_LDSTP_PRE(insn) (((insn) & 0x3b800000) == 0x29800000)
+#define AARCH64_LDST_UI(insn) (((insn) & 0x3b200c00) == 0x38000000)
+#define AARCH64_LDST_PIIMM(insn) (((insn) & 0x3b200c00) == 0x38000400)
+#define AARCH64_LDST_U(insn) (((insn) & 0x3b200c00) == 0x38000800)
+#define AARCH64_LDST_PREIMM(insn) (((insn) & 0x3b200c00) == 0x38000c00)
+#define AARCH64_LDST_RO(insn) (((insn) & 0x3b200c00) == 0x38200800)
+#define AARCH64_LDST_UIMM(insn) (((insn) & 0x3b000000) == 0x39000000)
+#define AARCH64_LDST_SIMD_M(insn) (((insn) & 0xbfbf0000) == 0x0c000000)
+#define AARCH64_LDST_SIMD_M_PI(insn) (((insn) & 0xbfa00000) == 0x0c800000)
+#define AARCH64_LDST_SIMD_S(insn) (((insn) & 0xbf9f0000) == 0x0d000000)
+#define AARCH64_LDST_SIMD_S_PI(insn) (((insn) & 0xbf800000) == 0x0d800000)
+
+/* Classify an INSN if it is indeed a load/store.
+
+   Return TRUE if INSN is a LD/ST instruction otherwise return FALSE.
+
+   For scalar LD/ST instructions PAIR is FALSE, RT is returned and RT2
+   is set equal to RT.
+
+   For LD/ST pair instructions PAIR is TRUE, RT and RT2 are returned.
+
+ */
+
+static bfd_boolean
+aarch64_mem_op_p (uint32_t insn, unsigned int *rt, unsigned int *rt2,
+                 bfd_boolean *pair, bfd_boolean *load)
+{
+  uint32_t opcode;
+  unsigned int r;
+  uint32_t opc = 0;
+  uint32_t v = 0;
+  uint32_t opc_v = 0;
+
+  /* Bail out quickly if INSN doesn't fall into the the load-store
+     encoding space.  */
+  if (!AARCH64_LDST (insn))
+    return FALSE;
+
+  *pair = FALSE;
+  *load = FALSE;
+  if (AARCH64_LDST_EX (insn))
+    {
+      *rt = AARCH64_RT (insn);
+      *rt2 = *rt;
+      if (AARCH64_BIT (insn, 21) == 1)
+        {
+         *pair = TRUE;
+         *rt2 = AARCH64_RT2 (insn);
+       }
+      *load = AARCH64_LD (insn);
+      return TRUE;
+    }
+  else if (AARCH64_LDST_NAP (insn)
+          || AARCH64_LDSTP_PI (insn)
+          || AARCH64_LDSTP_O (insn)
+          || AARCH64_LDSTP_PRE (insn))
+    {
+      *pair = TRUE;
+      *rt = AARCH64_RT (insn);
+      *rt2 = AARCH64_RT2 (insn);
+      *load = AARCH64_LD (insn);
+      return TRUE;
+    }
+  else if (AARCH64_LDST_PCREL (insn)
+          || AARCH64_LDST_UI (insn)
+          || AARCH64_LDST_PIIMM (insn)
+          || AARCH64_LDST_U (insn)
+          || AARCH64_LDST_PREIMM (insn)
+          || AARCH64_LDST_RO (insn)
+          || AARCH64_LDST_UIMM (insn))
+   {
+      *rt = AARCH64_RT (insn);
+      *rt2 = *rt;
+      if (AARCH64_LDST_PCREL (insn))
+       *load = TRUE;
+      opc = AARCH64_BITS (insn, 22, 2);
+      v = AARCH64_BIT (insn, 26);
+      opc_v = opc | (v << 2);
+      *load =  (opc_v == 1 || opc_v == 2 || opc_v == 3
+               || opc_v == 5 || opc_v == 7);
+      return TRUE;
+   }
+  else if (AARCH64_LDST_SIMD_M (insn)
+          || AARCH64_LDST_SIMD_M_PI (insn))
+    {
+      *rt = AARCH64_RT (insn);
+      *load = AARCH64_BIT (insn, 22);
+      opcode = (insn >> 12) & 0xf;
+      switch (opcode)
+       {
+       case 0:
+       case 2:
+         *rt2 = *rt + 3;
+         break;
+
+       case 4:
+       case 6:
+         *rt2 = *rt + 2;
+         break;
+
+       case 7:
+         *rt2 = *rt;
+         break;
+
+       case 8:
+       case 10:
+         *rt2 = *rt + 1;
+         break;
+
+       default:
+         return FALSE;
+       }
+      return TRUE;
+    }
+  else if (AARCH64_LDST_SIMD_S (insn)
+          || AARCH64_LDST_SIMD_S_PI (insn))
+    {
+      *rt = AARCH64_RT (insn);
+      r = (insn >> 21) & 1;
+      *load = AARCH64_BIT (insn, 22);
+      opcode = (insn >> 13) & 0x7;
+      switch (opcode)
+       {
+       case 0:
+       case 2:
+       case 4:
+         *rt2 = *rt + r;
+         break;
+
+       case 1:
+       case 3:
+       case 5:
+         *rt2 = *rt + (r == 0 ? 2 : 3);
+         break;
+
+       case 6:
+         *rt2 = *rt + r;
+         break;
+
+       case 7:
+         *rt2 = *rt + (r == 0 ? 2 : 3);
+         break;
+
+       default:
+         return FALSE;
+       }
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* Return TRUE if INSN is multiply-accumulate.  */
+
+static bfd_boolean
+aarch64_mlxl_p (uint32_t insn)
+{
+  uint32_t op31 = AARCH64_OP31 (insn);
+
+  if (AARCH64_MAC (insn)
+      && (op31 == 0 || op31 == 1 || op31 == 5)
+      /* Exclude MUL instructions which are encoded as a multiple accumulate
+        with RA = XZR.  */
+      && AARCH64_RA (insn) != AARCH64_ZR)
+    return TRUE;
+
+  return FALSE;
+}
+
+/* Some early revisions of the Cortex-A53 have an erratum (835769) whereby
+   it is possible for a 64-bit multiply-accumulate instruction to generate an
+   incorrect result.  The details are quite complex and hard to
+   determine statically, since branches in the code may exist in some
+   circumstances, but all cases end with a memory (load, store, or
+   prefetch) instruction followed immediately by the multiply-accumulate
+   operation.  We employ a linker patching technique, by moving the potentially
+   affected multiply-accumulate instruction into a patch region and replacing
+   the original instruction with a branch to the patch.  This function checks
+   if INSN_1 is the memory operation followed by a multiply-accumulate
+   operation (INSN_2).  Return TRUE if an erratum sequence is found, FALSE
+   if INSN_1 and INSN_2 are safe.  */
+
+static bfd_boolean
+aarch64_erratum_sequence (uint32_t insn_1, uint32_t insn_2)
+{
+  uint32_t rt;
+  uint32_t rt2;
+  uint32_t rn;
+  uint32_t rm;
+  uint32_t ra;
+  bfd_boolean pair;
+  bfd_boolean load;
+
+  if (aarch64_mlxl_p (insn_2)
+      && aarch64_mem_op_p (insn_1, &rt, &rt2, &pair, &load))
+    {
+      /* Any SIMD memory op is independent of the subsequent MLA
+        by definition of the erratum.  */
+      if (AARCH64_BIT (insn_1, 26))
+       return TRUE;
+
+      /* If not SIMD, check for integer memory ops and MLA relationship.  */
+      rn = AARCH64_RN (insn_2);
+      ra = AARCH64_RA (insn_2);
+      rm = AARCH64_RM (insn_2);
+
+      /* If this is a load and there's a true(RAW) dependency, we are safe
+        and this is not an erratum sequence.  */
+      if (load &&
+         (rt == rn || rt == rm || rt == ra
+          || (pair && (rt2 == rn || rt2 == rm || rt2 == ra))))
+       return FALSE;
+
+      /* We conservatively put out stubs for all other cases (including
+        writebacks).  */
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+/* Used to order a list of mapping symbols by address.  */
+
+static int
+elf_aarch64_compare_mapping (const void *a, const void *b)
+{
+  const elf_aarch64_section_map *amap = (const elf_aarch64_section_map *) a;
+  const elf_aarch64_section_map *bmap = (const elf_aarch64_section_map *) b;
+
+  if (amap->vma > bmap->vma)
+    return 1;
+  else if (amap->vma < bmap->vma)
+    return -1;
+  else if (amap->type > bmap->type)
+    /* Ensure results do not depend on the host qsort for objects with
+       multiple mapping symbols at the same address by sorting on type
+       after vma.  */
+    return 1;
+  else if (amap->type < bmap->type)
+    return -1;
+  else
+    return 0;
+}
+
+
+static char *
+_bfd_aarch64_erratum_835769_stub_name (unsigned num_fixes)
+{
+  char *stub_name = (char *) bfd_malloc
+    (strlen ("__erratum_835769_veneer_") + 16);
+  sprintf (stub_name,"__erratum_835769_veneer_%d", num_fixes);
+  return stub_name;
+}
+
+/* Scan for Cortex-A53 erratum 835769 sequence.
+
+   Return TRUE else FALSE on abnormal termination.  */
+
+static bfd_boolean
+_bfd_aarch64_erratum_835769_scan (bfd *input_bfd,
+                                 struct bfd_link_info *info,
+                                 unsigned int *num_fixes_p)
+{
+  asection *section;
+  struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
+  unsigned int num_fixes = *num_fixes_p;
+
+  if (htab == NULL)
+    return TRUE;
+
+  for (section = input_bfd->sections;
+       section != NULL;
+       section = section->next)
+    {
+      bfd_byte *contents = NULL;
+      struct _aarch64_elf_section_data *sec_data;
+      unsigned int span;
+
+      if (elf_section_type (section) != SHT_PROGBITS
+         || (elf_section_flags (section) & SHF_EXECINSTR) == 0
+         || (section->flags & SEC_EXCLUDE) != 0
+         || (section->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+         || (section->output_section == bfd_abs_section_ptr))
+       continue;
+
+      if (elf_section_data (section)->this_hdr.contents != NULL)
+       contents = elf_section_data (section)->this_hdr.contents;
+      else if (! bfd_malloc_and_get_section (input_bfd, section, &contents))
+       return FALSE;
+
+      sec_data = elf_aarch64_section_data (section);
+
+      qsort (sec_data->map, sec_data->mapcount,
+            sizeof (elf_aarch64_section_map), elf_aarch64_compare_mapping);
+
+      for (span = 0; span < sec_data->mapcount; span++)
+       {
+         unsigned int span_start = sec_data->map[span].vma;
+         unsigned int span_end = ((span == sec_data->mapcount - 1)
+                                  ? sec_data->map[0].vma + section->size
+                                  : sec_data->map[span + 1].vma);
+         unsigned int i;
+         char span_type = sec_data->map[span].type;
+
+         if (span_type == 'd')
+           continue;
+
+         for (i = span_start; i + 4 < span_end; i += 4)
+           {
+             uint32_t insn_1 = bfd_getl32 (contents + i);
+             uint32_t insn_2 = bfd_getl32 (contents + i + 4);
+
+             if (aarch64_erratum_sequence (insn_1, insn_2))
+               {
+                 struct elf_aarch64_stub_hash_entry *stub_entry;
+                 char *stub_name = _bfd_aarch64_erratum_835769_stub_name (num_fixes);
+                 if (! stub_name)
+                   return FALSE;
+
+                 stub_entry = _bfd_aarch64_add_stub_entry_in_group (stub_name,
+                                                                    section,
+                                                                    htab);
+                 if (! stub_entry)
+                   return FALSE;
+
+                 stub_entry->stub_type = aarch64_stub_erratum_835769_veneer;
+                 stub_entry->target_section = section;
+                 stub_entry->target_value = i + 4;
+                 stub_entry->veneered_insn = insn_2;
+                 stub_entry->output_name = stub_name;
+                 num_fixes++;
+               }
+           }
+       }
+      if (elf_section_data (section)->this_hdr.contents == NULL)
+       free (contents);
+    }
+
+  *num_fixes_p = num_fixes;
+
+  return TRUE;
+}
+
+
+/* Test if instruction INSN is ADRP.  */
+
+static bfd_boolean
+_bfd_aarch64_adrp_p (uint32_t insn)
+{
+  return ((insn & 0x9f000000) == 0x90000000);
+}
+
+
+/* Helper predicate to look for cortex-a53 erratum 843419 sequence 1.  */
+
+static bfd_boolean
+_bfd_aarch64_erratum_843419_sequence_p (uint32_t insn_1, uint32_t insn_2,
+                                       uint32_t insn_3)
+{
+  uint32_t rt;
+  uint32_t rt2;
+  bfd_boolean pair;
+  bfd_boolean load;
+
+  return (aarch64_mem_op_p (insn_2, &rt, &rt2, &pair, &load)
+         && (!pair
+             || (pair && !load))
+         && AARCH64_LDST_UIMM (insn_3)
+         && AARCH64_RN (insn_3) == AARCH64_RD (insn_1));
+}
+
+
+/* Test for the presence of Cortex-A53 erratum 843419 instruction sequence.
+
+   Return TRUE if section CONTENTS at offset I contains one of the
+   erratum 843419 sequences, otherwise return FALSE.  If a sequence is
+   seen set P_VENEER_I to the offset of the final LOAD/STORE
+   instruction in the sequence.
+ */
+
+static bfd_boolean
+_bfd_aarch64_erratum_843419_p (bfd_byte *contents, bfd_vma vma,
+                              bfd_vma i, bfd_vma span_end,
+                              bfd_vma *p_veneer_i)
+{
+  uint32_t insn_1 = bfd_getl32 (contents + i);
+
+  if (!_bfd_aarch64_adrp_p (insn_1))
+    return FALSE;
+
+  if (span_end < i + 12)
+    return FALSE;
+
+  uint32_t insn_2 = bfd_getl32 (contents + i + 4);
+  uint32_t insn_3 = bfd_getl32 (contents + i + 8);
+
+  if ((vma & 0xfff) != 0xff8 && (vma & 0xfff) != 0xffc)
+    return FALSE;
+
+  if (_bfd_aarch64_erratum_843419_sequence_p (insn_1, insn_2, insn_3))
+    {
+      *p_veneer_i = i + 8;
+      return TRUE;
+    }
+
+  if (span_end < i + 16)
+    return FALSE;
+
+  uint32_t insn_4 = bfd_getl32 (contents + i + 12);
+
+  if (_bfd_aarch64_erratum_843419_sequence_p (insn_1, insn_2, insn_4))
+    {
+      *p_veneer_i = i + 12;
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+
+/* Resize all stub sections.  */
+
+static void
+_bfd_aarch64_resize_stubs (struct elf_aarch64_link_hash_table *htab)
+{
+  asection *section;
+
+  /* OK, we've added some stubs.  Find out the new size of the
+     stub sections.  */
+  for (section = htab->stub_bfd->sections;
+       section != NULL; section = section->next)
+    {
+      /* Ignore non-stub sections.  */
+      if (!strstr (section->name, STUB_SUFFIX))
+       continue;
+      section->size = 0;
+    }
+
+  bfd_hash_traverse (&htab->stub_hash_table, aarch64_size_one_stub, htab);
+
+  for (section = htab->stub_bfd->sections;
+       section != NULL; section = section->next)
+    {
+      if (!strstr (section->name, STUB_SUFFIX))
+       continue;
+
+      if (section->size)
+       section->size += 4;
+
+      /* 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)
+       if (section->size)
+         section->size = BFD_ALIGN (section->size, 0x1000);
+    }
+}
+
+
+/* Construct an erratum 843419 workaround stub name.
+ */
+
+static char *
+_bfd_aarch64_erratum_843419_stub_name (asection *input_section,
+                                      bfd_vma offset)
+{
+  const bfd_size_type len = 8 + 4 + 1 + 8 + 1 + 16 + 1;
+  char *stub_name = bfd_malloc (len);
+
+  if (stub_name != NULL)
+    snprintf (stub_name, len, "e843419@%04x_%08x_%" BFD_VMA_FMT "x",
+             input_section->owner->id,
+             input_section->id,
+             offset);
+  return stub_name;
+}
+
+/*  Build a stub_entry structure describing an 843419 fixup.
+
+    The stub_entry constructed is populated with the bit pattern INSN
+    of the instruction located at OFFSET within input SECTION.
+
+    Returns TRUE on success.  */
+
+static bfd_boolean
+_bfd_aarch64_erratum_843419_fixup (uint32_t insn,
+                                  bfd_vma adrp_offset,
+                                  bfd_vma ldst_offset,
+                                  asection *section,
+                                  struct bfd_link_info *info)
+{
+  struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
+  char *stub_name;
+  struct elf_aarch64_stub_hash_entry *stub_entry;
+
+  stub_name = _bfd_aarch64_erratum_843419_stub_name (section, ldst_offset);
+  stub_entry = aarch64_stub_hash_lookup (&htab->stub_hash_table, stub_name,
+                                        FALSE, FALSE);
+  if (stub_entry)
+    {
+      free (stub_name);
+      return TRUE;
+    }
+
+  /* We always place an 843419 workaround veneer in the stub section
+     attached to the input section in which an erratum sequence has
+     been found.  This ensures that later in the link process (in
+     elfNN_aarch64_write_section) when we copy the veneered
+     instruction from the input section into the stub section the
+     copied instruction will have had any relocations applied to it.
+     If we placed workaround veneers in any other stub section then we
+     could not assume that all relocations have been processed on the
+     corresponding input section at the point we output the stub
+     section.
+   */
+
+  stub_entry = _bfd_aarch64_add_stub_entry_after (stub_name, section, htab);
+  if (stub_entry == NULL)
+    {
+      free (stub_name);
+      return FALSE;
+    }
+
+  stub_entry->adrp_offset = adrp_offset;
+  stub_entry->target_value = ldst_offset;
+  stub_entry->target_section = section;
+  stub_entry->stub_type = aarch64_stub_erratum_843419_veneer;
+  stub_entry->veneered_insn = insn;
+  stub_entry->output_name = stub_name;
+
+  return TRUE;
+}
+
+
+/* Scan an input section looking for the signature of erratum 843419.
+
+   Scans input SECTION in INPUT_BFD looking for erratum 843419
+   signatures, for each signature found a stub_entry is created
+   describing the location of the erratum for subsequent fixup.
+
+   Return TRUE on successful scan, FALSE on failure to scan.
+ */
+
+static bfd_boolean
+_bfd_aarch64_erratum_843419_scan (bfd *input_bfd, asection *section,
+                                 struct bfd_link_info *info)
+{
+  struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
+
+  if (htab == NULL)
+    return TRUE;
+
+  if (elf_section_type (section) != SHT_PROGBITS
+      || (elf_section_flags (section) & SHF_EXECINSTR) == 0
+      || (section->flags & SEC_EXCLUDE) != 0
+      || (section->sec_info_type == SEC_INFO_TYPE_JUST_SYMS)
+      || (section->output_section == bfd_abs_section_ptr))
+    return TRUE;
+
+  do
+    {
+      bfd_byte *contents = NULL;
+      struct _aarch64_elf_section_data *sec_data;
+      unsigned int span;
+
+      if (elf_section_data (section)->this_hdr.contents != NULL)
+       contents = elf_section_data (section)->this_hdr.contents;
+      else if (! bfd_malloc_and_get_section (input_bfd, section, &contents))
+       return FALSE;
+
+      sec_data = elf_aarch64_section_data (section);
+
+      qsort (sec_data->map, sec_data->mapcount,
+            sizeof (elf_aarch64_section_map), elf_aarch64_compare_mapping);
+
+      for (span = 0; span < sec_data->mapcount; span++)
+       {
+         unsigned int span_start = sec_data->map[span].vma;
+         unsigned int span_end = ((span == sec_data->mapcount - 1)
+                                  ? sec_data->map[0].vma + section->size
+                                  : sec_data->map[span + 1].vma);
+         unsigned int i;
+         char span_type = sec_data->map[span].type;
+
+         if (span_type == 'd')
+           continue;
+
+         for (i = span_start; i + 8 < span_end; i += 4)
+           {
+             bfd_vma vma = (section->output_section->vma
+                            + section->output_offset
+                            + i);
+             bfd_vma veneer_i;
+
+             if (_bfd_aarch64_erratum_843419_p
+                 (contents, vma, i, span_end, &veneer_i))
+               {
+                 uint32_t insn = bfd_getl32 (contents + veneer_i);
+
+                 if (!_bfd_aarch64_erratum_843419_fixup (insn, i, veneer_i,
+                                                         section, info))
+                   return FALSE;
+               }
+           }
+       }
+
+      if (elf_section_data (section)->this_hdr.contents == NULL)
+       free (contents);
+    }
+  while (0);
+
+  return TRUE;
+}
+
 
 /* Determine and set the size of the stub section for a final link.
 
@@ -2657,8 +3438,9 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
 {
   bfd_size_type stub_group_size;
   bfd_boolean stubs_always_before_branch;
-  bfd_boolean stub_changed = 0;
+  bfd_boolean stub_changed = FALSE;
   struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
+  unsigned int num_erratum_835769_fixes = 0;
 
   /* Propagate mach to stub bfd, because it may not have been
      finalized when we created stub_bfd.  */
@@ -2684,14 +3466,49 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
 
   group_sections (htab, stub_group_size, stubs_always_before_branch);
 
+  (*htab->layout_sections_again) ();
+
+  if (htab->fix_erratum_835769)
+    {
+      bfd *input_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;
+
+      _bfd_aarch64_resize_stubs (htab);
+      (*htab->layout_sections_again) ();
+    }
+
+  if (htab->fix_erratum_843419)
+    {
+      bfd *input_bfd;
+
+      for (input_bfd = info->input_bfds;
+          input_bfd != NULL;
+          input_bfd = input_bfd->link.next)
+       {
+         asection *section;
+
+         for (section = input_bfd->sections;
+              section != NULL;
+              section = section->next)
+           if (!_bfd_aarch64_erratum_843419_scan (input_bfd, section, info))
+             return FALSE;
+       }
+
+      _bfd_aarch64_resize_stubs (htab);
+      (*htab->layout_sections_again) ();
+    }
+
   while (1)
     {
       bfd *input_bfd;
-      unsigned int bfd_indx;
-      asection *stub_sec;
 
-      for (input_bfd = info->input_bfds, bfd_indx = 0;
-          input_bfd != NULL; input_bfd = input_bfd->link_next, bfd_indx++)
+      for (input_bfd = info->input_bfds;
+          input_bfd != NULL; input_bfd = input_bfd->link.next)
        {
          Elf_Internal_Shdr *symtab_hdr;
          asection *section;
@@ -2908,8 +3725,8 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
                      continue;
                    }
 
-                 stub_entry = elfNN_aarch64_add_stub (stub_name, section,
-                                                      htab);
+                 stub_entry = _bfd_aarch64_add_stub_entry_in_group
+                   (stub_name, section, htab);
                  if (stub_entry == NULL)
                    {
                      free (stub_name);
@@ -2947,13 +3764,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
       if (!stub_changed)
        break;
 
-      /* OK, we've added some stubs.  Find out the new size of the
-         stub sections.  */
-      for (stub_sec = htab->stub_bfd->sections;
-          stub_sec != NULL; stub_sec = stub_sec->next)
-       stub_sec->size = 0;
-
-      bfd_hash_traverse (&htab->stub_hash_table, aarch64_size_one_stub, htab);
+      _bfd_aarch64_resize_stubs (htab);
 
       /* Ask the linker to do its stuff.  */
       (*htab->layout_sections_again) ();
@@ -2996,6 +3807,9 @@ elfNN_aarch64_build_stubs (struct bfd_link_info *info)
       if (stub_sec->contents == NULL && size != 0)
        return FALSE;
       stub_sec->size = 0;
+
+      bfd_putl32 (0x14000000 | (size >> 2), stub_sec->contents);
+      stub_sec->size += 4;
     }
 
   /* Build the stubs as directed by the stub hash table.  */
@@ -3052,7 +3866,7 @@ bfd_elfNN_aarch64_init_maps (bfd *abfd)
     return;
 
   if ((abfd->flags & DYNAMIC) != 0)
-    return;
+   return;
 
   hdr = &elf_symtab_hdr (abfd);
   localsyms = hdr->sh_info;
@@ -3090,12 +3904,17 @@ void
 bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
                               struct bfd_link_info *link_info,
                               int no_enum_warn,
-                              int no_wchar_warn, int pic_veneer)
+                              int no_wchar_warn, int pic_veneer,
+                              int fix_erratum_835769,
+                              int fix_erratum_843419)
 {
   struct elf_aarch64_link_hash_table *globals;
 
   globals = elf_aarch64_hash_table (link_info);
   globals->pic_veneer = pic_veneer;
+  globals->fix_erratum_835769 = fix_erratum_835769;
+  globals->fix_erratum_843419 = fix_erratum_843419;
+  globals->fix_erratum_843419_adr = TRUE;
 
   BFD_ASSERT (is_aarch64_elf (output_bfd));
   elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
@@ -3167,6 +3986,16 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
              ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1
              : BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21);
 
+    case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
+      return (is_local
+             ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC
+             : r_type);
+
+    case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
+      return (is_local
+             ? 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:
       return (is_local
@@ -3179,6 +4008,14 @@ aarch64_tls_transition_without_check (bfd_reloc_code_real_type r_type,
     case BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC:
       return is_local ? BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC : r_type;
 
+    case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
+      return r_type;
+
+    case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
+      return (is_local
+             ? BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12
+             : BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19);
+
     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSDESC_CALL:
       /* Instructions with these relocations will become NOPs.  */
@@ -3203,19 +4040,23 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type)
       return GOT_NORMAL;
 
     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_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_LD_GOTTPREL_PREL19:
       return GOT_TLS_IE;
 
     case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
@@ -3301,8 +4142,7 @@ tpoff_base (struct bfd_link_info *info)
   struct elf_link_hash_table *htab = elf_hash_table (info);
 
   /* If tls_sec is NULL, we should have signalled an error already.  */
-  if (htab->tls_sec == NULL)
-    return 0;
+  BFD_ASSERT (htab->tls_sec != NULL);
 
   bfd_vma base = align_power ((bfd_vma) TCB_SIZE,
                              htab->tls_sec->alignment_power);
@@ -3406,6 +4246,183 @@ symbol_tlsdesc_got_offset (bfd *input_bfd, struct elf_link_hash_entry *h,
   return value;
 }
 
+/* Data for make_branch_to_erratum_835769_stub().  */
+
+struct erratum_835769_branch_to_stub_data
+{
+  struct bfd_link_info *info;
+  asection *output_section;
+  bfd_byte *contents;
+};
+
+/* Helper to insert branches to erratum 835769 stubs in the right
+   places for a particular section.  */
+
+static bfd_boolean
+make_branch_to_erratum_835769_stub (struct bfd_hash_entry *gen_entry,
+                                   void *in_arg)
+{
+  struct elf_aarch64_stub_hash_entry *stub_entry;
+  struct erratum_835769_branch_to_stub_data *data;
+  bfd_byte *contents;
+  unsigned long branch_insn = 0;
+  bfd_vma veneered_insn_loc, veneer_entry_loc;
+  bfd_signed_vma branch_offset;
+  unsigned int target;
+  bfd *abfd;
+
+  stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry;
+  data = (struct erratum_835769_branch_to_stub_data *) in_arg;
+
+  if (stub_entry->target_section != data->output_section
+      || stub_entry->stub_type != aarch64_stub_erratum_835769_veneer)
+    return TRUE;
+
+  contents = data->contents;
+  veneered_insn_loc = stub_entry->target_section->output_section->vma
+                     + stub_entry->target_section->output_offset
+                     + stub_entry->target_value;
+  veneer_entry_loc = stub_entry->stub_sec->output_section->vma
+                    + stub_entry->stub_sec->output_offset
+                    + stub_entry->stub_offset;
+  branch_offset = veneer_entry_loc - veneered_insn_loc;
+
+  abfd = stub_entry->target_section->owner;
+  if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc))
+           (*_bfd_error_handler)
+               (_("%B: error: Erratum 835769 stub out "
+                  "of range (input file too large)"), abfd);
+
+  target = stub_entry->target_value;
+  branch_insn = 0x14000000;
+  branch_offset >>= 2;
+  branch_offset &= 0x3ffffff;
+  branch_insn |= branch_offset;
+  bfd_putl32 (branch_insn, &contents[target]);
+
+  return TRUE;
+}
+
+
+static bfd_boolean
+_bfd_aarch64_erratum_843419_branch_to_stub (struct bfd_hash_entry *gen_entry,
+                                           void *in_arg)
+{
+  struct elf_aarch64_stub_hash_entry *stub_entry
+    = (struct elf_aarch64_stub_hash_entry *) gen_entry;
+  struct erratum_835769_branch_to_stub_data *data
+    = (struct erratum_835769_branch_to_stub_data *) in_arg;
+  struct bfd_link_info *info;
+  struct elf_aarch64_link_hash_table *htab;
+  bfd_byte *contents;
+  asection *section;
+  bfd *abfd;
+  bfd_vma place;
+  uint32_t insn;
+
+  info = data->info;
+  contents = data->contents;
+  section = data->output_section;
+
+  htab = elf_aarch64_hash_table (info);
+
+  if (stub_entry->target_section != section
+      || 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);
+
+  place = (section->output_section->vma + section->output_offset
+          + stub_entry->adrp_offset);
+  insn = bfd_getl32 (contents + stub_entry->adrp_offset);
+
+  if ((insn & AARCH64_ADRP_OP_MASK) !=  AARCH64_ADRP_OP)
+    abort ();
+
+  bfd_signed_vma imm =
+    (_bfd_aarch64_sign_extend
+     ((bfd_vma) _bfd_aarch64_decode_adrp_imm (insn) << 12, 33)
+     - (place & 0xfff));
+
+  if (htab->fix_erratum_843419_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);
+    }
+  else
+    {
+      bfd_vma veneered_insn_loc;
+      bfd_vma veneer_entry_loc;
+      bfd_signed_vma branch_offset;
+      uint32_t branch_insn;
+
+      veneered_insn_loc = stub_entry->target_section->output_section->vma
+       + stub_entry->target_section->output_offset
+       + stub_entry->target_value;
+      veneer_entry_loc = stub_entry->stub_sec->output_section->vma
+       + stub_entry->stub_sec->output_offset
+       + stub_entry->stub_offset;
+      branch_offset = veneer_entry_loc - veneered_insn_loc;
+
+      abfd = stub_entry->target_section->owner;
+      if (!aarch64_valid_branch_p (veneer_entry_loc, veneered_insn_loc))
+       (*_bfd_error_handler)
+         (_("%B: error: Erratum 843419 stub out "
+            "of range (input file too large)"), abfd);
+
+      branch_insn = 0x14000000;
+      branch_offset >>= 2;
+      branch_offset &= 0x3ffffff;
+      branch_insn |= branch_offset;
+      bfd_putl32 (branch_insn, contents + stub_entry->target_value);
+    }
+  return TRUE;
+}
+
+
+static bfd_boolean
+elfNN_aarch64_write_section (bfd *output_bfd  ATTRIBUTE_UNUSED,
+                            struct bfd_link_info *link_info,
+                            asection *sec,
+                            bfd_byte *contents)
+
+{
+  struct elf_aarch64_link_hash_table *globals =
+    elf_aarch64_hash_table (link_info);
+
+  if (globals == NULL)
+    return FALSE;
+
+  /* Fix code to point to erratum 835769 stubs.  */
+  if (globals->fix_erratum_835769)
+    {
+      struct erratum_835769_branch_to_stub_data data;
+
+      data.info = link_info;
+      data.output_section = sec;
+      data.contents = contents;
+      bfd_hash_traverse (&globals->stub_hash_table,
+                        make_branch_to_erratum_835769_stub, &data);
+    }
+
+  if (globals->fix_erratum_843419)
+    {
+      struct erratum_835769_branch_to_stub_data data;
+
+      data.info = link_info;
+      data.output_section = sec;
+      data.contents = contents;
+      bfd_hash_traverse (&globals->stub_hash_table,
+                        _bfd_aarch64_erratum_843419_branch_to_stub, &data);
+    }
+
+  return FALSE;
+}
+
 /* Perform a relocation as part of a final link.  */
 static bfd_reloc_status_type
 elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
@@ -3430,10 +4447,11 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
   bfd_reloc_code_real_type new_bfd_r_type;
   unsigned long r_symndx;
   bfd_byte *hit_data = contents + rel->r_offset;
-  bfd_vma place;
+  bfd_vma place, off;
   bfd_signed_vma signed_addend;
   struct elf_aarch64_link_hash_table *globals;
   bfd_boolean weak_undef_p;
+  asection *base_got;
 
   globals = elf_aarch64_hash_table (info);
 
@@ -3473,8 +4491,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     {
       asection *plt;
       const char *name;
-      asection *base_got;
-      bfd_vma off;
 
       if ((input_section->flags & SEC_ALLOC) == 0
          || h->plt.offset == (bfd_vma) -1)
@@ -3687,7 +4703,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
            memset (&outrel, 0, sizeof outrel);
          else if (h != NULL
                   && h->dynindx != -1
-                  && (!info->shared || !info->symbolic || !h->def_regular))
+                  && (!info->shared || !SYMBOLIC_BIND (info, h) || !h->def_regular))
            outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
          else
            {
@@ -3784,16 +4800,36 @@ 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:
+      if (info->shared
+         && (input_section->flags & SEC_ALLOC) != 0
+         && (input_section->flags & SEC_READONLY) != 0
+         && h != NULL
+         && !h->def_regular)
+       {
+         int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+
+         (*_bfd_error_handler)
+           (_("%B: relocation %s against external symbol `%s' can not be used"
+              " when making a shared object; recompile with -fPIC"),
+            input_bfd, elfNN_aarch64_howto_table[howto_index].name,
+            h->root.root.string);
+         bfd_set_error (bfd_error_bad_value);
+         return FALSE;
+       }
+
     case BFD_RELOC_AARCH64_16:
 #if ARCH_SIZE == 64
     case BFD_RELOC_AARCH64_32:
 #endif
     case BFD_RELOC_AARCH64_ADD_LO12:
-    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_BRANCH19:
-    case BFD_RELOC_AARCH64_LD_LO19_PCREL:
     case BFD_RELOC_AARCH64_LDST8_LO12:
     case BFD_RELOC_AARCH64_LDST16_LO12:
     case BFD_RELOC_AARCH64_LDST32_LO12:
@@ -3809,9 +4845,6 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     case BFD_RELOC_AARCH64_MOVW_G2:
     case BFD_RELOC_AARCH64_MOVW_G2_NC:
     case BFD_RELOC_AARCH64_MOVW_G3:
-    case BFD_RELOC_AARCH64_16_PCREL:
-    case BFD_RELOC_AARCH64_32_PCREL:
-    case BFD_RELOC_AARCH64_64_PCREL:
     case BFD_RELOC_AARCH64_TSTBR14:
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
                                                   signed_addend, weak_undef_p);
@@ -3832,19 +4865,73 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
          value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
                                                       0, weak_undef_p);
        }
+      else
+      {
+       struct elf_aarch64_local_symbol *locals
+         = elf_aarch64_locals (input_bfd);
+
+       if (locals == NULL)
+         {
+           int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+           (*_bfd_error_handler)
+             (_("%B: Local symbol descriptor table be NULL when applying "
+                "relocation %s against local symbol"),
+              input_bfd, elfNN_aarch64_howto_table[howto_index].name);
+           abort ();
+         }
+
+       off = symbol_got_offset (input_bfd, h, r_symndx);
+       base_got = globals->root.sgot;
+       bfd_vma got_entry_addr = (base_got->output_section->vma
+                                 + base_got->output_offset + off);
+
+       if (!symbol_got_offset_mark_p (input_bfd, h, r_symndx))
+         {
+           bfd_put_64 (output_bfd, value, base_got->contents + off);
+
+           if (info->shared)
+             {
+               asection *s;
+               Elf_Internal_Rela outrel;
+
+               /* For local symbol, we have done absolute relocation in static
+                  linking stageh. While for share library, we need to update
+                  the content of GOT entry according to the share objects
+                  loading base address. So we need to generate a
+                  R_AARCH64_RELATIVE reloc for dynamic linker.  */
+               s = globals->root.srelgot;
+               if (s == NULL)
+                 abort ();
+
+               outrel.r_offset = got_entry_addr;
+               outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE));
+               outrel.r_addend = value;
+               elf_append_rela (output_bfd, s, &outrel);
+             }
+
+           symbol_got_offset_mark (input_bfd, h, r_symndx);
+         }
+
+       /* 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;
+      }
+
       break;
 
     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_LD_GOTTPREL_PREL19:
       if (globals->root.sgot == NULL)
        return bfd_reloc_notsupported;
 
       value = (symbol_got_offset (input_bfd, h, r_symndx)
               + globals->root.sgot->output_section->vma
-              + globals->root.sgot->output_section->output_offset);
+              + globals->root.sgot->output_offset);
 
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
                                                   0, weak_undef_p);
@@ -3868,15 +4955,16 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
     case BFD_RELOC_AARCH64_TLSDESC_ADD:
     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_LD32_LO12_NC:
     case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
     case BFD_RELOC_AARCH64_TLSDESC_LDR:
+    case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
       if (globals->root.sgot == NULL)
        return bfd_reloc_notsupported;
-
       value = (symbol_tlsdesc_got_offset (input_bfd, h, r_symndx)
               + globals->root.sgotplt->output_section->vma
-              + globals->root.sgotplt->output_section->output_offset
+              + globals->root.sgotplt->output_offset
               + globals->sgotplt_jump_table_size);
 
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
@@ -3939,10 +5027,102 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
             or
             adrp x0, :tlsdesc:var   =>   adrp x0, :gottprel:var
           */
-         insn = bfd_getl32 (contents + rel->r_offset);
          return bfd_reloc_continue;
        }
 
+    case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
+      BFD_ASSERT (0);
+      break;
+
+    case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
+      if (is_local)
+       {
+         /* Tiny TLSDESC->LE relaxation:
+            ldr   x1, :tlsdesc:var      =>  movz  x0, #:tprel_g1:var
+            adr   x0, :tlsdesc:var      =>  movk  x0, #:tprel_g0_nc:var
+            .tlsdesccall var
+            blr   x1                    =>  nop
+          */
+         BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (TLSDESC_ADR_PREL21));
+         BFD_ASSERT (ELFNN_R_TYPE (rel[2].r_info) == AARCH64_R (TLSDESC_CALL));
+
+         rel[1].r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info),
+                                       AARCH64_R (TLSLE_MOVW_TPREL_G0_NC));
+         rel[2].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+
+         bfd_putl32 (0xd2a00000, contents + rel->r_offset);
+         bfd_putl32 (0xf2800000, contents + rel->r_offset + 4);
+         bfd_putl32 (INSN_NOP, contents + rel->r_offset + 8);
+         return bfd_reloc_continue;
+       }
+      else
+       {
+         /* Tiny TLSDESC->IE relaxation:
+            ldr   x1, :tlsdesc:var      =>  ldr   x0, :gottprel:var
+            adr   x0, :tlsdesc:var      =>  nop
+            .tlsdesccall var
+            blr   x1                    =>  nop
+          */
+         BFD_ASSERT (ELFNN_R_TYPE (rel[1].r_info) == AARCH64_R (TLSDESC_ADR_PREL21));
+         BFD_ASSERT (ELFNN_R_TYPE (rel[2].r_info) == AARCH64_R (TLSDESC_CALL));
+
+         rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+         rel[2].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+
+         bfd_putl32 (0x58000000, contents + rel->r_offset);
+         bfd_putl32 (INSN_NOP, contents + rel->r_offset + 4);
+         bfd_putl32 (INSN_NOP, contents + rel->r_offset + 8);
+         return bfd_reloc_continue;
+       }
+
+    case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
+      if (is_local)
+       {
+         /* Tiny GD->LE relaxation:
+            adr x0, :tlsgd:var      =>   mrs  x1, tpidr_el0
+             bl   __tls_get_addr     =>   add  x0, x1, #:tprel_hi12:x, lsl #12
+             nop                     =>   add  x0, x0, #:tprel_lo12_nc:x
+          */
+
+         /* First kill the tls_get_addr reloc on the bl instruction.  */
+         BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+
+         bfd_putl32 (0xd53bd041, contents + rel->r_offset + 0);
+         bfd_putl32 (0x91400020, contents + rel->r_offset + 4);
+         bfd_putl32 (0x91000000, contents + rel->r_offset + 8);
+
+         rel[1].r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info),
+                                       AARCH64_R (TLSLE_ADD_TPREL_LO12_NC));
+         rel[1].r_offset = rel->r_offset + 8;
+
+         /* Move the current relocation to the second instruction in
+            the sequence.  */
+         rel->r_offset += 4;
+         rel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel->r_info),
+                                     AARCH64_R (TLSLE_ADD_TPREL_HI12));
+         return bfd_reloc_continue;
+       }
+      else
+       {
+         /* Tiny GD->IE relaxation:
+            adr x0, :tlsgd:var      =>   ldr  x0, :gottprel:var
+            bl   __tls_get_addr     =>   mrs  x1, tpidr_el0
+            nop                     =>   add  x0, x0, x1
+          */
+
+         /* First kill the tls_get_addr reloc on the bl instruction.  */
+         BFD_ASSERT (rel->r_offset + 4 == rel[1].r_offset);
+         rel[1].r_info = ELFNN_R_INFO (STN_UNDEF, R_AARCH64_NONE);
+
+         bfd_putl32 (0x58000000, contents + rel->r_offset);
+         bfd_putl32 (0xd53bd041, contents + rel->r_offset + 4);
+         bfd_putl32 (0x8b000020, contents + rel->r_offset + 8);
+         return bfd_reloc_continue;
+       }
+
+    case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
+      return bfd_reloc_continue;
+
     case BFD_RELOC_AARCH64_TLSDESC_LDNN_LO12_NC:
       if (is_local)
        {
@@ -3958,7 +5138,7 @@ elfNN_aarch64_tls_relax (struct elf_aarch64_link_hash_table *globals,
             ldr xd, [x0, #:tlsdesc_lo12:var] => ldr x0, [x0, #:gottprel_lo12:var]
           */
          insn = bfd_getl32 (contents + rel->r_offset);
-         insn &= 0xfffffff0;
+         insn &= 0xffffffe0;
          bfd_putl32 (insn, contents + rel->r_offset);
          return bfd_reloc_continue;
        }
@@ -4160,15 +5340,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
                                         rel, 1, relend, howto, 0, contents);
 
       if (info->relocatable)
-       {
-         /* This is a relocatable link.  We don't have to change
-            anything, unless the reloc is against a section symbol,
-            in which case we have to adjust according to where the
-            section symbol winds up in the output section.  */
-         if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-           rel->r_addend += sec->output_offset;
-         continue;
-       }
+       continue;
 
       if (h != NULL)
        name = h->root.root.string;
@@ -4236,6 +5408,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
       switch (elfNN_aarch64_bfd_reloc_from_type (r_type))
        {
        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))
            {
@@ -4314,6 +5487,7 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
 
        case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
        case BFD_RELOC_AARCH64_TLSIE_LDNN_GOTTPREL_LO12_NC:
+       case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
          if (! symbol_got_offset_mark_p (input_bfd, h, r_symndx))
            {
              bfd_boolean need_relocs = FALSE;
@@ -4375,7 +5549,9 @@ elfNN_aarch64_relocate_section (bfd *output_bfd,
 
        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_LDNN_LO12_NC:
+       case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
          if (! symbol_tlsdesc_got_offset_mark_p (input_bfd, h, r_symndx))
            {
              bfd_boolean need_relocs = FALSE;
@@ -4743,13 +5919,17 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
        case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
        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_LD32_LO12_NC:
        case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
+       case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
        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_TLSIE_ADR_GOTTPREL_PAGE21:
        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:
        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:
@@ -4776,16 +5956,6 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
            }
          break;
 
-       case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
-       case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
-       case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
-         if (h != NULL && info->executable)
-           {
-             if (h->plt.refcount > 0)
-               h->plt.refcount -= 1;
-           }
-         break;
-
        case BFD_RELOC_AARCH64_CALL26:
        case BFD_RELOC_AARCH64_JUMP26:
          /* If this is a local symbol then we resolve it
@@ -4797,6 +5967,13 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
            h->plt.refcount -= 1;
          break;
 
+       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)
            {
@@ -4913,7 +6090,7 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   s = htab->sdynbss;
 
-  return _bfd_elf_adjust_dynamic_copy (h, s);
+  return _bfd_elf_adjust_dynamic_copy (info, h, s);
 
 }
 
@@ -5214,13 +6391,17 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
        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_LD32_LO12_NC:
        case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
+       case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
        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_TLSIE_ADR_GOTTPREL_PAGE21:
        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:
        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:
@@ -5293,6 +6474,22 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            break;
          }
 
+       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:
+         if (info->shared)
+           {
+             int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+             (*_bfd_error_handler)
+               (_("%B: relocation %s against `%s' can not be used when making "
+                  "a shared object; recompile with -fPIC"),
+                abfd, elfNN_aarch64_howto_table[howto_index].name,
+                (h) ? h->root.root.string : "a local symbol");
+             bfd_set_error (bfd_error_bad_value);
+             return FALSE;
+           }
+
        case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
        case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
        case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
@@ -5350,8 +6547,8 @@ elfNN_aarch64_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED,
 
 static bfd_boolean
 aarch64_elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
-                          asection *section,
                           asymbol **symbols,
+                          asection *section,
                           bfd_vma offset,
                           const char **filename_ptr,
                           const char **functionname_ptr)
@@ -5410,32 +6607,33 @@ aarch64_elf_find_function (bfd *abfd ATTRIBUTE_UNUSED,
 
 static bfd_boolean
 elfNN_aarch64_find_nearest_line (bfd *abfd,
-                                asection *section,
                                 asymbol **symbols,
+                                asection *section,
                                 bfd_vma offset,
                                 const char **filename_ptr,
                                 const char **functionname_ptr,
-                                unsigned int *line_ptr)
+                                unsigned int *line_ptr,
+                                unsigned int *discriminator_ptr)
 {
   bfd_boolean found = FALSE;
 
-  /* We skip _bfd_dwarf1_find_nearest_line since no known AArch64
-     toolchain uses it.  */
-
-  if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections,
-                                    section, symbols, offset,
+  if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset,
                                     filename_ptr, functionname_ptr,
-                                    line_ptr, NULL, 0,
+                                    line_ptr, discriminator_ptr,
+                                    dwarf_debug_sections, 0,
                                     &elf_tdata (abfd)->dwarf2_find_line_info))
     {
       if (!*functionname_ptr)
-       aarch64_elf_find_function (abfd, section, symbols, offset,
+       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,
@@ -5448,7 +6646,7 @@ elfNN_aarch64_find_nearest_line (bfd *abfd,
   if (symbols == NULL)
     return FALSE;
 
-  if (!aarch64_elf_find_function (abfd, section, symbols, offset,
+  if (!aarch64_elf_find_function (abfd, symbols, section, offset,
                                  filename_ptr, functionname_ptr))
     return FALSE;
 
@@ -5500,17 +6698,6 @@ elfNN_aarch64_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSE
     }
 }
 
-/* Set the right machine number for an AArch64 ELF file.  */
-
-static bfd_boolean
-elfNN_aarch64_section_flags (flagword *flags, const Elf_Internal_Shdr *hdr)
-{
-  if (hdr->sh_type == SHT_NOTE)
-    *flags |= SEC_LINK_ONCE | SEC_LINK_DUPLICATES_SAME_CONTENTS;
-
-  return TRUE;
-}
-
 /* Handle an AArch64 specific section when reading an object file.  This is
    called when bfd_section_from_shdr finds a section with an unknown
    type.  */
@@ -5755,8 +6942,23 @@ aarch64_map_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
       if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_DATA, addr + 16))
        return FALSE;
       break;
+    case aarch64_stub_erratum_835769_veneer:
+      if (!elfNN_aarch64_output_stub_sym (osi, stub_name, addr,
+                                         sizeof (aarch64_erratum_835769_stub)))
+       return FALSE;
+      if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+       return FALSE;
+      break;
+    case aarch64_stub_erratum_843419_veneer:
+      if (!elfNN_aarch64_output_stub_sym (osi, stub_name, addr,
+                                         sizeof (aarch64_erratum_843419_stub)))
+       return FALSE;
+      if (!elfNN_aarch64_output_map_sym (osi, AARCH64_MAP_INSN, addr))
+       return FALSE;
+      break;
+
     default:
-      BFD_FAIL ();
+      abort ();
     }
 
   return TRUE;
@@ -5800,6 +7002,10 @@ elfNN_aarch64_output_arch_local_syms (bfd *output_bfd,
          osi.sec_shndx = _bfd_elf_section_from_bfd_section
            (output_bfd, osi.sec->output_section);
 
+         /* The first instruction in a stub is always a branch.  */
+         if (!elfNN_aarch64_output_map_sym (&osi, AARCH64_MAP_INSN, 0))
+           return FALSE;
+
          bfd_hash_traverse (&htab->stub_hash_table, aarch64_map_one_stub,
                             &osi);
        }
@@ -6303,7 +7509,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
 
   /* Set up .got offsets for local syms, and space for local dynamic
      relocs.  */
-  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+  for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
     {
       struct elf_aarch64_local_symbol *locals = NULL;
       Elf_Internal_Shdr *symtab_hdr;
@@ -6366,7 +7572,8 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                  htab->root.sgot->size += GOT_ENTRY_SIZE * 2;
                }
 
-             if (got_type & GOT_TLS_IE)
+             if (got_type & GOT_TLS_IE
+                 || got_type & GOT_NORMAL)
                {
                  locals[i].got_offset = htab->root.sgot->size;
                  htab->root.sgot->size += GOT_ENTRY_SIZE;
@@ -6376,10 +7583,6 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                {
                }
 
-             if (got_type == GOT_NORMAL)
-               {
-               }
-
              if (info->shared)
                {
                  if (got_type & GOT_TLSDESC_GD)
@@ -6392,7 +7595,8 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
                  if (got_type & GOT_TLS_GD)
                    htab->root.srelgot->size += RELOC_SIZE (htab) * 2;
 
-                 if (got_type & GOT_TLS_IE)
+                 if (got_type & GOT_TLS_IE
+                     || got_type & GOT_NORMAL)
                    htab->root.srelgot->size += RELOC_SIZE (htab);
                }
            }
@@ -6450,6 +7654,16 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
        }
     }
 
+  /* Init mapping symbols information to use later to distingush between
+     code and data while scanning for errata.  */
+  if (htab->fix_erratum_835769 || htab->fix_erratum_843419)
+    for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
+      {
+       if (!is_aarch64_elf (ibfd))
+         continue;
+       bfd_elfNN_aarch64_init_maps (ibfd);
+      }
+
   /* We now have determined the sizes of the various dynamic sections.
      Allocate memory for them.  */
   relocs = FALSE;
@@ -6627,7 +7841,7 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
 
   plt_entry = plt->contents + h->plt.offset;
   plt_entry_address = plt->output_section->vma
-    + plt->output_section->output_offset + h->plt.offset;
+    + plt->output_offset + h->plt.offset;
   gotplt_entry_address = gotplt->output_section->vma +
     gotplt->output_offset + got_offset;
 
@@ -6776,11 +7990,18 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
       if (!h->def_regular)
        {
          /* Mark the symbol as undefined, rather than as defined in
-            the .plt section.  Leave the value alone.  This is a clue
-            for the dynamic linker, to make function pointer
-            comparisons work between an application and shared
-            library.  */
+            the .plt section.  */
          sym->st_shndx = SHN_UNDEF;
+         /* If the symbol is weak we need to clear the value.
+            Otherwise, the PLT entry would provide a definition for
+            the symbol even if the symbol wasn't defined anywhere,
+            and so the symbol would never be NULL.  Leave the value if
+            there were any relocations where pointer equality matters
+            (this is a clue for the dynamic linker, to make function
+            pointer comparisons work between an application and shared
+            library).  */
+         if (!h->ref_regular_nonweak || !h->pointer_equality_needed)
+           sym->st_value = 0;
        }
     }
 
@@ -6934,7 +8155,7 @@ elfNN_aarch64_init_small_plt0_entry (bfd *output_bfd ATTRIBUTE_UNUSED,
                  + GOT_ENTRY_SIZE * 2);
 
   plt_base = htab->root.splt->output_section->vma +
-    htab->root.splt->output_section->output_offset;
+    htab->root.splt->output_offset;
 
   /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
      ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
@@ -6994,7 +8215,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
              break;
 
            case DT_PLTRELSZ:
-             s = htab->root.srelplt->output_section;
+             s = htab->root.srelplt;
              dyn.d_un.d_val = s->size;
              break;
 
@@ -7008,7 +8229,7 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
                 about changing the DT_RELA entry.  */
              if (htab->root.srelplt != NULL)
                {
-                 s = htab->root.srelplt->output_section;
+                 s = htab->root.srelplt;
                  dyn.d_un.d_val -= s->size;
                }
              break;
@@ -7210,9 +8431,6 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define bfd_elfNN_bfd_link_hash_table_create    \
   elfNN_aarch64_link_hash_table_create
 
-#define bfd_elfNN_bfd_link_hash_table_free      \
-  elfNN_aarch64_hash_table_free
-
 #define bfd_elfNN_bfd_merge_private_bfd_data   \
   elfNN_aarch64_merge_private_bfd_data
 
@@ -7287,9 +8505,6 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_reloc_type_class           \
   elfNN_aarch64_reloc_type_class
 
-#define elf_backend_section_flags              \
-  elfNN_aarch64_section_flags
-
 #define elf_backend_section_from_shdr          \
   elfNN_aarch64_section_from_shdr
 
@@ -7299,6 +8514,9 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_size_info                  \
   elfNN_aarch64_size_info
 
+#define elf_backend_write_section              \
+  elfNN_aarch64_write_section
+
 #define elf_backend_can_refcount       1
 #define elf_backend_can_gc_sections    1
 #define elf_backend_plt_readonly       1
@@ -7307,6 +8525,7 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define elf_backend_may_use_rel_p      0
 #define elf_backend_may_use_rela_p     1
 #define elf_backend_default_use_rela_p 1
+#define elf_backend_rela_normal        1
 #define elf_backend_got_header_size (GOT_ENTRY_SIZE * 3)
 #define elf_backend_default_execstack  0
 
This page took 0.05011 seconds and 4 git commands to generate.